Cloudflare Error 1020 Access Denied: Causes and Fixes (2026)

The Scraper

Last updated on May 25, 2026

Bypass Methods

Error 1020 is different from the rest of Cloudflare's error family. It's not a rate limit. It's not a generic block. It's the site's owner telling Cloudflare: "if a request matches these conditions, deny it." You've matched. The page won't load.

The good news: 1020 is rule-based, which means it's deterministic. If you can figure out what triggered it, you can avoid the trigger. The bad news: the rules are invisible to you. You have to reason from the symptoms.

This post walks through what 1020 means, the common rule patterns sites deploy, and the working bypass strategies for 2026.


What Cloudflare Error 1020 Actually Means

When Cloudflare returns a 1020, it's because a request matched a WAF (Web Application Firewall) custom rule with the action set to Block. The rules are written by the site owner, not by Cloudflare's default ruleset, and can match on almost any request attribute:

  • IP address, ASN, or country

  • User-Agent string

  • Referer header

  • URL path or query string

  • HTTP method

  • Header presence or value

  • Combinations of any of the above

A typical 1020 rule looks something like: "Block if country is not US and path starts with /api/." Or: "Block if User-Agent contains python-requests." Or: "Block if ASN is in our list of known proxy ASNs."

Because the rules vary by site, the same setup can hit 1020 on one Cloudflare-protected site and sail through another. There's no universal fix, there's only diagnosis.


Step 1: Identify What Triggered the Block

Before changing your setup, isolate the variable. Run these tests in order, changing one thing at a time:

Test from a different IP. If you have access to a residential proxy or a friend's network, try the same request from there. If it works, your IP or ASN is on the blocklist. If it still fails, the rule isn't about your IP.

Test with a vanilla browser User-Agent. If you were using a custom UA or a scraper signature (python-requests/2.31, curl/8.5, scrapy/2.11), swap to a current Chrome User-Agent. Many 1020 rules block on UA substrings — a single header change can fix it.

Test from a different country. Geo-blocks are common, especially for sites in regulated industries (banking, gambling, streaming, government). If the site loads from a US IP but not from your home country, geo is the rule.

Test without query parameters. If you're hitting /search?q=...&page=..., try the bare path. Sites sometimes block on query parameter patterns that look like injection attempts or scraping ranges.

The order matters. Diagnosing wrong wastes time chasing the wrong fix.


Common Rule Patterns and Their Fixes

Once you know what triggered the block, the fix follows directly. The patterns below cover most 1020 cases.


IP-Based Blocks

The most common trigger. Cloudflare exposes IP reputation scores, and site owners often block any IP above a threshold. Datacenter ASNs, known VPN exit nodes, and Tor exits get blocked aggressively.

The fix: residential or mobile proxies. Datacenter proxies, even fresh ones, often share ASNs with known abuse sources. Residential IPs route through real ISPs and rarely trigger reputation-based rules.

If you're using a residential pool and still hitting 1020, the IPs are likely recycled, previous users got them flagged. A premium provider with cleaner pools, or a mobile proxy, fixes this.


Country and ASN Blocks

Site owners block by country for compliance, licensing, or anti-fraud reasons. The fix is straightforward: route through a proxy in a permitted country.

ASN blocks are harder to diagnose because you don't see the ASN unless you look it up. Use ipinfo.io/<your-ip> to check. If your proxy's ASN is something like AS14061 (DigitalOcean) or AS16509 (AWS), expect blocks on any site protecting against scrapers. Switch to a residential or mobile proxy with an ISP ASN like AS7922 (Comcast) or AS22394 (Cellco/Verizon).


User-Agent Blocks

Some of the laziest rules, and the most common. The site blocks any UA containing python, bot, crawler, scrapy, curl, or similar substrings.

The fix is one line:


import requests

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
}

response = requests.get("https://example.com", headers=headers)


Keep the full header set. Sites that check UA often also check for missing Accept-Language or Accept-Encoding, which are giveaways for non-browser clients.


Path or Query Pattern Blocks

If /api/ or /admin/ paths are blocked, the rule is gating access to endpoints the site owner doesn't want public. There's no header trick that bypasses this, the rule is explicit. You'll need to access the data through the rendered HTML pages instead, or accept that the endpoint is off-limits.

