Not a scraper? See Seeing this as a visitor.
On this page 7 sections
What does Cloudflare 403 Forbidden mean?
A Cloudflare 403 means your request was refused, and one of three things refused it: a Cloudflare security rule, a failed challenge, or the website's own server. The status alone only says the server refuses to process the request (MDN: 403); the page that comes with it tells you which case you are in.
| Case | What refused the request | What you see |
|---|---|---|
| Blocked by Cloudflare | A WAF, IP, country, rate limiting or bot rule, or the Browser Integrity Check | A Cloudflare-branded page, often with "Error 10xx" and a Ray ID |
| Challenge not passed | A managed or JavaScript challenge | A "Just a moment..." page; the response carries the header cf-mitigated: challenge |
| Refused by the website itself | The origin server; Cloudflare only passes the 403 through | The site's own 403 page, with no Cloudflare branding |
Per Cloudflare's Error 403 page, a 403 without Cloudflare branding comes from the origin server. A challenge page response always carries cf-mitigated: challenge (Detect a Challenge Page response; How challenges work).
How to tell which rule blocked you
Read the response, then change one thing at a time:
- Read the page title and body. An "Error 10xx" code names the Cloudflare rule type. "Just a moment..." is a challenge. A plain site-styled 403 is the origin.
- Read the headers. A
cf-rayheader (the Ray ID) andserver: cloudflaretell you the response passed through Cloudflare (Cloudflare HTTP headers), not who blocked it. Acf-mitigated: challengeheader means a challenge. - Open the same URL in a normal browser on the same IP. If it loads, the IP is not banned: the problem is your client.
- Repeat from another IP and location. If it passes, the block is about IP reputation, network or country.
- Slow down to one request every few seconds. If the 403s stop, a rate rule fired.
This Python requests snippet sends one request through the ProxyField gateway and prints the status, the Cloudflare headers, the title and any 10xx code. Replace <login>, <password> and the URL.
import re
import requests
proxy = "http://<login>-country-us-city-new_york:<password>@gate.proxyfield.io:7000"
r = requests.get("https://example.com/", proxies={"http": proxy, "https": proxy}, timeout=30)
print("status:", r.status_code)
for name in ("server", "cf-ray", "cf-mitigated", "retry-after"):
print(name + ":", r.headers.get(name))
title = re.search(r"<title>(.*?)</title>", r.text, re.I | re.S)
print("title:", title.group(1).strip() if title else None)
code = re.search(r"Error\s*(1\d{3})", r.text)
print("cloudflare error code:", code.group(1) if code else None)| Symptom | Likely cause | Go to fix |
|---|---|---|
| 403s after a burst; Error 1015 or a 429 | Rate limiting rule | 1 |
| Error 1010, or 403 at once from a plain HTTP client | Browser Integrity Check or header rules | 2 |
"Just a moment..." page, cf-mitigated: challenge | Challenge not passed | 3 |
| Correct headers, still blocked; a real browser on the same IP passes | TLS or browser fingerprint, bot score | 4 |
| Another IP passes where yours fails; Error 1020 on one network only | IP reputation, network (ASN) or country rule | 5 |
| A site-styled 403, no Cloudflare branding | The origin refuses you | 7 |
How to fix Cloudflare 403 when scraping
Fix the simplest cause first; each step says when it applies.
1. Slow down and back off
If the 403s start after a burst, or you see Error 1015 or a 429, a rate limiting rule fired. Lower concurrency, add random delays and back off on each error. If a Retry-After header is present, wait at least that long (MDN: Retry-After). Cloudflare's Error 1015 page warns that retrying within a short period can extend the block.
2. Send complete, consistent browser headers
If a plain HTTP client gets a 403 on its first request, or you see Error 1010, your headers give you away. Send a User-Agent that matches the client you really are, plus the Accept, Accept-Language and Accept-Encoding headers that browser sends (MDN: User-Agent). Error 1010 means the site banned your browser's signature (Error 1010). A Chrome User-Agent on a Python client does not make it Chrome: a claim the rest of the request contradicts can make things worse.
3. Use a real browser for JavaScript challenges
If the response has cf-mitigated: challenge, a plain HTTP client cannot pass: the challenge runs in the browser. Load the page with Playwright or Puppeteer and keep the cookies in one browser context for the session, so you are not challenged on every page. Setup: Playwright with proxies, Puppeteer with proxies. Cloudflare lists the browsers its challenges support; a headless browser can still be challenged.
4. Match the TLS and HTTP fingerprint to the browser you claim to be
If a browser-like client with correct headers is still blocked, the TLS handshake may be the tell. Cloudflare profiles TLS clients with JA3 and JA4 fingerprints and uses them among its bot detection engines. An HTTP library has its own fingerprint, whatever User-Agent it sends. The simplest consistent setup is a real browser (fix 3).
5. Change the IP type: residential, mobile or ISP
If another IP passes where yours fails, the rule is about IP reputation, network (ASN) or country. Datacenter ranges are the usual target of network-based rules. Move to residential proxies, mobile proxies or static residential (ISP) proxies. Keep one sticky IP for a whole challenge session and rotate between sessions, not inside one.
ProxyField gives you a new IP on every request (rotating proxies) or sticky sessions from 30 s to 36 h (presets 1, 5, 10, 30 min, 1, 3, 6 h), with country, region and city targeting. This Playwright launch uses the gateway with country and city targeting:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(proxy={
"server": "http://gate.proxyfield.io:7000",
"username": "<login>-country-us-city-new_york",
"password": "<password>",
})
context = browser.new_context() # one context keeps one set of cookies
page = context.new_page()
response = page.goto("https://example.com/")
print(response.status, response.headers.get("cf-mitigated"), page.title())
browser.close()Add a sticky session before you run a challenge flow: -session-<id>-ttl-<seconds> after the location, as in <login>-country-us-session-he9f2qga-ttl-600 (ttl is 30 to 129,600 seconds, 20 minutes by default). A new IP type does not change your headers, fingerprint or request rate, so fixes 1 to 4 still apply.
6. Use the site's API or a scraping API
If the site offers an official API or data export, use it. If not, ProxyField's web scraping API fetches any URL as plain HTTP or with JavaScript rendering, billed on successful results only. Contact sales.
7. If the block is deliberate, stop and ask
If the 403 comes from the origin, or the same rule blocks every IP and client you try, the site does not want automated access. Check its robots.txt (RFC 9309) and terms, and ask the owner for access. Getting past an access barrier the owner set up on purpose can raise legal risk: see is web scraping legal.
Will residential proxies fix Cloudflare 403?
A residential IP can clear blocks based on IP reputation or datacenter ranges; it does not fix a mismatched browser fingerprint, missing JavaScript or a too-fast request rate.
| Cause | Does a residential proxy help? | What else you need |
|---|---|---|
| IP reputation or datacenter network (ASN) rule | Often; mobile and static residential (ISP) IPs can help too | A sticky IP for each session |
| Rate limit | Partly: rotation spreads requests over many IPs | A slower rate and back-off |
| Header or fingerprint mismatch | No | Consistent headers, a real browser |
| JavaScript challenge | No | A real browser that runs the challenge |
On targets with no Cloudflare bot rules, cheaper per-GB datacenter proxies are usually enough.
Cloudflare 403 vs 1020, 1015 and other codes
403 is the HTTP status; the 10xx number on a Cloudflare page names the rule behind it:
- 1020 Access denied: a firewall rule on the site blocks you (Error 1020).
- 1015: too many requests in a given period (fix 1).
- 1010: the site banned your browser's signature (fix 2).
- 52x: the origin server failed, not your request.
The Cloudflare table on the errors hub lists the rest.
Seeing this as a visitor, not a scraper?
Hit a Cloudflare 403 while browsing? The site's rules flagged your connection:
- Turn off your VPN, proxy or browser extensions and reload.
- Clear the site's cookies, or try a private window.
- Still blocked? Send the Ray ID from the error page to the site owner; only they can change the rule.
Cloudflare 403 Forbidden FAQ
Why does Cloudflare return 403 Forbidden to my scraper, and how do I fix it?
ProxyField's checklist for a Cloudflare 403 on a scraper has five causes: the request rate, headers, missing JavaScript, the TLS fingerprint and the IP's reputation. Fix them in that order; a residential IP, from $1.95/GB, helps only with the last one.
Will switching to residential proxies fix Cloudflare 403 errors, or is the problem my headers and browser fingerprint?
Test both: if a normal browser on the same IP passes, the problem is your headers or fingerprint, and a new IP won't fix it. If only another IP passes, the rule is about IP reputation or datacenter ranges, and residential, mobile or ISP IPs can help.
What does 403 Forbidden mean on Cloudflare?
A Cloudflare rule or the website's own server refused your request. A Cloudflare-branded page means a Cloudflare rule or a failed challenge; a page without Cloudflare branding means the origin server.
How do I fix Cloudflare 403 Forbidden?
Find which rule fired, then fix in order: slow down, send complete browser headers, use a real browser for JavaScript challenges, match the TLS fingerprint, change the IP type, or use an API. If the block is deliberate, stop and ask the site owner.
What is "error status 403" on a Cloudflare page?
It is the HTTP status code Cloudflare returned with its block or challenge page. The 10xx code and the Ray ID on the same page tell you which rule fired.
Can I get past a Cloudflare 403 Forbidden block?
Only by fixing what the rule checks: rate, headers, JavaScript, fingerprint or IP. If the same rule blocks every client and IP you try, the site does not want automated access; read its terms and ask the owner.
What is the difference between Cloudflare 403 and error 1020?
403 is the HTTP status code behind several kinds of Cloudflare block. Error 1020 is one of them: the "Access denied" page shown when a firewall rule on the site blocks your request.
What is the difference between a Cloudflare 403 and a Cloudflare challenge page?
A block page refuses the request outright; a challenge page ("Just a moment...") asks the browser to run a check first and carries the header cf-mitigated: challenge. A plain HTTP client can't pass a challenge, while a real browser can.
How do I fix a Cloudflare 403 as a visitor, not a scraper?
Turn off your VPN, proxy or browser extensions and reload, then clear the site's cookies or try a private window. If you're still blocked, send the Ray ID from the error page to the site owner; only they can change the rule.
Is a Cloudflare 403 caused by my IP being banned?
Sometimes. Test the page in a normal browser on the same IP and from another IP: if the browser passes, the problem is your client; if only another IP passes, it is the IP.