The 522 page is one of the most recognisable errors on the web: the Cloudflare branding, the three-box diagram of browser, Cloudflare, and host, the word "Connection timed out", and a Ray ID at the bottom. The diagram is more honest than most error pages, because it shows you exactly where the failure is. The line between your browser and Cloudflare is green. The line between Cloudflare and the host is red. Everything on your side of Cloudflare, including your proxy, did its job.
That is worth stating plainly, because a large share of the people who search for this error while using a proxy assume the proxy is at fault, and change it, and change it again, and get the same page. Cloudflare's own definition is that a 522 "occurs when Cloudflare times out contacting the origin web server". The origin is the site's real server, behind Cloudflare, that your proxy never speaks to. A 522 says that Cloudflare could not open a connection to it in time. Swapping the proxy changes which Cloudflare data center you arrive at, and sometimes that matters, but it cannot make an unreachable origin reachable.
Your client
sends the request
Proxy
delivers it to Cloudflare
Cloudflare edge
answers: this leg worked
Origin server
no connection in time = 522
What the 522 measures
Cloudflare's documentation gives the exact conditions. Before a connection is established, the origin has to answer Cloudflare's initial connection attempt (the TCP SYN) with a SYN-ACK, and Cloudflare gives up after 19 seconds across several retries. After a connection is established, the origin has to acknowledge Cloudflare's request within 90 seconds. Miss either window and the visitor receives a 522.
The causes Cloudflare lists are all on the origin side: the origin's firewall or .htaccess rules blocking or rate-limiting Cloudflare's IP ranges (which the documentation calls the most common cause), an overloaded or offline origin, keepalive disabled on the origin web server, an incorrect origin IP in the Cloudflare DNS record, and packets dropped somewhere between Cloudflare and the origin. Not one of those involves the visitor, the visitor's proxy, or the visitor's request. The usual proxy troubleshooting fails on this error for exactly that reason.
Why scrapers see more 522s than browsers do
If nothing about the visitor causes a 522, why do scraping jobs collect so many of them while a person at a browser rarely sees one? Three reasons, and the third one is uncomfortable.
Volume finds the failures. A person loads a dozen pages an hour. A scraper loads thousands. An origin that drops one connection in every few hundred looks fine to the person and produces a steady trickle of 522s in the scraper's log. The rate is the origin's; the scraper simply samples it often enough to notice.
Different exits, different data centers, different paths. Cloudflare has data centers all over the world, and every request is handled by the one nearest its source. A residential exit in Manila and one in Frankfurt arrive at different Cloudflare locations, and Cloudflare connects to the origin from wherever it was reached. If the origin's firewall has blocked a particular Cloudflare range, or the route from one location to the origin is degraded, requests through some exits get 522 while others sail through. That mechanism explains "it works from my connection but not through the proxy": the proxy is not failing, it is arriving somewhere that the origin cannot be reached from.
Sometimes the scraper is the overload. A 522 caused by an overloaded origin has to be caused by somebody's traffic, and a scraper running a hundred concurrent connections against a small site is a plausible somebody. When an origin stops answering SYNs, its connection queue is full. A job that reacts to 522s by retrying immediately, at the same concurrency, keeps the queue full and turns a brief spike into an outage that the job then reports as the site's fault.
What to do about a 522
1. Confirm it is Cloudflare, and confirm it is not only you
Read the response. A Cloudflare 522 carries a cf-ray header and the branded page with the diagram. Then load the same URL from a direct connection, or from a browser on another network. If it fails there too, the origin is unreachable for everyone and the job is to wait, not to fix. If it works directly, move to step 3.
2. Back off, and cut concurrency to that host
A 522 is a server not accepting connections. Treat it as an instruction to slow down. Retry with growing delays (a few seconds, then tens of seconds, then a minute or more, with random jitter so that workers do not return together), cap the number of attempts, and drop concurrency against that host to a small fraction of normal while the 522s persist. Probe with a single request at intervals, and resume the full job only when the probe succeeds. If the 522s began when your job ramped up, halve the request rate permanently; the origin has told you its limit.
3. Try a few other exits, then stop
Because the path from the Cloudflare edge to the origin depends on where you arrive, a different exit can succeed where the first failed. Rotate through exits in two or three different regions and watch the result. If one region consistently gets 522 and others do not, pin the job to the regions that work, and accept that the origin has a problem with one path that you cannot fix. If every exit gets 522, the origin is down or blocking Cloudflare broadly, and further rotation is wasted effort. Rotating through a hundred IPs against an origin that is offline achieves nothing except a hundred log lines.
4. Do not mistake it for a block
A 522 is not bot management. Challenge pages, 403s, and the 503 with a JavaScript check are Cloudflare deciding your request looks automated; a 522 is Cloudflare failing to reach the site at all, and it will show the same page to a person in a browser. Changing headers, TLS fingerprints, or IP type does nothing for a 522. If a job produces both 522s and challenges, treat them separately: the challenges are covered in our guide on scraping past Cloudflare, and the 522s by the steps here.
5. Watch for the 524
A close relative that is easy to lump in: 524, "A timeout occurred". That one means Cloudflare did connect to the origin, sent the request, and then waited 100 seconds without receiving a complete response. It points at a slow page or a heavy API call rather than an unreachable server, and the fix is on the request side: ask for less per request, paginate, or avoid the endpoint that computes something enormous. A job that sees 524s on one endpoint and nothing elsewhere has found a slow endpoint, not a broken origin.
The Cloudflare 5xx family at a glance
Each of these is Cloudflare reporting on the origin. None of them is about the visitor's connection or proxy.
| Code | Cloudflare's label | What happened between Cloudflare and the origin | What you can do |
|---|---|---|---|
| 520 | Web server returns an unknown error | The origin sent an empty, malformed, or unexpected response | Retry with backoff; usually transient |
| 521 | Web server is down | The origin refused the connection or is offline | Wait; nothing on your side |
| 522 | Connection timed out | The origin did not accept the connection in time | Back off, try other exits, wait |
| 523 | Origin is unreachable | Cloudflare could not route to the origin at all | Wait; the site's DNS or network |
| 524 | A timeout occurred | Connected, but no complete response within 100 seconds | Lighter requests, paginate |
| 525 | SSL handshake failed | TLS between Cloudflare and the origin failed | Wait; origin certificate problem |
| 526 | Invalid SSL certificate | The origin's certificate failed validation | Wait; origin certificate problem |
If the site is yours
Half the people who search for this error are not scraping anything; they own the site behind Cloudflare and their visitors are seeing the page. If that is you, the fix list is Cloudflare's, and it is short. Allow every Cloudflare IP range through the origin firewall and any rate limiting in .htaccess, iptables, or your host's panel; Cloudflare publishes the ranges and updates them. Check that the origin IP in your Cloudflare DNS record is the server you think it is, especially after a migration. Look at the server's load and at whether the web service is running. Enable keepalive on the origin web server. If none of that lands, ask the host for a traceroute and packet logs between Cloudflare and the origin, which is the evidence Cloudflare support will ask for too.
Handling 522s in a scraper
Scrapy already treats 522 and 524 as retryable: they are in the default RETRY_HTTP_CODES list along with 500, 502, 503, and 504. What it does not do by default is slow down between attempts. Combine the retry list with a delay and a low concurrency ceiling per domain, and let AutoThrottle raise the pace only when responses come back healthy:
# settings.py
RETRY_ENABLED = True
RETRY_TIMES = 3
RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429]
CONCURRENT_REQUESTS_PER_DOMAIN = 4
DOWNLOAD_DELAY = 1.0
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 1.0
AUTOTHROTTLE_MAX_DELAY = 60.0
AUTOTHROTTLE_TARGET_CONCURRENCY = 2.0
For other clients, the same three rules apply: treat 522 as retryable, wait longer after each failure, and lower concurrency for that host while failures continue. Our Scrapy proxy guide shows how the retry middleware and a proxy rotator divide the work between them, and the 504 guide covers the timeout you will see when the slow hop is your proxy rather than Cloudflare.
The proxy's real job on Cloudflare sites
A proxy cannot fix a 522, and it is worth being clear about what it is for instead. On sites behind Cloudflare, the proxy decides which data center your request reaches, which IP reputation Cloudflare's bot management sees, and whether a session that has passed a challenge keeps the same address for its whole flow. Those are the levers behind 403s, challenges, and rate limits, which are far more common on Cloudflare sites than 522s are. For that work, residential proxies with sticky sessions are the standard tool, and every address in our pool is re-verified by the same engine that runs our proxy checker, so the IP you send from is one that answered a check minutes ago rather than one that died an hour before your job started.