OmniScrapeOmniScrape
ProductsSolutionsGuidesDocs ↗PricingAbout
← All guides
Anti-Bot Bypass

Cloudflare Error 1020: Why No Solver Will Fix It

Your request comes back with "Access denied — error code 1020", so you enable the solver, raise the timeout, and retry. Nothing changes. You add a browser render. Still nothing. The instinct is to escalate harder, and with 1020 that instinct is exactly backwards.

1020 is not a challenge you failed. It is a firewall rule that matched, and a matched rule has no solve path — there is nothing to compute, no widget to clear, no cookie to earn. The fix is to stop matching the rule, which means identifying which property of your request triggered it. This guide covers how to read Cloudflare's error codes as a diagnostic, and what to actually change.

On this page

1. A rule match, not a bot score2. Reading the code as a diagnostic3. Working out which property triggered it4. What actually resolves a 10205. Configuring OmniScrape against a 10206. FAQ

1.A rule match, not a bot score

Cloudflare gives zone operators a rules engine: block or challenge requests matching conditions on country, ASN, IP range, URI path, HTTP method, header presence, User-Agent string, and more. When a request matches a rule whose action is Block, the edge returns 1020. The decision is deterministic and happens before any bot-scoring or challenge logic gets a say.

This is the crucial difference from the challenge codes. A challenge means "prove you are a browser" and has a defined path to success. A 1020 means "a human wrote a rule that excludes requests like yours", and the only way through is to stop being a request like yours. Retrying identical requests with a heavier engine burns budget and changes nothing.

It also means 1020 is often not about bot detection at all. Plenty of 1020s are geo-blocks, deny-lists for cloud ASNs, or rules protecting a specific path such as /admin or /api. Reading it as "my scraper looks like a bot" sends you optimising fingerprints when the actual trigger was your egress country.

2.Reading the code as a diagnostic

Cloudflare's numeric codes narrow the cause considerably, and the first useful step is simply reading which one you got rather than treating every block as the same event. Each points at a different layer of the stack, and therefore at a different fix.

Note that several of these are not scraper-specific at all — a browser on a residential connection would hit the same wall for 1009 or 1020, because the rule does not care what client you are running.

  • 1020 — a WAF or firewall rule matched and blocked. No solve path; change the matching property.
  • 1015 — rate limited. Reduce concurrency and request rate; wait out the window.
  • 1010 — the client's browser signature was rejected. Common with automation-flagged headless stacks.
  • 1009 — the request's country is not permitted for this zone. Change proxy country.
  • 1006 / 1007 / 1008 — the specific IP is banned. Rotate egress.

3.Working out which property triggered it

Change one variable at a time. The properties worth testing, roughly in order of how often they turn out to be the cause, are egress country, egress ASN type, the URI path, the HTTP method, the User-Agent string, and the presence or absence of headers a browser would always send. Bisecting is fast because most zones have only a handful of custom rules.

Start with the path. If the homepage returns content and /api/v2/products returns 1020, the rule is path-scoped and no amount of fingerprint work will help — the endpoint is simply not meant to be reached directly. The same test distinguishes a site-wide block from a targeted one in a single pair of requests.

Then test egress. Fetch the same URL through a residential IP in the country the site actually serves. If a datacenter IP gets 1020 and a residential IP in-market gets content, the rule is an ASN or geo rule and your fix is egress selection, not engine selection. Keep the cf-ray value from blocked responses; it is the identifier a site operator would need if you ever have grounds to ask them about the rule.

Isolate the matching property before changing engines
bash
12345678910# Bisect the rule: same client, three variables changed one at a time.
# 1. Is it path-scoped?
curl -s -o /dev/null -w '%{http_code}\n' https://target.example.com/
curl -s -o /dev/null -w '%{http_code}\n' https://target.example.com/api/v2/products

# 2. Is it method-scoped?
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://target.example.com/api/v2/products

# 3. Keep the cf-ray from any blocked response for later reference.
curl -sI https://target.example.com/api/v2/products | grep -i '^cf-ray'

4.What actually resolves a 1020

Egress is the highest-yield change. Cloud ASNs are the most commonly deny-listed category on the internet, and a residential IP in the market the site serves removes both the ASN rule and the geo rule in one move. Match the country to the content you expect rather than defaulting to US for a European retailer.

Header hygiene is the second. Rules that match on a missing or obviously synthetic User-Agent, or on the absence of the Sec-Fetch family, are cheap for operators to write and common in practice. A browser-grade request carries a coherent header set; a hand-assembled one usually does not, and the gap is easy to write a rule against.