Query string blocks usually trigger on values that look like SQL injection or directory traversal. If you're passing user-controlled input, sanitize it. If you're hitting search endpoints with unusual parameters, try the values a browser would actually send.


Header Combination Blocks

The hardest to diagnose. The site blocks requests where some combination of headers looks wrong, say, Accept-Language: en from a country whose IPs usually send Accept-Language: fr. Or requests missing Sec-Fetch-* headers entirely, which is normal for requests and curl but never happens from a real Chrome.

The fix is to send the full set of headers a real browser sends. Either use a stealth library like curl_cffi (which mimics Chrome's TLS fingerprint as well as headers), or drive a real browser through Playwright.


from curl_cffi import requests

response = requests.get(
    "https://example.com",
    impersonate="chrome120",
)


curl_cffi ships with browser-impersonation profiles that handle both the TLS handshake and the header order — two things that requests gets wrong in ways Cloudflare can detect.


When the Rule Is Just Your IP Reputation

Sometimes you diagnose every variable and the only commonality is the IP. The IP is in a Cloudflare-shared abuse list, and no header change will fix that.

Your options:

  1. Rotate to a clean residential IP and don't reuse the dirty one.

  2. Use a premium residential provider that promises clean pools (worth verifying, ask for ASN distribution data).

  3. Switch to mobile, where carrier NAT makes per-IP reputation effectively meaningless.

This is the unglamorous answer, but it's often the right one. IP reputation is a slow-moving signal, once an IP is dirty, it stays dirty for weeks. Trying to clean it through other request changes is a losing game.


What Doesn't Work

A few popular suggestions that don't actually fix 1020:

  • Clearing cookies and cache. 1020 is server-side. Your local browser state doesn't matter.

  • Switching browsers. Same reason. The block is on your IP and request attributes, not your browser identity.

  • Waiting it out. Unlike rate limit errors, 1020 won't time out. The rule will keep blocking you until the site owner removes it or you change what your request looks like.

  • Generic VPNs. Most consumer VPNs use datacenter IPs that are already on Cloudflare's reputation lists. They may help with geo-blocks, but rarely with reputation-based 1020.


When to Give Up

If a site is enforcing 1020 aggressively against your specific use case, the site owner has made a deliberate choice to keep your traffic out. Bypassing it permanently is an arms race you'll lose against motivated security teams.

For legitimate use cases (your own account, your own data, research access), contact the site owner. For aggressive scraping where the owner clearly doesn't want you there, consider whether the data is worth the ongoing maintenance cost, and whether there's a sanctioned API or data partner you can use instead.


Wrapping Up

Error 1020 is a diagnosis problem, not a brute-force one. Isolate the variable, fix the matching trigger, and you're through. Most cases come down to one of: IP reputation, country block, User-Agent substring, or missing browser headers. Test in that order and you'll resolve the majority of 1020s without escalating to expensive stealth tooling.

Error 1020 is different from the rest of Cloudflare's error family. It's not a rate limit. It's not a generic block. It's the site's owner telling Cloudflare: "if a request matches these conditions, deny it." You've matched. The page won't load.

The good news: 1020 is rule-based, which means it's deterministic. If you can figure out what triggered it, you can avoid the trigger. The bad news: the rules are invisible to you. You have to reason from the symptoms.

This post walks through what 1020 means, the common rule patterns sites deploy, and the working bypass strategies for 2026.


What Cloudflare Error 1020 Actually Means

When Cloudflare returns a 1020, it's because a request matched a WAF (Web Application Firewall) custom rule with the action set to Block. The rules are written by the site owner, not by Cloudflare's default ruleset, and can match on almost any request attribute:

  • IP address, ASN, or country

  • User-Agent string

  • Referer header

  • URL path or query string

  • HTTP method

  • Header presence or value

  • Combinations of any of the above

A typical 1020 rule looks something like: "Block if country is not US and path starts with /api/." Or: "Block if User-Agent contains python-requests." Or: "Block if ASN is in our list of known proxy ASNs."

Because the rules vary by site, the same setup can hit 1020 on one Cloudflare-protected site and sail through another. There's no universal fix, there's only diagnosis.


Step 1: Identify What Triggered the Block

Before changing your setup, isolate the variable. Run these tests in order, changing one thing at a time:

Test from a different IP. If you have access to a residential proxy or a friend's network, try the same request from there. If it works, your IP or ASN is on the blocklist. If it still fails, the rule isn't about your IP.

Test with a vanilla browser User-Agent. If you were using a custom UA or a scraper signature (python-requests/2.31, curl/8.5, scrapy/2.11), swap to a current Chrome User-Agent. Many 1020 rules block on UA substrings — a single header change can fix it.

Test from a different country. Geo-blocks are common, especially for sites in regulated industries (banking, gambling, streaming, government). If the site loads from a US IP but not from your home country, geo is the rule.

Test without query parameters. If you're hitting /search?q=...&page=..., try the bare path. Sites sometimes block on query parameter patterns that look like injection attempts or scraping ranges.

The order matters. Diagnosing wrong wastes time chasing the wrong fix.


Common Rule Patterns and Their Fixes

Once you know what triggered the block, the fix follows directly. The patterns below cover most 1020 cases.


IP-Based Blocks

The most common trigger. Cloudflare exposes IP reputation scores, and site owners often block any IP above a threshold. Datacenter ASNs, known VPN exit nodes, and Tor exits get blocked aggressively.

The fix: residential or mobile proxies. Datacenter proxies, even fresh ones, often share ASNs with known abuse sources. Residential IPs route through real ISPs and rarely trigger reputation-based rules.

If you're using a residential pool and still hitting 1020, the IPs are likely recycled, previous users got them flagged. A premium provider with cleaner pools, or a mobile proxy, fixes this.


Country and ASN Blocks

Site owners block by country for compliance, licensing, or anti-fraud reasons. The fix is straightforward: route through a proxy in a permitted country.

ASN blocks are harder to diagnose because you don't see the ASN unless you look it up. Use ipinfo.io/<your-ip> to check. If your proxy's ASN is something like AS14061 (DigitalOcean) or AS16509 (AWS), expect blocks on any site protecting against scrapers. Switch to a residential or mobile proxy with an ISP ASN like AS7922 (Comcast) or AS22394 (Cellco/Verizon).


User-Agent Blocks

Some of the laziest rules, and the most common. The site blocks any UA containing python, bot, crawler, scrapy, curl, or similar substrings.

The fix is one line:


import requests

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
}

