How to scrape Akamai-protected sites
Akamai Bot Manager sits in front of many large retail and travel sites. A plain request to one of them usually gets an "Access Denied" page, an empty response or a page that never finishes loading its data. StealthASF gets the real page back. In our production tests on 8 October 2026, Home Depot passed in stealth mode, and Nike, Lowe's and Home Depot all returned the real page with its real title in Ultra mode. This guide uses a Lowe's category page as the example target.
1. Pick the mode
The API field engine selects the request mode. For an Akamai site you have two good starting points. auto sends a plain request first and steps up to protected mode (stealth, 25 credits) when it detects a block, and it remembers sites that needed protection so later requests start there. ultra is our strongest mode at 50 credits and goes straight to the configuration that passed every Akamai site in our tests. Use auto when you want the lowest cost per page and ultra when you want the first request to count.
2. Send a first request with curl
Create an API key in your dashboard after verifying your email, then set STEALTHASF_API_KEY in your shell. Keep the key out of source control. The request below asks for the page in Ultra mode with text extraction, which is the quickest way to see whether you received real content.
curl --max-time 600 "https://stealthasf.com/v1/scrape" \
-H "x-api-key: $STEALTHASF_API_KEY" \
-H "content-type: application/json" \
--data-raw '{"url":"https://www.lowes.com/c/Tools","engine":"ultra","extract":"text"}'The endpoint accepts JSON and authenticates with the x-api-key header. The 600-second client timeout leaves room for slow pages.
3. Check that you got the real page
The response carries two statuses. The HTTP status of the API call tells you whether StealthASF accepted and completed the request. The status field inside the JSON is the target page's own status. A real page from an Akamai site comes back with status 200, the site's normal title in html and product names, prices or headings in the extracted text. An Akamai block page is short and says "Access Denied" with a reference number. When StealthASF detects a block it returns HTTP 422 and charges nothing.
The engine field tells you which mode produced the result. Save it with your results, because it decides the charge: a stealth request can escalate to Ultra when a site needs it.
4. Move the request into Python
This example uses only the Python standard library. It stops on an API error instead of treating the error body as page content. In a real job, also catch connection errors and timeouts, keep the job_id for each request, and check for a field you expect, such as a product name, before you store anything.
import json
import os
from urllib.error import HTTPError
from urllib.request import Request, urlopen
payload = {
"url": "https://www.lowes.com/c/Tools",
"engine": "ultra",
"extract": "text"
}
request = Request(
"https://stealthasf.com/v1/scrape",
data=json.dumps(payload).encode("utf-8"),
headers={
"x-api-key": os.environ["STEALTHASF_API_KEY"],
"content-type": "application/json",
},
method="POST",
)
try:
with urlopen(request, timeout=600) as response:
result = json.load(response)
except HTTPError as error:
detail = error.read().decode("utf-8")
raise SystemExit(f"API error {error.code}: {detail}")
print("Target status:", result["status"])
print("Credits:", result["credits_charged"])
print(result.get("data"))To pull structured fields instead of text, set extract to links for every link with its text, meta for the title, description and Open Graph tags, or table for the first HTML table. The full HTML is always in html if you prefer your own parser. When the page loads its data from its own JSON endpoint, the response can include discovered_api with the endpoint details.
5. Budget the credits
A stealth request costs 25 credits and an Ultra request 50. Both include the first 1 MB of transfer and add 10 credits per additional MB, rounded up to a whole credit, where MB means 1,048,576 bytes. A 3 MB Ultra request costs 70 credits. A solved CAPTCHA adds 25 credits. Blocked requests are never charged. On the Pro plan, 250,000 credits cover 10,000 stealth requests or 5,000 Ultra requests at the base rate. Read credits_charged on each response for the exact amount.
6. Scale up
Run a small batch of real URLs first: category pages, product pages and a search page if you need one. Store the target status, engine, credits and a sample of the extracted fields for each. If the same URL keeps returning 422, send support the job ID and we will look at it. Do not send your API key.
Then raise concurrency step by step within your plan limit. Respect Retry-After on a 429 response and give retries a fixed cap. Measure credits per complete record, not per HTTP 200, so a layout change that empties a field shows up quickly. If prices or stock depend on location, add a country field on Pro or Scale and keep it fixed across runs. See the Home Depot guide and the Nike guide for site-specific walkthroughs, the API reference for every field and the pricing page for plan allowances.