If the rule is genuinely path-scoped, respect it. A 1020 on an internal API endpoint is an operator telling you that endpoint is not public, and routing around it is a different kind of decision from clearing a bot challenge — one with terms-of-service and legal dimensions that are yours to weigh, not a technical problem to escalate past.

5.Configuring OmniScrape against a 1020

The parameter that matters here is proxy, not enable_solver. Set residential egress in the target's market and let the request go through the normal auto path. Because there is no challenge to clear, forcing js_rendering adds cost and latency without improving the outcome.

Read data.status_code and the body rather than assuming the wrapper hid a failure. When the origin's edge returns a 1020 page, that is the response — a successful unlock of a blocked page still contains the block. Check for "error code: 1020" in the body as an explicit condition in your validation layer so these do not silently enter your dataset as short pages.

If a country change resolves it, pin it. Passing session_id alongside a working proxy keeps subsequent requests on the same egress rather than rediscovering the block on the next rotation.

Change egress, not engine
bash
12345678910curl -X POST https://api.omniscrape.io/v1/scrape \
  -H "Content-Type: application/json" \
  -H "X-API-Key: ${OMNISCRAPE_KEY}" \
  -d '{
    "url": "https://target.example.com/catalog",
    "mode": "auto",
    "proxy": "residential:de:sticky",
    "session_id": "de-catalog-01",
    "output_format": "html"
  }'

Frequently asked questions

Why does enabling the solver not fix error 1020?

Because there is no challenge to solve. 1020 means a firewall rule matched and the edge blocked the request outright, before any bot-scoring or challenge logic runs. Solvers clear challenges; they cannot un-match a rule.

What is the difference between 1020 and 1015?

1015 is rate limiting — you sent too much, too fast, and backing off resolves it. 1020 is a rule match, which does not decay with time; retrying the same request an hour later returns the same block unless something about the request changed.

I get 1020 on one path but the homepage loads fine.

That is a path-scoped rule, and it is the most common shape of 1020. Fingerprint and engine changes will not help. Treat it as the operator declaring that endpoint non-public, and weigh whether routing around it is something you have grounds to do.

Does a residential proxy fix 1020?

It fixes the large subset caused by ASN deny-lists and country rules, which together account for most 1020s scrapers encounter. It does nothing for path-, method-, or header-scoped rules, which is why bisecting before buying is worth the two minutes.

Should I keep retrying a 1020?

No. Identical retries produce identical results and consume budget. Change exactly one property — country first, then path, then headers — and retry once per change until you find the trigger.

Related guides

  • How to Bypass Cloudflare When Web Scraping
  • cf_clearance Cookie: Why Copying It Never Works
  • Web Scraping Without Getting Blocked
  • Rotating Proxies for Web Scraping: Policies, Session Binding, and Geo Pools
  • How to Bypass Cloudflare in Python
  • How to Bypass Cloudflare in Node.js

Ready to scrape without blocks?

Published unit rates, clear plan limits, and billing tied to successful work. No hidden fees and no guessing what a scrape will cost. Free trial credit on signup. No credit card required.

Ready to get started?

Start scraping protected sites today. No credit card required.

OmniScrapeOmniScrape

Web scraping infrastructure for developers. One API call to bypass any protection.

All systems operational

Payments accepted

Credit / Debit CardVisaMastercardCryptoBTCUSDTETH50+ coins

Product

  • Web Unlocker
  • Browser-as-a-Service
  • Residential Proxies
  • Pricing

Developers

  • API Reference ↗
  • Quickstart ↗
  • All Guides
  • Use Cases
  • Status

Company

  • About
  • Contact

Legal

  • Privacy Policy
  • Terms of Service
  • Refund Policy
  • Cookie Policy
  • Acceptable Use

Popular guides

  • How to Bypass Cloudflare When Web Scraping
  • How to Bypass DataDome When Web Scraping
  • How to Bypass Akamai Bot Manager When Web Scraping
  • How to Bypass F5 BIG-IP Bot Defense When Web Scraping
  • Web Scraping API: Endpoint, Modes, Output Formats & Integration Patterns
  • Web Scraping with Python
  • Scrape JavaScript-Rendered Pages: SPAs, Hydration, and Hidden APIs
  • Web Scraping Without Getting Blocked
  • Headless Browser Scraping: When to Use It and How to Do It Right
  • Rotating Proxies for Web Scraping: Policies, Session Binding, and Geo Pools
  • OmniScrape vs ScrapingBee
  • OmniScrape vs ZenRows
Browse all guides →

OmniScrape is a product of PT Data Digital Grup. Copyright ©2026.

PrivacyTermsRefundsAcceptable Use