response = requests.get("https://example.com", headers=headers)


Keep the full header set. Sites that check UA often also check for missing Accept-Language or Accept-Encoding, which are giveaways for non-browser clients.


Path or Query Pattern Blocks

If /api/ or /admin/ paths are blocked, the rule is gating access to endpoints the site owner doesn't want public. There's no header trick that bypasses this, the rule is explicit. You'll need to access the data through the rendered HTML pages instead, or accept that the endpoint is off-limits.

Query string blocks usually trigger on values that look like SQL injection or directory traversal. If you're passing user-controlled input, sanitize it. If you're hitting search endpoints with unusual parameters, try the values a browser would actually send.


Header Combination Blocks

The hardest to diagnose. The site blocks requests where some combination of headers looks wrong, say, Accept-Language: en from a country whose IPs usually send Accept-Language: fr. Or requests missing Sec-Fetch-* headers entirely, which is normal for requests and curl but never happens from a real Chrome.

The fix is to send the full set of headers a real browser sends. Either use a stealth library like curl_cffi (which mimics Chrome's TLS fingerprint as well as headers), or drive a real browser through Playwright.


from curl_cffi import requests

response = requests.get(
    "https://example.com",
    impersonate="chrome120",
)


curl_cffi ships with browser-impersonation profiles that handle both the TLS handshake and the header order — two things that requests gets wrong in ways Cloudflare can detect.


When the Rule Is Just Your IP Reputation

Sometimes you diagnose every variable and the only commonality is the IP. The IP is in a Cloudflare-shared abuse list, and no header change will fix that.

Your options:

  1. Rotate to a clean residential IP and don't reuse the dirty one.

  2. Use a premium residential provider that promises clean pools (worth verifying, ask for ASN distribution data).

  3. Switch to mobile, where carrier NAT makes per-IP reputation effectively meaningless.

This is the unglamorous answer, but it's often the right one. IP reputation is a slow-moving signal, once an IP is dirty, it stays dirty for weeks. Trying to clean it through other request changes is a losing game.


What Doesn't Work

A few popular suggestions that don't actually fix 1020:

  • Clearing cookies and cache. 1020 is server-side. Your local browser state doesn't matter.

  • Switching browsers. Same reason. The block is on your IP and request attributes, not your browser identity.

  • Waiting it out. Unlike rate limit errors, 1020 won't time out. The rule will keep blocking you until the site owner removes it or you change what your request looks like.

  • Generic VPNs. Most consumer VPNs use datacenter IPs that are already on Cloudflare's reputation lists. They may help with geo-blocks, but rarely with reputation-based 1020.


When to Give Up

If a site is enforcing 1020 aggressively against your specific use case, the site owner has made a deliberate choice to keep your traffic out. Bypassing it permanently is an arms race you'll lose against motivated security teams.

For legitimate use cases (your own account, your own data, research access), contact the site owner. For aggressive scraping where the owner clearly doesn't want you there, consider whether the data is worth the ongoing maintenance cost, and whether there's a sanctioned API or data partner you can use instead.


Wrapping Up

Error 1020 is a diagnosis problem, not a brute-force one. Isolate the variable, fix the matching trigger, and you're through. Most cases come down to one of: IP reputation, country block, User-Agent substring, or missing browser headers. Test in that order and you'll resolve the majority of 1020s without escalating to expensive stealth tooling.

Error 1020 is different from the rest of Cloudflare's error family. It's not a rate limit. It's not a generic block. It's the site's owner telling Cloudflare: "if a request matches these conditions, deny it." You've matched. The page won't load.

The good news: 1020 is rule-based, which means it's deterministic. If you can figure out what triggered it, you can avoid the trigger. The bad news: the rules are invisible to you. You have to reason from the symptoms.

This post walks through what 1020 means, the common rule patterns sites deploy, and the working bypass strategies for 2026.


What Cloudflare Error 1020 Actually Means

When Cloudflare returns a 1020, it's because a request matched a WAF (Web Application Firewall) custom rule with the action set to Block. The rules are written by the site owner, not by Cloudflare's default ruleset, and can match on almost any request attribute:

  • IP address, ASN, or country

  • User-Agent string

  • Referer header

  • URL path or query string

  • HTTP method

  • Header presence or value

  • Combinations of any of the above

A typical 1020 rule looks something like: "Block if country is not US and path starts with /api/." Or: "Block if User-Agent contains python-requests." Or: "Block if ASN is in our list of known proxy ASNs."

Because the rules vary by site, the same setup can hit 1020 on one Cloudflare-protected site and sail through another. There's no universal fix, there's only diagnosis.


Step 1: Identify What Triggered the Block

Before changing your setup, isolate the variable. Run these tests in order, changing one thing at a time:

Test from a different IP. If you have access to a residential proxy or a friend's network, try the same request from there. If it works, your IP or ASN is on the blocklist. If it still fails, the rule isn't about your IP.

Test with a vanilla browser User-Agent. If you were using a custom UA or a scraper signature (python-requests/2.31, curl/8.5, scrapy/2.11), swap to a current Chrome User-Agent. Many 1020 rules block on UA substrings — a single header change can fix it.

Test from a different country. Geo-blocks are common, especially for sites in regulated industries (banking, gambling, streaming, government). If the site loads from a US IP but not from your home country, geo is the rule.

Test without query parameters. If you're hitting /search?q=...&page=..., try the bare path. Sites sometimes block on query parameter patterns that look like injection attempts or scraping ranges.

The order matters. Diagnosing wrong wastes time chasing the wrong fix.


Common Rule Patterns and Their Fixes

Once you know what triggered the block, the fix follows directly. The patterns below cover most 1020 cases.


IP-Based Blocks

The most common trigger. Cloudflare exposes IP reputation scores, and site owners often block any IP above a threshold. Datacenter ASNs, known VPN exit nodes, and Tor exits get blocked aggressively.

The fix: residential or mobile proxies. Datacenter proxies, even fresh ones, often share ASNs with known abuse sources. Residential IPs route through real ISPs and rarely trigger reputation-based rules.

If you're using a residential pool and still hitting 1020, the IPs are likely recycled, previous users got them flagged. A premium provider with cleaner pools, or a mobile proxy, fixes this.


Country and ASN Blocks

Site owners block by country for compliance, licensing, or anti-fraud reasons. The fix is straightforward: route through a proxy in a permitted country.

ASN blocks are harder to diagnose because you don't see the ASN unless you look it up. Use ipinfo.io/<your-ip> to check. If your proxy's ASN is something like AS14061 (DigitalOcean) or AS16509 (AWS), expect blocks on any site protecting against scrapers. Switch to a residential or mobile proxy with an ISP ASN like AS7922 (Comcast) or AS22394 (Cellco/Verizon).


User-Agent Blocks

Some of the laziest rules, and the most common. The site blocks any UA containing python, bot, crawler, scrapy, curl, or similar substrings.

The fix is one line:


import requests

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
}

