When a site behind Cloudflare cannot be reached, Cloudflare answers in its place. Error 522, "Connection timed out", is one of those answers. Cloudflare defines it in one sentence: "Error 522 occurs when Cloudflare times out contacting the origin web server". The origin is the site's own server, which sits behind Cloudflare.
So your request did reach Cloudflare, and your connection and your proxy did their part. The failure lies on the leg from Cloudflare to the origin, which your proxy never touches. That is why a new proxy so rarely helps. A different exit can change the Cloudflare data center you arrive at, and sometimes that matters. It cannot make a silent server answer.
The 522 is also the most searched of Cloudflare's origin errors. Keyword Planner counts about 1,000 searches a month worldwide for "cloudflare 522", more than for any other code in the family.
Your client
sends the request
Proxy
delivers it to Cloudflare
Cloudflare edge
answers: this leg worked
Origin server
no connection in time = 522
What exactly timed out?
Cloudflare names two limits. Before a TCP connection exists, Cloudflare sends a SYN and waits for the origin's SYN+ACK. Its backoff intervals between SYN retries are 1, 1, 1, 1, 1, 2, 4 and 8 seconds, 19 seconds in all, and then it gives up. Once the connection exists, the origin has 90 seconds to acknowledge Cloudflare's request. Missing either limit produces a 522.
Cloudflare's page on connection limits adds two notes. These two timers are "not an exhaustive list of every operation that can produce 522". And "a timeout while TLS remains pending can be reported as 522 rather than 525", so a stuck TLS handshake with the origin can show the same code.
A 524 comes one step later. There the origin took the request and then sent no response within the Proxy Read Timeout.
The causes Cloudflare lists all sit at the origin. The first reads "Cloudflare IP addresses are rate limited or blocked in .htaccess, iptables, or firewalls", and Cloudflare marks it as the "most common cause". The others are an overloaded or offline server and keepalives turned off on the web server. A wrong origin IP in the Cloudflare DNS records and packets dropped at the origin complete the list. None of them involves the visitor, the visitor's proxy, or the request.
Is the 522 coming from my proxy?
Almost never, and one header tells you. A Cloudflare 522 arrives with a cf-ray response header, the Ray ID that Cloudflare gives every request. That header proves the request reached Cloudflare.
Two exceptions are worth knowing. The first is a hostname that belongs to your proxy provider, such as its dashboard or API, hosted behind Cloudflare. A 522 there means that service's own server is down, and its status page is the place to look.
The second is a proxy gateway that uses 522 for its own timeout. Oxylabs' residential quick-start guide, last updated September 29, 2023, lists "522 Timeout" for the case where its proxy server got no timely response from upstream. The same table uses 525 for "No Exit Found". A gateway's 522 comes without a cf-ray header. For an https:// address, curl 7.87.0 and later report it as CONNECT tunnel failed, response 522, because the proxy answered the tunnel request itself. curl 7.86.0 and older print Received HTTP code 522 from proxy after CONNECT instead, as our 502 guide shows.
Why does the site load directly but fail through the proxy?
Cloudflare runs an anycast network. In its own words, "the same IP address is announced from data centers worldwide, so each visitor's request is routed to a nearby data center". A proxy exit in another city or country usually arrives at a different data center than your own connection.
The cf-ray header shows which one. Cloudflare's example is 230b030023ae2822-SJC, where the three letters at the end name the data center that processed the request. Compare the header on both routes:
curl -sI https://example.com | grep -i cf-ray
curl -sI -x http://YOUR-LOGIN:YOUR-PASSWORD@HOST:PORT https://example.com | grep -i cf-ray
If the codes differ and only one route fails, the origin has trouble with one path. The usual reason is its firewall. Cloudflare warns that to an origin's firewall, its traffic "can look like a limited number of sources sending a high volume of traffic". That "may trigger automatic blocking or rate limiting". A firewall that has blocked some Cloudflare addresses leaves the requests through those addresses hanging, while others pass. A damaged route between one data center and the origin has the same effect.
One caveat applies. With Argo Smart Routing or Tiered Caching, the data center that connects to the origin can differ from the one you reached. Cloudflare notes that the origin then sees the connecting data center's code.
What should I do when a 522 hits my browser or scraper?
1. Check that it is Cloudflare's, and that it is not only you
Look for the cf-ray header and Cloudflare's error page. Then load the same address from another network, such as a phone on mobile data. If it fails there too, the origin is down for everyone, and the job is to wait.
2. Slow down before you retry
A 522 comes from a server that is not taking connections. Retry with growing delays: a few seconds, then tens of seconds, then a minute or more. Add random jitter so that your workers do not return together, and cap the number of attempts. Cut concurrency against that host while the 522s last, and resume when a single probe request succeeds. If the 522s began when your job ramped up, your own traffic may be part of the load, so keep the lower rate.
Mind the clock as well. A 522 from the 19-second limit cannot arrive before Cloudflare has waited those 19 seconds. A 522 from the request limit comes after 90 seconds or more. A client that gives up sooner never sees the 522. It reports its own timeout instead, and the error then looks like a proxy problem.
3. Try two or three regions, then stop
The path to the origin depends on where you enter Cloudflare, so an exit in another region can succeed where the first failed. If one region fails every time and others work, send the job through the regions that work. If every region fails, the origin is down or blocks Cloudflare broadly. Rotating through a hundred more addresses then adds nothing but log lines.
4. Keep it apart from blocks
A challenge page or a block such as error 1020 means that Cloudflare stopped your request on the site's behalf. A 522 means that Cloudflare could not reach the site at all, and a person in a browser gets the same page. Headers, browser fingerprints and a different kind of IP change nothing about a 522. If a job collects both kinds, handle them separately. Our guide to sites behind Cloudflare covers challenges and blocks.
5. Tell it apart from a 524
A 524, "A timeout occurred", means Cloudflare did connect and send the request, then waited the full Proxy Read Timeout without a response. Cloudflare now puts that at 125 seconds by default. Older guides, an earlier version of this page among them, gave 100. A 524 points at a slow page or a heavy API call. Ask for less per request, paginate, or avoid the endpoint that computes something huge. Enterprise zones can raise the limit to 6,000 seconds.
How do Cloudflare's origin errors compare?
Each code in this family is Cloudflare reporting on the site's own server. The table follows Cloudflare's own pages as read on October 23, 2026.
Cloudflare's origin errors, and what a visitor can do about each
| Code | What happened between Cloudflare and the origin | What a visitor or scraper can do |
|---|---|---|
| 520 Web server returns an unknown error | The origin sent an empty, unknown or unexpected response | Retry later, with backoff |
| 521 Web server is down | The origin refused Cloudflare's connection | Wait |
| 522 Connection timed out | No SYN+ACK within 19 seconds, or no acknowledgment of the request within 90 | Slow down, try two or three regions, then wait |
| 523 Origin is unreachable | Cloudflare could not contact the origin, typically because no route led to its IP | Wait |
| 524 A timeout occurred | Connected, but no response within the Proxy Read Timeout, 125 seconds by default | Ask for less per request, or paginate |
| 525 SSL handshake failed | The TLS handshake with the origin failed, with SSL set to Full or Full (Strict) | Wait |
| 526 Invalid SSL certificate | Cloudflare could not validate the origin's certificate, with SSL set to Full (Strict) | Wait |
| 530 | Cloudflare could not resolve the origin's hostname, and the page carries a 1xxx error | Read the 1xxx code on the page |
Cloudflare documentation, the pages for errors 520 to 530, read October 23, 2026
How do I fix a 522 on my own site?
If your own visitors see the page, the fix list is Cloudflare's, and it starts with the firewall. All visitor traffic reaches your server from Cloudflare's addresses. A rule that blocks some of them shuts out every visitor who enters through them.
Allow every Cloudflare range. On October 23, 2026, Cloudflare listed 22 ranges, 15 for IPv4 and 7 for IPv6. Its API at https://api.cloudflare.com/client/v4/ips returns them as JSON, with an etag that changes when the list does. Use the API in scripts. When we fetched the plain-text lists at cloudflare.com/ips-v4 and /ips-v6 with Python's default settings, both answered 403 Forbidden, while curl received them.
This short script compares an allowlist file with the current list and prints what is missing:
# cf_allowlist_check.py: which of Cloudflare's published ranges does an allowlist miss?
# usage: python cf_allowlist_check.py allowlist.txt (one address or range per line, # starts a comment)
import ipaddress
import json
import sys
import urllib.request
with urllib.request.urlopen("https://api.cloudflare.com/client/v4/ips", timeout=15) as reply:
result = json.load(reply)["result"]
cloudflare = [ipaddress.ip_network(c) for c in result["ipv4_cidrs"] + result["ipv6_cidrs"]]
with open(sys.argv[1]) as f:
entries = [line.split("#")[0].strip() for line in f]
allowed = [ipaddress.ip_network(e, strict=False) for e in entries if e]
missing = [net for net in cloudflare
if not any(net.version == a.version and net.subnet_of(a) for a in allowed)]
print(f"Cloudflare lists {len(cloudflare)} ranges (etag {result['etag']}), "
f"the allowlist covers {len(cloudflare) - len(missing)}")
for net in missing:
print("missing:", net)
Cloudflare's own example adds one iptables rule per range: iptables -I INPUT -p tcp -m multiport --dports http,https -s $ip -j ACCEPT. Check security plugins too, such as those for WordPress, because they can block Cloudflare's addresses on their own.
Check the origin IP. The A or AAAA record in your Cloudflare DNS must point at the server your host runs today. After a move to a new server, check this first.
Check the load and the web service. Cloudflare's list says "An overloaded or offline origin web server drops incoming requests".
Keep HTTP keep-alive on. Cloudflare reuses open connections to the origin, and its connection limits page says "Ensure HTTP keep-alive connections are enabled on your origin".
Look for dropped packets. Before you contact Cloudflare support, it asks for an MTR or a traceroute from the origin to a Cloudflare address that often connected before the trouble began. Take that address from your server's logs. Origin Analytics in the dashboard shows the rate of failed TCP connections by path.
Rule out the special cases. A Worker on a Custom Domain that fetches its own hostname gets a 522. Cloudflare Pages needs a custom domain with the CNAME pointed at it. An Origin Rule must point at a hostname that resolves.
While you fix it, Always Online can show visitors an archived copy. It works only when Cloudflare cannot connect to the origin, which is the usual 522. It serves a stale copy from Cloudflare's cache or from the Internet Archive. On the Free plan, the archive crawls your popular pages every 30 days, so the copy can be old. Dynamic parts such as a cart still show the error.
How should a scraper handle 522s?
Scrapy retries a 522 out of the box. In Scrapy 2.19.0, released September 10, 2026, the default RETRY_HTTP_CODES list is 500, 502, 503, 504, 522, 524, 408 and 429. RETRY_TIMES is 2, three requests in all. A retry goes back into the queue at a lower priority, with no wait of its own.
The waiting comes from AutoThrottle. Its guide sets the target delay to a response's latency divided by AUTOTHROTTLE_TARGET_CONCURRENCY. It also states that "latencies of non-200 responses are not allowed to decrease the delay". Scrapy's code also never lets the new delay fall below that target. With a target concurrency of 1, a 522 that took 19 seconds to arrive raises the delay to 19 seconds. The cap is AUTOTHROTTLE_MAX_DELAY, 60 seconds by default. Scrapy's DOWNLOAD_TIMEOUT of 180 seconds is longer than every Cloudflare limit above, so Scrapy sees the 522 or 524 before its own timeout fires.
# settings.py
RETRY_TIMES = 3
RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429] # Scrapy's default list
CONCURRENT_REQUESTS_PER_DOMAIN = 4
DOWNLOAD_DELAY = 1.0
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 5.0
AUTOTHROTTLE_MAX_DELAY = 60.0
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
For other clients, three rules do the same work. Treat a 522 as worth a retry, wait longer after each failure, and keep the client's timeout above 19 seconds so that the 522 can reach it. Our Scrapy proxy guide shows how the retry middleware and a proxy rotator share the work. The 504 guide covers the timeout you see when the slow hop is the proxy.
What can a proxy change on a Cloudflare site?
A proxy decides where your request enters Cloudflare, which address Cloudflare's bot management sees, and whether a session keeps one address from start to end. Those matter for the path-specific 522s above, and far more for challenges and rate limits. A proxy cannot make an origin answer. Our residential proxies cost $0.50/GB for one GB, falling to $0.44/GB at 2,000 GB+. To check a proxy itself before you blame a site, our proxy checker tests whether it works.
What we could not check
- We did not produce a 522. That would need a site behind Cloudflare whose origin stops answering, and we test nothing on anyone's network. The timers, causes and fixes on this page come from Cloudflare's own pages as read on October 23, 2026.
- The 403 that Cloudflare's plain-text lists gave Python's default client is one observation, from one machine on one day.
- Cloudflare changes its limits and its ranges. This page is due for a check by January 23, 2027.
Sources
- Cloudflare documentation: Error 522, Error 524, the 5xx overview and the pages for errors 520, 521, 523, 525, 526 and 530, read October 23, 2026.
- Cloudflare documentation: Connection limits, Cloudflare IP addresses, HTTP headers and Always Online, read October 23, 2026.
- Cloudflare's IP list API,
https://api.cloudflare.com/client/v4/ips, read October 23, 2026, etag 38f79d050aa027e3be3865e495dcc9bc. - Scrapy 2.19.0: default_settings.py, retry.py and the AutoThrottle documentation.
- curl source, lib/cf-h1-proxy.c, for the CONNECT message, read October 23, 2026.
- Oxylabs, Residential Proxies Quick Start Guide, its table of response codes, last updated September 29, 2023, read through our server on October 23, 2026.
- Google Keyword Planner, worldwide monthly searches, read October 23, 2026.



