What each code means, in one sentence

All three errors are generated by the Cloudflare edge, not by your application, which is why they never appear in your own application logs. They describe three different moments of failure between the edge proxy and your origin server:

  • Error 521, "Web Server Is Down": Cloudflare reached your origin address and the connection was actively refused. Something is alive at the origin and it said no. Typically the web server process is stopped or crashing, it is not bound to the port your SSL/TLS mode requires, or a security tool at the origin is rejecting Cloudflare addresses.
  • Error 522, "Connection Timed Out": Cloudflare got no usable answer at all. The edge gives up if no SYN+ACK comes back within 19 seconds of its SYN, or if the origin does not acknowledge the resource request within 90 seconds once the TCP connection is established. Nothing refused anything: the packets went into a void.
  • Error 524, "A Timeout Occurred": the connection worked, the request was accepted, and the origin simply took too long to answer. The default Proxy Read Timeout is 125 seconds. A separate Proxy Write Timeout of 30 seconds applies when Cloudflare is writing data to the origin, and that one cannot be adjusted on any plan.

The difference between the three is the whole diagnosis, and it is the part most often skipped. 521 is a refusal, 522 is silence, 524 is slowness. A refusal points at a stopped service or a wrong listening port. Silence points at a firewall, a saturated network stack, or a stale origin IP. Slowness points at application code and the database. Nothing about a 524 is a network incident, and no amount of SQL tuning will ever fix a 521.

A useful reflex is to keep a history of which code appears, when, and from which country: 521 concentrated in bursts usually means the web server keeps restarting, while 524 clustered on one endpoint points to slow code rather than a connectivity fault. Cloudflare exposes this in Zone Analytics, where errors can be filtered by edge status code and broken down by URL, source address and data center.

Recommended protocol to stabilize origin connections

To eliminate intermittent outages and secure continuous uptime:

  • Unrestricted allowlisting of Cloudflare IP ranges: Configure host and cloud provider firewall rules to allow all official Cloudflare IPv4 and IPv6 subnets without connection rate limits.
  • Restoring real visitor client IPs: Install origin web server modules (ngx_http_realip_module for Nginx, mod_remoteip for Apache) so local brute-force detectors do not mistake proxy addresses for attackers.
  • Keeping keepalives enabled: Cloudflare reuses open TCP connections to your origin and documents disabled origin keepalives as a direct cause of 522. Keep them on and give them a sane timeout.
  • Decoupling long-running operations: Offload heavy exports and slow tasks into background queues so public HTTP responses consistently resolve well under the 125-second read timeout.

Nginx origins: where a 522 usually comes from

Nginx accepts connections far faster than it can hand them to an application, so on an nginx origin the 522 is almost always about connection budget rather than about nginx being down.

  • Exhausted worker connections. When nginx runs out of worker_connections or file descriptors, new connections pile up in the kernel accept queue and never receive a reply, which is exactly the silence a 522 describes. Read the current values and the listening sockets in one pass:
    nginx -T | grep -E "worker_connections|keepalive_timeout|listen "
  • A full accept queue. On the origin, a Recv-Q sitting at or near Send-Q on port 443 means the queue is saturated and connections are being dropped before nginx sees them:
    ss -ltn | grep -E ":80|:443"
  • Disabled keepalives. keepalive_timeout 0; forces a new TCP connection for every single request from every Cloudflare data center. Cloudflare lists disabled origin keepalives among the causes of 522.
  • Per-address limits applied to the proxy. A limit_req or limit_conn zone keyed on $binary_remote_addr counts the entire Cloudflare network as a handful of clients unless set_real_ip_from and real_ip_header CF-Connecting-IP are configured. Those directives return 503 rather than 522, but the same misreading is what makes fail2ban ban the proxies and take the site down.
  • The 502 that is not a 522. If nginx is running but the PHP-FPM socket or the Node upstream is dead, nginx answers 502 and Cloudflare passes it straight through. Seeing a real 502 in the browser therefore proves nginx answered, so the problem is behind nginx, not between Cloudflare and nginx.