response = requests.get("https://example.com", headers=headers)


Keep the full header set. Sites that check UA often also check for missing Accept-Language or Accept-Encoding, which are giveaways for non-browser clients.


Path or Query Pattern Blocks

If /api/ or /admin/ paths are blocked, the rule is gating access to endpoints the site owner doesn't want public. There's no header trick that bypasses this, the rule is explicit. You'll need to access the data through the rendered HTML pages instead, or accept that the endpoint is off-limits.

Query string blocks usually trigger on values that look like SQL injection or directory traversal. If you're passing user-controlled input, sanitize it. If you're hitting search endpoints with unusual parameters, try the values a browser would actually send.


Header Combination Blocks

The hardest to diagnose. The site blocks requests where some combination of headers looks wrong, say, Accept-Language: en from a country whose IPs usually send Accept-Language: fr. Or requests missing Sec-Fetch-* headers entirely, which is normal for requests and curl but never happens from a real Chrome.

The fix is to send the full set of headers a real browser sends. Either use a stealth library like curl_cffi (which mimics Chrome's TLS fingerprint as well as headers), or drive a real browser through Playwright.


from curl_cffi import requests

response = requests.get(
    "https://example.com",
    impersonate="chrome120",
)


curl_cffi ships with browser-impersonation profiles that handle both the TLS handshake and the header order — two things that requests gets wrong in ways Cloudflare can detect.


When the Rule Is Just Your IP Reputation

Sometimes you diagnose every variable and the only commonality is the IP. The IP is in a Cloudflare-shared abuse list, and no header change will fix that.

Your options:

  1. Rotate to a clean residential IP and don't reuse the dirty one.

  2. Use a premium residential provider that promises clean pools (worth verifying, ask for ASN distribution data).

  3. Switch to mobile, where carrier NAT makes per-IP reputation effectively meaningless.

This is the unglamorous answer, but it's often the right one. IP reputation is a slow-moving signal, once an IP is dirty, it stays dirty for weeks. Trying to clean it through other request changes is a losing game.


What Doesn't Work

A few popular suggestions that don't actually fix 1020:

  • Clearing cookies and cache. 1020 is server-side. Your local browser state doesn't matter.

  • Switching browsers. Same reason. The block is on your IP and request attributes, not your browser identity.

  • Waiting it out. Unlike rate limit errors, 1020 won't time out. The rule will keep blocking you until the site owner removes it or you change what your request looks like.

  • Generic VPNs. Most consumer VPNs use datacenter IPs that are already on Cloudflare's reputation lists. They may help with geo-blocks, but rarely with reputation-based 1020.


When to Give Up

If a site is enforcing 1020 aggressively against your specific use case, the site owner has made a deliberate choice to keep your traffic out. Bypassing it permanently is an arms race you'll lose against motivated security teams.

For legitimate use cases (your own account, your own data, research access), contact the site owner. For aggressive scraping where the owner clearly doesn't want you there, consider whether the data is worth the ongoing maintenance cost, and whether there's a sanctioned API or data partner you can use instead.


Wrapping Up

Error 1020 is a diagnosis problem, not a brute-force one. Isolate the variable, fix the matching trigger, and you're through. Most cases come down to one of: IP reputation, country block, User-Agent substring, or missing browser headers. Test in that order and you'll resolve the majority of 1020s without escalating to expensive stealth tooling.

Author

The Scraper

Engineer and Webscraping Specialist

About Author

The Scraper is a software engineer and web scraping specialist, focused on building production-grade data extraction systems. His work centers on large-scale crawling, anti-bot evasion, proxy infrastructure, and browser automation. He writes about real-world scraping failures, silent data corruption, and systems that operate at scale.

Like this article? Share it.
You asked, we answer - Users questions:

In This Article