ByteScope

521

How to fix HTTP 521 Web Server Is Down

5xx server errorNon-standardCloudflare

Cloudflare's own code, not an IETF one, for the narrowest failure in the whole 5xx range: your origin actively refused Cloudflare's TCP connection, so nothing was slow and nothing was misrouted — something said no.

Why you are seeing 521, and what to do about it

The same three digits are three different problems depending on which side of the request you are on. Read the block that describes you.

Reproduce 521 with curl

Run this against the URL that failed. It prints the status without the error page, so you can see what the server said rather than what the browser rendered.

curl
curl -sS -o /dev/null --connect-timeout 5 -w '\n%{http_code} connect=%{time_connect}s\n' --resolve example.com:443:203.0.113.10 https://example.com/

`--resolve` makes curl connect to the address you name while still sending the original host name and SNI, so this reproduces what Cloudflare does when it dials your origin, with the edge taken out of the path — put your real origin address in place of the example one. `--connect-timeout 5` keeps a refusal fast and, just as usefully, separates it from a silent drop. There are three outcomes and each is a different bug. `curl: (7) Failed to connect to example.com port 443: Connection refused` is the reproduction: the origin refused you exactly as it refused Cloudflare, and the answer is on the origin — no listener, wrong bind address, wrong port, or a firewall set to reject. A hang that ends at the five-second connect timeout is not a 521 at all; a dropped SYN is what Cloudflare reports as 522, so a DROP rule and a REJECT rule on the same firewall produce two different error numbers. And a normal response means the origin accepts connections from you but not from Cloudflare, which points squarely at source-address filtering rather than at the service — check the origin firewall against Cloudflare's published IP ranges. Run the same request without `--resolve` afterwards to see the edge's answer and read the `cf-ray` header, which is the id an operator can look up.

What 521 actually means

521 is not in RFC 9110. The IETF's registered 5xx codes stop at 511, and the 520-526 range is Cloudflare's own extension, documented only by Cloudflare and produced only for traffic proxied through it — a DNS record that is grey-clouded cannot return one. Cloudflare defines the code exactly: error 521 occurs when the origin web server refuses connections from Cloudflare. That word "refuses" is the entire value of the number. A refusal is an answer — a TCP RST, or an ICMP unreachable — which means the packet reached the origin's network and something there declined it, and that rules out three neighbouring codes in one step. It is not 522, which Cloudflare defines as a timeout: no SYN+ACK within 19 seconds of Cloudflare's SYN, or no acknowledgement of the request within 90 seconds after the connection is established. It is not 523, which Cloudflare defines as being unable to contact the origin at all, typically because a network device between them has no route to the origin's address. And it is not 520, which is the origin answering with something empty, unknown or unexpected. Cloudflare lists two causes for 521 — an offlined origin web server application, and blocked Cloudflare requests — and the resolutions follow from them: ensure the origin is responsive, review its error logs for application crashes or outages, confirm Cloudflare's IP addresses are not blocked or rate limited, allow all Cloudflare IP ranges in the origin's firewall or other security software, and ensure the origin is actively bound and listening on the port your SSL/TLS mode requires — port 80 for Flexible, port 443 for Full and Full (Strict). That last item catches the case people spend longest on, because Cloudflare only proxies a fixed set of ports: 80, 8080, 8880, 2052, 2082, 2086 and 2095 for HTTP, and 443, 2053, 2083, 2087, 2096 and 8443 for HTTPS. An origin listening anywhere else is unreachable by the proxy no matter how healthy it is.

Codes 521 gets mistaken for

Confused withHow to tell them apart
522Both mean Cloudflare could not get a working connection to your origin, and the difference is whether the origin answered. 521 is a refusal, which is an answer and therefore instant. 522 is a timeout, which Cloudflare defines precisely: no SYN+ACK within 19 seconds of its SYN, or no acknowledgement of its request within 90 seconds after the connection is up. The same firewall rule produces one or the other depending on REJECT versus DROP.
523523 is Cloudflare being unable to contact the origin at all, which its documentation attributes to a network device between them having no route to the origin's address. Their worked example is an AWS route table where an over-broad `172.0.0.0/8` entry swallows Cloudflare's own `172.64.0.0/13` range and sends the return traffic somewhere private. So 521 means the packets arrived and were refused; 523 means they never got there.
520520 is the origin answering with something Cloudflare cannot use — empty, unknown or unexpected, including response headers above Cloudflare's 128 KB limit, which excessive cookies reach more often than people expect. That is the opposite end of the connection from 521: with 520 the handshake, the request and a response all happened, and only the content of the response was wrong.
502502 is the IETF code any proxy may return for an invalid response from an inbound server, and it covers refusals, resets and unparseable replies all at once. 521 is Cloudflare narrowing that same class down to one cause, which is the reason the 520-526 range exists: a generic 502 leaves you checking four things, while a 521 tells you the origin refused the connection and sends you straight to the listener and the firewall.
524524 is the reassuring one by comparison, because it proves the connection succeeded: Cloudflare connected to the origin and then waited 125 seconds for an HTTP response that never came. So 524 rules out every question 521 raises — the listener is up, the port is right, the firewall is letting Cloudflare through — and moves the whole investigation into the application.
Reason phrase
Web Server Is Down
Class
5xx server error
Defined by
Cloudflare
Standard
Non-standard

Tools on this site

All of these run in your browser — nothing is uploaded.

Related status codes

Codes people usually end up reading in the same session as 521.

Frequently asked questions

How do I find out which server produced this status code?

Read the response headers rather than the page. curl -sS -o /dev/null -D - https://example.com/path prints them without the body, and server, via and cf-ray between them name the layer that answered. A cf-ray value means Cloudflare handled the response and is the id their support will ask for. To take the edge out of the picture entirely, repeat the request with --resolve example.com:443:203.0.113.10, which connects to the origin address you name while still sending the original host name and SNI — if the answer changes, the edge and the origin disagree.

Does the reason phrase after the number matter?

No, and you should never branch on it. RFC 9112 tells clients to ignore the reason phrase, servers are free to change it, and HTTP/2 and HTTP/3 do not carry one at all — so 404 Not Found over HTTP/1.1 arrives as a bare 404 over HTTP/2. The phrases on this site are the registered ones because they are what people search for and what appears in an HTTP/1.1 log, not because any software depends on them.

Should I retry a request that failed with this code?

Retry 5xx and 429; do not retry 4xx, because nothing about the request will be different next time. If the response carries Retry-After, honour it — RFC 9110 defines it for exactly this, and it may be either a number of seconds or a date. Otherwise use exponential backoff with jitter and a hard cap, and only for idempotent methods: a retried POST can charge a card twice. A retry storm against a server that is already failing is how a brief incident becomes a long one.

Can I make my server return a different status code?

Yes, and the only rule that matters is that the code has to be true. Anything that reads your responses automatically — search engines, monitoring, caches, client retry logic — makes decisions from the number and never from the page. Serving an error page with 200 hides the failure from your own alerting; serving 200 for a missing page gets the error indexed as content; returning 500 for a request that was simply malformed sends whoever is on call to the wrong half of the stack.

Still stuck on 521? browse every status code in the reference — or go back up to the block written for your side of the stack.