The nginx error log names the cause directly in most of these cases:

grep -iE "worker_connections|too many open files|accept" /var/log/nginx/error.log | tail -20

Apache origins: same symptom, different knobs

  • Worker pool saturation. Once every worker is busy, Apache stops accepting new connections and the edge sees silence. Check which MPM is loaded and how the virtual hosts are bound:
    apachectl -M | grep mpm
    apachectl -S
    Raising MaxRequestWorkers helps only if the machine has the memory for it; the real fix is usually to stop the slow requests that hold workers open.
  • No listener on the port your SSL/TLS mode needs. apachectl -S lists every virtual host and port. A zone on Full or Full (strict) with no port 443 virtual host produces a clean 521, every time, everywhere.
  • Legacy access lists. Cloudflare names .htaccess explicitly as a place where its addresses end up blocked. An Require ip or Deny from list written before the proxy was enabled refuses the edge and returns 521.
  • Anti-abuse modules reading the wrong address. mod_evasive and similar modules see Cloudflare addresses instead of visitors until mod_remoteip is configured with RemoteIPHeader CF-Connecting-IP and the Cloudflare ranges declared as trusted proxies.
  • Timeout directives and 524. Apache's own Timeout and mod_reqtimeout settings decide when Apache gives up, not when Cloudflare does. If Apache waits longer than 125 seconds, the visitor sees a Cloudflare 524 while your access log records a 200 several minutes later.

An origin behind a firewall that blocks Cloudflare IP ranges

