You sent a request, and instead of the page you got a Cloudflare page that says "Error 1020: Access Denied." The site loads fine in your browser, but your script, your scraper, or even your own backend keeps getting bounced. It feels arbitrary, but it isn't: 1020 is a specific, deterministic outcome of a firewall rule, and once you know which rule fired, you usually know how to fix it.
This guide explains exactly what error 1020 means, the handful of things that trigger it, how to diagnose which one is hitting you, and the concrete fixes for legitimate automation. It is also honest about the cases a solver cannot help with. If a site deliberately blocks your country or IP range, no tool changes that, and pretending otherwise wastes your time.
What "Error 1020: Access Denied" actually means
Error 1020 means a Cloudflare WAF (Web Application Firewall) rule on the target site evaluated your request and matched a block rule. Cloudflare ran your request against the site owner's firewall configuration, something matched, and the request was refused before it ever reached the origin server. The 1020 code is Cloudflare's generic label for "a custom firewall/WAF rule blocked this."
This is an important distinction from a captcha or a challenge. A challenge says "prove you're a browser and you can continue." A 1020 says "a rule decided you don't get in," full stop. There is no widget to solve and no token to fetch. Whether you can get past it depends entirely on which rule fired and why it matched your request.
Two requests can both return 1020 for completely different reasons: one because the rule keyed on a high bot score, another because the rule blocks an entire country. The first is fixable from the client side; the second is not. So the first job is always diagnosis, not brute force.
What triggers a 1020
WAF rules are configured per site, so the exact trigger varies, but in practice a 1020 against automation almost always comes from one of these:
- IP reputation or ASN: the rule blocks IPs with a poor reputation score, or blocks the autonomous system numbers (ASNs) belonging to cloud and hosting providers. Datacenter IPs from AWS, GCP, Hetzner, OVH and friends trip this fast.
- Geo / country block: the rule denies traffic from specific countries or regions. If your proxy exits in a blocked country, you get 1020 no matter what your headers look like.
- Blocked or missing User-Agent: rules often block empty User-Agents, obvious library defaults like python-requests/2.x or Go-http-client, or known scraper strings.
- Referer / hotlink rule: a rule that requires requests to a resource come from the site's own domain. A direct hit with no (or a foreign) Referer header gets blocked.
- Exposed automation signals: navigator.webdriver, headless browser tells, or inconsistent client hints can match a managed rule designed to catch bots.
- Missing or invalid cf_clearance: when the site runs a challenge and the rule expects a valid clearance cookie, a request without one (or with an expired/mismatched one) gets denied.
- High bot score: Cloudflare assigns each request a bot score, and a rule can block everything below a threshold. This is the trigger a solver can actually influence, because it is about how bot-like your request looks.
How to diagnose which rule fired
Before changing anything, figure out which category you're in, because the fixes are different and some are impossible. Work through it in order:
First, swap your exit IP. Try the same request from a clean residential IP in a different country. If a datacenter IP gets 1020 and a residential IP in your home country sails through, you were caught by an IP/ASN or geo rule. If both fail identically, IP is probably not the whole story.
Second, test from a real browser through the same proxy. If your browser also gets 1020 on that IP and region, it is an IP, ASN, or geo block, not a bot-detection problem, and no header or fingerprint tweak will help. If the browser passes but your script fails, you're tripping a User-Agent, header, fingerprint, or bot-score rule.
Third, look at what you're sending. A missing Referer on a hotlink-protected resource, a default library User-Agent, or no cf_clearance on a challenged path each produce a clean, reproducible 1020 that disappears the moment you fix that one thing.
How to fix a 1020 for legitimate automation
Once you know it's a bot-detection or header rule and not a deliberate geo/IP ban, the fixes are straightforward and stackable. Apply them in order of effort:
- Use clean residential proxies. Datacenter IPs trip IP/ASN rules almost immediately. Rotating residential or mobile IPs carry far higher trust and clear most reputation-based 1020s.
- Send realistic, consistent browser headers. A full, coherent set (User-Agent, Accept, Accept-Language, Accept-Encoding, sec-ch-ua, sec-ch-ua-platform) in browser-like order, with a User-Agent that matches the rest, beats a sparse library default.
- Match the User-Agent to the rest of the request. A Chrome User-Agent paired with sec-ch-ua client hints that claim Firefox is an instant tell. Keep the whole story consistent.
- Get a valid cf_clearance by actually passing the challenge. If the rule depends on the clearance cookie, you need a real one earned by completing the challenge, not a forged value.
- Avoid known-bad fingerprints. Don't leak navigator.webdriver, don't run an obviously headless profile, and don't reuse a TLS/JA3 fingerprint that's been flagged.
- Slow down. Aggressive request rates raise your bot score and can flip a borderline request into a blocked one. Add jitter and respect sane concurrency limits.
1020 vs 1015, 1010, and 1012
It's easy to lump every Cloudflare error code together, but they mean different things and call for different responses. Don't apply a 1020 fix to a 1015 problem.
Error 1015 is rate limiting. You sent too many requests too fast and Cloudflare is throttling you, usually temporarily. The fix is to slow down, add backoff, and spread load across IPs, not to change your fingerprint. If your 1020 is really a disguised rate problem, headers won't save you.
Error 1010 means Cloudflare blocked the request because your browser's signature was flagged, typically associated with automation tooling and detected browser fingerprints. Error 1012 is "Access Denied" tied to a Cloudflare security rule as well, often surfacing when the site owner has restricted access. The practical takeaway: 1010 points you at your fingerprint, 1015 at your request rate, and 1020 at a custom firewall rule whose specific trigger you still have to identify.
Be honest: when a 1020 is not something you can solve
This part matters because it saves you from burning hours on the wrong problem. A 1020 from an intentional rule is not a captcha, and no solver, no proxy rotation, and no header tuning will change a site owner's deliberate decision to block you.
If the site explicitly blocks your country, your entire IP range, or your ASN, that is a policy choice on their end. The only thing that changes the outcome is changing where your request comes from, and even then only if they haven't blocked your new location too. A solver doesn't bypass a geo block; it was never designed to, and any vendor claiming otherwise is overselling.
Where a solver genuinely helps is the bot-score path of a 1020. When the firewall rule is keyed on "this request looks automated," the fix is to make the request look like a real, challenge-passing browser, which means a clean fingerprint, a valid cf_clearance, and a matching User-Agent. That is a tractable problem, and it's the one worth automating.
Where NSLSolver fits, and how to apply cf_clearance
If your diagnosis lands on the bot-score path, where the site runs a Cloudflare managed/JS challenge and the rule blocks anything without a valid clearance, NSLSolver's Challenge endpoint clears it for you and returns the two artifacts your normal session needs: a cf_clearance cookie and the matching user_agent. You attach both to a requests session and keep going at native HTTP speed, no headless browser in your pipeline.
NSLSolver solves Cloudflare Turnstile, Cloudflare Challenge (managed/JS), and Kasada. It does not solve geo blocks, IP-reputation bans, or non-Cloudflare systems, because those aren't challenges. Use it specifically when a 1020 is being driven by the bot-detection path and a real cf_clearance is what's missing.
The contract is small. POST to https://api.nslsolver.com/solve with your X-API-Key. The response cookies field is a dict keyed by cf_clearance, and the user agent comes back as user_agent (snake_case). The User-Agent you send afterward must match the one bound to the cookie, so always use the value the API returns.
import requests
API_KEY = "nsl_YOUR_API_KEY"
TARGET = "https://target-site.com"
# 1) Ask NSLSolver to pass the Cloudflare challenge behind the 1020 rule
resp = requests.post(
"https://api.nslsolver.com/solve",
headers={"X-API-Key": API_KEY},
json={
"type": "challenge",
"url": TARGET,
"proxy": "http://user:pass@host:port", # use a clean residential proxy
},
timeout=120,
)
data = resp.json()
# 2) Apply the cf_clearance cookie + matching user_agent to a session
session = requests.Session()
session.cookies.update(data["cookies"]) # dict keyed by cf_clearance
session.headers["User-Agent"] = data["user_agent"]
# 3) Requests now carry a valid clearance and stop tripping the bot-score rule
page = session.get(TARGET)
print(page.status_code) # 200 instead of 1020
print(page.text[:500])