The 403 Tax: What Anti-Bot Protection Really Does to Your Scraping Bill
A cost-first teardown of scraping APIs under Cloudflare and Turnstile pressure: credit multipliers, retry amplification, and the only metric that survives production.
Price your own targets, not the sticker price
Start with a free trial, run the 200-URL pilot from this teardown, and measure cost per 1,000 usable pages before you commit to a plan.
ScraperAPI ↗Smartproxy / Decodo ↗Affiliate links. See the disclosure above.
The crawl finished at 06:00. The job log says 100,000 requests. The dataset has 68,000 usable rows, 22,000 challenge pages, and 10,000 timeouts. The invoice counts 100,000 requests plus every retry, every JavaScript render, and every premium-proxy attempt.
That gap between requests sent and pages usable is the 403 tax. It is invisible on a pricing page, and it is the number that decides whether a scraping API is cheap or expensive.
This is a cost-first teardown of the problem. I use the normalized plan inputs published on scrape.mybskm.top, walk through the arithmetic, and then show a two-hour pilot that produces a better buying decision than any vendor comparison table.
The invoice counts attempts, not answers
A scraping API is not a bandwidth pipe. It is a request orchestrator: it chooses an IP, opens a TLS session, may execute JavaScript, may solve or wait out a challenge, and may retry. Every one of those steps can consume a credit.
That is why two providers can both advertise "$49 per month" and produce very different bills. The useful unit is not the request. It is the usable page: a response that contains the fields your pipeline needs, at the time you need them.
A 200 response with a Cloudflare interstitial is a failure. A 403 with a valid cached copy may still be a success if your pipeline is allowed to use the cache. A timeout after 30 seconds may have consumed a credit even though it produced nothing. Your accounting has to follow the output, not the status code.
A residential IP is not a Turnstile pass
Cloudflare, DataDome, and Akamai do not make a single decision. They combine signals:
- IP reputation and ASN type.
- TLS fingerprint and HTTP/2 settings.
- Header order and browser fingerprint.
- Cookie and challenge-token state.
- Request rate, navigation pattern, and mouse or keyboard behavior.
A residential IP helps with the first signal. It does not automatically produce a valid Turnstile token. Turnstile requires JavaScript execution in a browser-like environment, and that execution is usually billed at a higher credit multiplier. DataDome and Akamai apply similar layered checks.
This is the practical reason "just buy residential proxies" often disappoints. You can move the IP and still fail the browser and token checks. A managed scraping API bundles the browser, the proxy, and the retry logic, but it charges for all three.
The credit multiplier is the real price list
The public calculator normalizes four providers to a common baseline. The inputs below were observed on 2026-10-17. They are planning baselines, not fresh vendor quotes, and the site explicitly labels them that way.
| API (baseline input) | Plan | Included credits | Cost / credit | 10k @ 1 credit | 10k @ 5 credits | 10k @ 25 credits |
|---|---|---|---|---|---|---|
| ZenRows | $49 | 250,000 | $0.000196 | $1.96 | $9.80 | $49.00 |
| ScrapingBee | $49 | 150,000 | $0.000327 | $3.27 | $16.33 | $81.67 |
| ScraperAPI | $49 | 100,000 | $0.000490 | $4.90 | $24.50 | $122.50 |
| Crawlbase | $29 | not specified | n/a | n/a | n/a | n/a |
The formula is simple:
cost per request = plan price / included credits * credits per request
At one credit per request, the difference between the cheapest and most expensive normalized option is $2.94 per 10,000 requests. At 25 credits per request, it is $73.50. The multiplier, not the plan price, controls the spread.
Crawlbase is deliberately left as n/a. Its supplied baseline does not state the included paid request volume, so the $2.90 per 10,000 estimate cannot be converted into a per-credit rate. Treating it as comparable would be a spreadsheet error dressed up as analysis.
Retry amplification: the line item finance never sees
Suppose you need 100,000 URLs. Thirty percent hit a challenge or a 403. A naive retry policy tries each failed URL three times. You now bill:
70,000 non-challenged attempts + 30,000 challenged URLs * 3 attempts = 160,000 billed attempts
If every attempt costs one credit, the allocated cost at the normalized rates is:
| Billing assumption | Billed credits | ZenRows | ScrapingBee | ScraperAPI |
|---|---|---|---|---|
| 1 credit per attempt | 160,000 | $31.36 | $52.27 | $78.40 |
| 5 credits per challenged retry | 520,000 | $101.92 | $169.87 | $254.80 |
The second row is the important one. It assumes 70,000 clean requests at one credit and 30,000 challenged requests at three attempts times five credits. That is 520,000 credits for a job that "only" had 100,000 URLs.
These are allocated plan costs, not necessarily the provider's overage price. Overage rates can be higher, and plans may throttle or block before overage. The point is directional: a retry policy without a credit budget is an open-ended invoice.
Cost per 1,000 usable pages
The metric to put in the budget is:
cost per 1,000 usable pages =
(cost per credit * credits per attempt) / usable yield * 1,000
Using the normalized rates and an explicit 70% yield assumption:
| API | $ / 1k attempts (1 credit) | $ / 1k usable at 70%, 1 credit | $ / 1k usable at 70%, 5 credits |
|---|---|---|---|
| ZenRows | $0.196 | $0.280 | $1.400 |
| ScrapingBee | $0.327 | $0.467 | $2.333 |
| ScraperAPI | $0.490 | $0.700 | $3.500 |
Seventy percent is an assumption, not a measurement. It is there to make the arithmetic visible. If the supplied baseline success rates of 98.5%, 97.8%, and 96.5% held, the one-credit numbers would be $0.199, $0.334, and $0.508 per 1,000 usable pages. Those rates are supplied planning inputs, not independent target measurements, so your own pilot still decides.
The 5-credit column is the part most teams miss. A provider with a lower per-credit price can lose on a target that forces JavaScript rendering on every request. The opposite is also true: a provider with a higher per-credit price can win if it avoids retries and returns clean data on the first attempt.
A two-hour pilot that beats any comparison table
You do not need a 10,000-request benchmark to make a good decision. You need a representative sample, a definition of usable, and honest accounting.
- Pick 200 URLs. Stratify by template, not by random pages. Include the pages that produce the most revenue or the most support tickets.
- Define usable before you run. A product page is usable only if the price, currency, and availability fields are present. A listing page is usable only if it returns the expected number of items. Hash the relevant fragment, not the whole HTML, so rotating ads do not create false negatives.
- Run three times. Morning, midday, and evening in the target geography. Use the same session settings and the same timeout. Record status, latency, bytes, and credits consumed.
- Count retries as cost. If your client retries three times, the pilot must record three attempts. Otherwise the result is a demo, not an economic measurement.
- Compute the useful number. Cost per 1,000 usable pages, not cost per request. Add the engineering time spent on the integration.
A minimal standard-library probe looks like this:
import hashlib
import json
import time
import urllib.request
TARGET = "https://example.com/product/123"
MARKER = "Add to cart"
def probe(url):
request = urllib.request.Request(
url, headers={"User-Agent": "cost-pilot/1.0"})
started = time.perf_counter()
with urllib.request.urlopen(request, timeout=30) as response:
body = response.read()
status = response.status
return {
"status": status,
"seconds": round(time.perf_counter() - started, 3),
"usable": MARKER.encode() in body,
"sha256": hashlib.sha256(body).hexdigest()[:16],
}
print(json.dumps(probe(TARGET)))
Run that through your provider's endpoint and through a direct baseline. The direct baseline tells you what the target does without a proxy. The provider result tells you what you are buying. If the direct baseline is already 95% usable, a managed API may still be worth it for maintenance and IP rotation, but you should price it as an operational convenience, not as a magic bypass.
What I would do with a $49 budget
Start with the free trial, not the annual plan. Run the 200-URL pilot. Measure usable yield and credits per usable page. Then decide whether the problem is IP reputation, browser execution, or your own parser.
Three rules have saved me more money than any vendor comparison:
- Cache before you crawl. A page that has not changed does not need a new credit.
- Use the official API when one exists. It is usually cheaper, more stable, and less likely to trigger a challenge than scraping the HTML.
- Set a retry budget. If a URL fails three times, park it and alert. Infinite retries convert a temporary block into a permanent cost.
The conclusion that survives contact with production
The cheapest scraping API is not the one with the lowest sticker price. It is the one with the lowest cost per usable page at your target, your geography, and your required freshness.
That number depends on three variables you control: the credit multiplier of the request mode, the yield of the target, and the retry policy. A provider that looks 60% cheaper per credit can be 2.5x more expensive per usable page once rendering is included. A provider that looks expensive can win if it returns clean data on the first attempt.
Run the arithmetic before you run the invoice. The calculator and the underlying baseline are public:
- Scraping API cost calculator: scrape.mybskm.top
- Residential proxy economics: proxy.mybskm.top
- Methodology and data: GitHub repository
Disclosure: Some outbound links on this page are affiliate links. If you buy a service through them, I may earn a commission at no extra cost to you. The baseline figures are supplied planning inputs, not independently measured target results or current vendor quotes. Verify current pricing and terms with each provider before purchasing.
Data note: Normalized plan inputs observed 2026-10-17T12:39:14Z. Success rates and 10k estimates are supplied baselines, and performance was not independently measured. HTTP 200 is not proof of bypass success.
Price your own targets, not the sticker price
Start with a free trial, run the 200-URL pilot from this teardown, and measure cost per 1,000 usable pages before you commit to a plan.
ScraperAPI ↗Smartproxy / Decodo ↗Affiliate links. See the disclosure above.