Cloudflare's documentation calls this the most common cause of 522: its addresses being rate limited or blocked in .htaccess, iptables, or a firewall. The fix is not hard, but it fails in three predictable ways, and all three are avoidable.

  1. Fetch the current list rather than a copied one. The ranges change. Never paste addresses from a blog post, including this one. Cloudflare publishes the authoritative list at www.cloudflare.com/ips, as plain text suitable for scripts, and as JSON on the public API endpoint:
    curl -s https://www.cloudflare.com/ips-v4
    curl -s https://www.cloudflare.com/ips-v6
    curl -s https://api.cloudflare.com/client/v4/ips
    The JSON response carries an etag, which is what you compare against on a scheduled refresh to know whether anything changed.
  2. Apply them at every layer, in the same session. Cloud security group, host firewall, application or .htaccess allowlist, and the ignore list of any anti-abuse tool such as fail2ban or CrowdSec. Allowing the ranges in one place and not the other is the single most common reason a 522 survives a fix, because each layer then points at the other. A UFW example, both families at once:
    for ip in $(curl -s https://www.cloudflare.com/ips-v4) $(curl -s https://www.cloudflare.com/ips-v6); do
      sudo ufw allow from "$ip" to any port 443 proto tcp
    done
  3. Never skip IPv6. Cloudflare uses its IPv6 ranges routinely. Allowing IPv4 only means a share of connections fails depending on which address family the edge picks, which is the textbook signature of an intermittent 522 that nobody can reproduce on demand.
  4. Refresh on a schedule. A one-shot allowlist ages. Put the fetch in a monthly job that rewrites the rules, rather than discovering the drift during an outage.
  5. Consider not exposing the origin at all. Cloudflare Tunnel replaces inbound rules entirely: the cloudflared daemon opens outbound-only connections to Cloudflare on port 7844, so the origin needs no public address, no open inbound port and no IP allowlist to maintain. On a self-hosted or home-lab origin this removes the whole class of problem.
  6. Filter by country at the edge, not at the origin. If the goal was to keep unwanted regions out, express that in Cloudflare security rules. Blocking address ranges at the origin to achieve it inevitably catches the proxy itself.

522 on Cloudflare Pages and Workers, where there is no classic origin

A 522 on a project with no server of your own looks like a contradiction, which is why these cases cost the most time. There are four real ones, and Cloudflare documents the first three.

  • Cloudflare Pages with a custom domain. On a Pages project, a 522 nearly always means the domain is not wired correctly on both sides. The custom domain must be added to the project, and the CNAME record must point to that custom Pages domain. A CNAME left pointing at a previous host, or a domain that was never registered on the project, produces a 522 while the .pages.dev URL keeps working perfectly.
  • A Worker on a Custom Domain fetching its own hostname. This is the counter-intuitive one. Cloudflare states plainly that a Worker deployed on a Custom Domain performing a fetch to its own hostname causes a 522, because the request loops back into the Worker instead of reaching an origin. The documented options are to use a Route instead of a Custom Domain, to target a different hostname, or to enable the global_fetch_strictly_public compatibility flag.
  • An Origin Rule pointing somewhere unresolvable. If an Origin Rule sends traffic to a hostname that cannot be resolved, for instance a Worker route whose A record is a reserved address such as 192.0.2.0, the edge returns 522.
  • A third-party service called from a Worker or a Pages Function. This one behaves differently from what people expect. Cloudflare documents no set time limit on an individual subrequest, so a slow external API does not trip a proxy read timeout of its own: what you get instead is a request that hangs until the visitor leaves, or whatever error your own code returns. When a genuine 522 does appear on such a call, it usually comes from the third party's own Cloudflare zone and is surfaced through your page. The practical protection is to bound every external call yourself, with AbortSignal.timeout() around the fetch, and to return a status you chose rather than one you inherited.

"It only fails when my VPN is on"

This search comes up often and it deserves an honest answer, because most of the time the site owner is chasing something that is not theirs. A 522 is decided between Cloudflare and your origin, and the visitor's connection has no say in whether the origin answers. So a page that works without a VPN and breaks with it is usually one of three things, and only one of them is yours to fix.

  • It is not actually a 522. Shared VPN exit addresses carry a poor reputation, and what they typically trigger is a Managed Challenge, a CAPTCHA, or a 1020 page from a security rule. Those look like a blocked site to the visitor but have nothing to do with origin connectivity. Read the code printed on the page before doing anything else. If someone reports "the site is down on my VPN", ask for a screenshot rather than a description.
  • A different Cloudflare data center, and a partial allowlist. This is the case that is genuinely yours. A VPN moves your exit point, so another Cloudflare location serves you, and that location contacts your origin from a different address. If your allowlist is stale or was copied from an old list, some locations get through and others are dropped. The symptom is a site that works for most people and fails for a minority, seemingly at random. Filtering errors by data center in Zone Analytics confirms it in a minute, and reapplying the full current ranges fixes it.
  • The VPN itself. Corporate clients that intercept TLS, split-tunnel misconfigurations, a saturated exit node, or DNS resolution forced through the tunnel all break the connection before Cloudflare is involved. If the same URL loads from a phone on mobile data and only fails through one specific VPN, the site is not the problem and no change on your side will help.

Error 524, long-running work, and what to do when you cannot make it faster

A 524 means the connection was fine and the application was too slow. The clock is the Proxy Read Timeout, 125 seconds by default, plus a fixed 30-second Proxy Write Timeout when Cloudflare writes data to the origin. Neither is adjustable outside Enterprise, so the interesting question is what to do about an export, a report or an import that legitimately takes three minutes.

  • Return immediately and poll. Cloudflare's own recommendation for large HTTP processes is status polling. The endpoint accepts the job, answers in milliseconds with an identifier, and the browser asks for the state every few seconds. This is the only option that scales, and it also survives a dropped connection on the visitor's side.
  • Move the endpoint to a DNS-only subdomain. Cloudflare suggests putting requests that regularly exceed 125 seconds behind a subdomain that is not proxied, shown as a grey cloud in the DNS app. The trade-off is real: that hostname loses the proxy, and its address becomes public. Use it for an admin export, not for a public route.
  • Start answering early. The timeout counts time without a response from the origin, so an endpoint that sends its headers and a first chunk quickly behaves very differently from one that buffers everything for two minutes before flushing. Streaming a long report instead of assembling it in memory often removes the error without making anything faster.
  • Cache the expensive result. If the slow answer is identical for everyone, only the first request should ever pay for it. Our guide on why the Cloudflare cache is not working and how to fix low hit ratios covers the rule structure that makes this safe.
  • Enterprise only: raise the timeout. The Proxy Read Timeout can be raised up to 6,000 seconds on Enterprise zones, through a Cache Rule or the zone settings API. Cloudflare notes a possible one-second discrepancy between the value set and the moment the error fires, so set one second above your target.

What does not work, and gets tried anyway: restarting the server, which does not make a 90-second query faster; raising max_execution_time in PHP, which changes when your code gives up rather than when Cloudflare stops waiting; and adding memory to an instance whose bottleneck is a missing database index.

Diagnosing step by step: from curl to a stable origin

Follow these steps in order. Each one narrows the search space before you change anything, and more checklists of this kind are available in our Cloudflare guides hub.

  1. Classify the failure pattern. Sample the site over a minute and record which code appears and how often:
    for i in $(seq 1 30); do curl -s -o /dev/null -w "%{http_code}\n" https://www.example.com/; sleep 2; done
    Alternating 200 and 521 responses point to a web server that keeps restarting. 522 in bursts usually means firewall throttling or saturation. 524 on a single endpoint points to slow application code rather than a network problem.
  2. Record what you will need to escalate. Cloudflare asks for the exact code, the time with its timezone, and the failing URL before anyone can help. The Ray ID identifies the request:
    curl -sI https://www.example.com/ | grep -iE "^HTTP|cf-ray|server"
  3. Separate a network problem from an application delay with timings. One command tells you which of the three codes you are heading towards:
    curl -s -o /dev/null https://www.example.com/ \
      -w "connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n"
    A connect phase that never completes is 522 territory. A normal connect with a time to first byte climbing past a few seconds is a 524 waiting to happen. A connect that fails instantly is a refusal, so a 521.
  4. Test the origin directly, bypassing the proxy. Get the origin address from your hosting panel or from a DNS-only test record, then:
    curl -sI --resolve www.example.com:443:203.0.113.10 https://www.example.com/
    If this also fails or times out, the problem lives on the origin side and Cloudflare is only the messenger.
  5. Ask whether the port is reachable at all. From a machine outside your hosting:
    nc -vz 203.0.113.10 443
    "Connection refused" is 521 material, an indefinite hang is 522 material. The distinction is worth thirty seconds because it sends you to two different teams.
  6. Check what the web server is listening on. On the origin, confirm that the daemon actually binds the expected ports:
    ss -tlnp | grep -E ":80|:443"
    A daemon listening only on IPv6, or on a custom port, explains a 521 that survives service restarts.
  7. Look for saturation rather than for a block. A firewall and an overloaded machine produce the same silence, but the counters do not lie:
    ss -s
    nstat -az | grep -iE "ListenDrops|ListenOverflows|TCPBacklogDrop"
    dmesg -T | grep -iE "conntrack|table full|drop" | tail -20
    Counters that are non-zero and growing during the incident mean the origin is dropping connections under load, not that a rule is rejecting them.
  8. Allow every Cloudflare IP range, at every layer. Apply the current lists as described above, at the cloud security group and at the host firewall, IPv4 and IPv6, and add them to the ignore list of any anti-abuse tool.
  9. Restore real visitor IPs at the origin. Configure mod_remoteip (Apache) or ngx_http_realip_module (Nginx) so rate limiters and brute-force detectors read the visitor address from CF-Connecting-IP instead of the proxy address. Otherwise a busy day is enough for fail2ban to ban the proxies themselves and take the whole site down.
  10. Check the path, in both directions. A traceroute from outside tells you little; what Cloudflare support asks for is a report from your origin back towards a Cloudflare address seen in your own logs:
    mtr -rwc 50 198.41.128.1
    Run it during the incident, not after, and keep the output.
  11. Check the SSL/TLS mode. In SSL/TLS > Overview, prefer Full (strict) with a valid origin certificate. A mismatch between the edge mode and the origin listener produces connection or handshake failures that surface as 52x codes, sometimes only on some URLs. Do not "solve" it by switching to Flexible: that trades one error for a redirect loop, as our guide on the infinite HTTPS redirect loop behind Cloudflare explains.
  12. Profile anything that answers in more than a few seconds. For 524 errors, enable the slow query log on your database, check PHP-FPM pool saturation or a blocked Node.js event loop, and move exports, report generation, and webhook processing to background queues. Every public endpoint must answer well within the 125-second limit.

Common mistakes that keep the errors coming back

  • Allowing Cloudflare addresses at only one layer: Allowing the ranges on the cloud security group but not on the host firewall (or the reverse) leaves the traffic blocked, and each layer points the finger at the other.
  • Allowing IPv4 while forgetting IPv6: Half of the connections then fail depending on which address family the edge picks, which is the textbook signature of an intermittent 522.
  • Pasting an address list instead of fetching it: The ranges change. A list copied into a firewall script three years ago is a scheduled outage, and it fails silently until the day a new range is used.
  • Letting local anti-abuse tools ban the proxies: fail2ban or an application rate limiter that sees thousands of requests from a handful of addresses will eventually ban them all, taking every visitor down at once.
  • Reading a 502 as a 522: A 502 means your web server answered and its upstream did not, so Cloudflare is passing your own error through. Looking for a firewall problem there wastes an afternoon.
  • Treating 524 as a network incident: Restarting the server does not make a 90-second SQL query faster. A 524 means the connection was fine and the application was too slow; the fix lives in the code and the database, not in the firewall.
  • Leaving a stale origin IP in DNS: After a server migration, an A record still pointing to the old machine produces 521 or 522 errors that come and go with propagation. Check DNS > Records before touching anything else; our guide on broken email after migrating to Cloudflare covers DNS record hygiene in detail.

Frequently asked questions

What does Cloudflare error 522 mean?

It means Cloudflare tried to reach your origin server and got no usable answer in time. Cloudflare gives up if no SYN+ACK comes back within 19 seconds of its SYN, or if the origin does not acknowledge the resource request within 90 seconds once the TCP connection exists. Nothing refused the connection and nothing was too slow to compute: the packets simply went nowhere. Per Cloudflare's own documentation, the most common cause is an origin firewall that blocks or rate limits Cloudflare IP ranges.

How do I fix Cloudflare error 522 connection timed out?

Work in this order. Confirm the origin answers at all by querying its address directly with curl --resolve. Allow every current Cloudflare IPv4 and IPv6 range at every filtering layer, meaning the cloud security group, the host firewall, .htaccess or application allowlists, and anti-abuse tools such as fail2ban. Check that the origin is not saturated by looking at the TCP accept queue and at the ListenOverflows counters. Confirm the A or AAAA record in Cloudflare DNS still matches the address your host actually provisioned. Keepalives must stay enabled at the origin.

How do I fix Cloudflare error 521?

A 521 is an active refusal, so something is alive at the origin and saying no. Check that the web server process is running and has not crashed, then confirm it is bound to the port your SSL/TLS mode requires: port 80 for Flexible, port 443 for Full and Full (strict). Verify that the origin actually serves HTTPS with a valid certificate if you use Full or Full (strict). Finally, look for a security tool refusing Cloudflare addresses: an .htaccess allowlist, a Require ip directive, a host firewall, or fail2ban.

Cloudflare error 522 with nginx: where should I look first?

At saturation and at keepalives, in that order. When nginx exhausts worker_connections, new connections pile up in the kernel accept queue and never get answered, which is exactly what a 522 describes. Check the Recv-Q column of ss -ltn on port 443 and the nginx error log for worker_connections or "too many open files". Then confirm keepalive_timeout is not set to 0, because Cloudflare documents disabled origin keepalives as a cause of 522. If nginx itself is up but the PHP-FPM or Node upstream is down, you get a 502 passed through to the visitor, not a 522.

Why does Cloudflare Pages return a 522 error?

On a Pages project, a 522 is nearly always a custom domain that is not wired correctly. Cloudflare's documentation asks you to verify that the custom domain has been added to the project and that the CNAME record points to that custom Pages domain. A CNAME left pointing at an old host, or a domain never registered on the project side, produces a 522 even though there is no origin server of your own anywhere in the picture.

Can a Cloudflare Worker return error code 522?

Yes, and the documented case is counter-intuitive: a Worker deployed on a Custom Domain that performs a fetch to its own hostname causes a 522, because the request loops back into the Worker instead of reaching an origin. Cloudflare suggests using a Route instead of a Custom Domain, targeting another hostname, or enabling the global_fetch_strictly_public compatibility flag. An Origin Rule pointing at a hostname that cannot be resolved produces the same code. A slow third-party API is a different story: Cloudflare documents no set time limit on an individual subrequest, so what you usually see there is a hanging request or an error your own code returns.

Why do I get Cloudflare error 522 with a VPN?

A 522 is decided between Cloudflare and the origin, so the visitor's connection does not normally change whether the origin answers. Check the code on the page first: shared VPN exit addresses usually trigger a Managed Challenge, a CAPTCHA or a 1020 page, not a 522. The one case that is genuinely yours to fix is a partial allowlist: a VPN moves your exit point, another Cloudflare data center serves you, it contacts your origin from a different address, and a stale allowlist rejects it. If the page is fine from a phone on mobile data and broken only through one VPN, the site is not the problem.

What is a Cloudflare 522 host error?

It is not a separate code. The Cloudflare 522 error page shows three segments, your browser, the Cloudflare data center, and your host, and it marks the host segment as the failing one. People search for "522 host error" because that is the wording on the screen. The diagnosis is the same as for any 522: the edge could not get a usable answer from your origin.

Why do 522 errors appear only at certain times of day?

Because the cause is a limit being crossed, not a permanent block. Traffic bursts exhaust a connection budget, a fail2ban threshold triggers after repeated connections, or the host firewall applies rate limiting that only kicks in under load. Sampling the error rate over a full day usually reveals the pattern.

Is the usual Reddit advice on error 522 correct?

The two answers that dominate those threads, allow the Cloudflare IP ranges and open a ticket with your host, are both right most of the time, and both skip a step. Allowlisting only helps if you apply the current list at every layer including IPv6, and a host ticket only goes somewhere if you bring the exact code, the timestamp with its timezone and the URL, which is precisely what Cloudflare asks you to provide. Two pieces of advice in those threads are worth ignoring: pausing Cloudflare hides the symptom without telling you anything, and switching SSL/TLS to Flexible trades a 522 for a redirect loop.

Do I need a paid Cloudflare plan to fix 521, 522, or 524?

No. These three errors are generated by the edge based on the origin's behavior, and the fix always lives on your infrastructure: firewall rules, listening ports, or application performance. The Cloudflare IP lists are public and usable on every plan, including Free. Higher plans change the support you get, not the nature of the fix. The single exception is raising the 524 timeout, which is an Enterprise setting.

Can the 125-second limit behind error 524 be increased?

Only on Enterprise zones, where the Proxy Read Timeout can be raised up to 6,000 seconds through a Cache Rule or the zone settings API. On every other plan the limit is fixed, so the practical options are to make the endpoint faster, return a job identifier and poll for the result, cache the expensive response, or move the long-running endpoint to a DNS-only subdomain.

Do these errors affect my search rankings?

Repeated errors during crawls are read as instability, and pages that consistently return 5xx can be dropped from the index. Availability and caching usually have to be fixed together; our guide on cache optimization shows how to absorb traffic spikes at the edge so fewer requests ever reach a fragile origin.

Is your website experiencing unexplained intermittent downtime?

CF Garage audits the connectivity pipeline between Cloudflare and your origin, pinpoints the root cause, and locks down stable uptime. Fixed pricing, risk-free configuration.

View our offers

Related topics