Web Server Is Down
ActiveHTTP 521 Web Server Is Down is a Cloudflare-specific status code indicating the origin server actively refused the TCP connection. Not defined in any RFC. Cloudflare attempted to connect but the origin rejected it at the transport layer — the server is stopped, crashed, or firewalling Cloudflare IPs.
Description
The 521 Web Server Is Down status code is a proprietary error returned by Cloudflare's reverse proxy when it cannot establish a TCP connection to the origin server because the connection was actively refused. This is distinct from a timeout — the origin's network stack explicitly sent a TCP RST or ICMP port-unreachable in response to Cloudflare's SYN packet.
The most common cause is that the origin web server process (nginx, Apache, Caddy, Node.js, etc.) has stopped running or crashed. When no process is listening on the configured port (typically 80 or 443), the operating system's kernel rejects incoming connections immediately with a RST packet. Cloudflare receives this rejection and surfaces it to the end user as a 521.
Another frequent cause is firewall misconfiguration at the origin. If the origin server's firewall (iptables, ufw, security groups, etc.) blocks Cloudflare's IP ranges, connection attempts are refused before they reach the web server process. Cloudflare publishes their IP ranges at cloudflare.com/ips, and these must be explicitly whitelisted in any origin firewall rules.
The 521 is fundamentally different from its siblings in Cloudflare's 5xx range. A 520 means the origin responded but with an unexpected or malformed response that Cloudflare couldn't parse. A 522 means the origin didn't respond at all — the TCP handshake timed out. A 523 means the origin is unreachable at the DNS level. The 521 specifically means: the origin is reachable at the network layer, but actively said 'no' at the transport layer.
To resolve a 521: verify the origin web server is running and listening on the correct port, ensure Cloudflare's published IP ranges are allowed through any firewalls or security groups, confirm the server isn't binding only to localhost (127.0.0.1) instead of all interfaces (0.0.0.0), and verify the port configured in Cloudflare's DNS settings matches what the origin is actually listening on.
Examples
HTTP/1.1 521 Web Server Is Down
Server: cloudflare
Date: Mon, 15 Jan 2024 10:30:00 GMT
Content-Type: text/html; charset=UTF-8
CF-RAY: 8a1b2c3d4e5f6g7h-SJC
<!DOCTYPE html>
<html>
<head><title>521 Web Server Is Down</title></head>
<body>
<h1>Web server is down</h1>
<p>The web server is not returning a connection.</p>
</body>
</html># Cloudflare's perspective (conceptual):
# SYN → origin:443
# ← RST from origin (nothing listening on port 443)
# Result: 521 returned to visitor
# Verify on origin:
$ ss -tlnp | grep ':443'
# (empty — nothing listening)
$ systemctl status nginx
● nginx.service - A high performance web server
Active: inactive (dead) since Mon 2024-01-15 10:25:00 UTC# Check if Cloudflare IPs are allowed:
$ iptables -L INPUT -n | grep -c '173.245.48'
0
# Cloudflare IPv4 ranges that must be whitelisted:
# 173.245.48.0/20
# 103.21.244.0/22
# 103.22.200.0/22
# 103.31.4.0/22
# 141.101.64.0/18
# 108.162.192.0/18
# 190.93.240.0/20
# 188.114.96.0/20
# 197.234.240.0/22
# 198.41.128.0/17
# 162.158.0.0/15
# 104.16.0.0/13
# 104.24.0.0/14
# 172.64.0.0/13
# 131.0.72.0/22
# Fix: Allow all Cloudflare IPs
$ for ip in $(curl -s https://www.cloudflare.com/ips-v4); do
ufw allow from $ip to any port 443
done# Problem: server listening on 127.0.0.1 only
$ ss -tlnp | grep ':443'
LISTEN 0 511 127.0.0.1:443 *:* users:(("nginx",pid=1234,fd=6))
# Cloudflare connects to the public IP, not localhost
# Connection is refused because nginx only accepts local connections
# Fix in nginx.conf:
# WRONG: listen 127.0.0.1:443 ssl;
# RIGHT: listen 0.0.0.0:443 ssl;
# Fix in Docker:
# WRONG: ports: ["127.0.0.1:443:443"]
# RIGHT: ports: ["0.0.0.0:443:443"]# Every Cloudflare response includes CF-RAY for support tickets
# Format: CF-RAY: {ray-id}-{colo}
HTTP/1.1 521 Web Server Is Down
Server: cloudflare
CF-RAY: 8a1b2c3d4e5f6g7h-SJC
X-Cloudflare-Error: 1016
# SJC = San Jose data center (where Cloudflare tried from)
# Use this ray ID when filing support tickets or checking logs# Test if origin accepts connections on the expected port:
$ curl -svo /dev/null --connect-timeout 5 https://origin-ip:443
* Connecting to origin-ip port 443
* connect to origin-ip port 443 failed: Connection refused
# Test with specific Cloudflare IP as source (if possible):
$ curl -svo /dev/null --interface 172.64.x.x https://origin-ip:443
# Check origin from the server itself:
$ curl -svo /dev/null https://localhost:443
* Connected to localhost (127.0.0.1) port 443
> GET / HTTP/1.1
< HTTP/1.1 200 OKEdge Cases
- •A 521 can appear intermittently if the origin web server is crashing and restarting in a loop — connections are refused during the restart window but succeed once the process is back up.
- •Docker containers with incorrect port mappings (binding to 127.0.0.1 inside the container or mapping to wrong host ports) are one of the most common causes of 521s that are hard to debug because the server appears running locally.
- •If Cloudflare's DNS is set to 'Proxied' (orange cloud) but the origin only accepts direct connections on a non-standard port, Cloudflare will try port 80/443 by default and get refused — configure the correct port in Cloudflare's Origin Rules.
- •Load balancers between Cloudflare and the origin can mask the real issue: the LB might accept the connection from Cloudflare but then fail to connect to the backend, sometimes surfacing as 521 depending on LB configuration.
- •Rate limiting at the origin firewall level (too many connections from Cloudflare IPs) can trigger intermittent 521s under high traffic — Cloudflare sends all visitor traffic from a small set of IP ranges, which looks like a DDoS to naive rate limiters.
- •IPv6 misconfiguration: if the origin has an AAAA record in Cloudflare but the origin server only listens on IPv4, Cloudflare may attempt an IPv6 connection that gets refused.
- •Some hosting providers (especially shared hosting) block connections from known CDN/proxy IP ranges by default as an anti-abuse measure — this must be explicitly overridden.
When You'll See This
- →Origin nginx/Apache process crashed or was stopped by systemd due to OOM kill
- →Server reboot completed but web server service didn't auto-start
- →Origin firewall rules were updated and accidentally dropped Cloudflare IP ranges
- →Docker container exited or port mapping changed during deployment
- →Wrong port configured in Cloudflare DNS — origin listens on 8443 but Cloudflare connects to 443
- →Origin server binding changed to localhost-only after a config update
- →Hosting provider suspended the account or disabled the web service
- →SSL certificate renewal script restarted nginx and it failed to come back up due to config error
- →Kubernetes pod was evicted and the service has no healthy endpoints
- →Security group or network ACL change in AWS/GCP/Azure blocked inbound from Cloudflare ranges
Implementation References
| Language | Constant |
|---|---|
| Cloudflare Workers | 521 (not programmable — returned by edge when origin refuses) |
| Go | 521 (no stdlib constant — non-standard code) |
| Python (requests) | response.status_code == 521 (no named constant) |
| Node.js | res.statusCode === 521 (no http.STATUS_CODES entry) |
| Rust (reqwest) | response.status().as_u16() == 521 |
| curl | curl -o /dev/null -w '%{http_code}' → '521' |
| .NET (HttpClient) | (int)response.StatusCode == 521 (no HttpStatusCode enum value) |
| Java (HttpURLConnection) | connection.getResponseCode() == 521 (no named constant) |
History
The 521 status code was introduced by Cloudflare around 2010 as part of their custom 5xx error range (520-527) to provide more granular diagnostics for reverse proxy failures that standard HTTP status codes don't cover. The standard 502 Bad Gateway was too vague — it could mean anything from a parse error to a timeout to a refused connection. Cloudflare split these failure modes into distinct codes: 520 (unknown/parse error), 521 (connection refused), 522 (connection timed out), 523 (origin unreachable), 524 (response timed out), 525 (SSL handshake failed), 526 (invalid SSL certificate), and 527 (Railgun error). The 521 specifically addresses the TCP RST/connection-refused failure mode. These codes are not registered with IANA and are not part of any RFC — they exist solely within Cloudflare's ecosystem and are only visible to end users when Cloudflare is the reverse proxy. Other CDN providers (Fastly, AWS CloudFront, Akamai) handle the same failure mode differently, typically returning a generic 502 or 503 with provider-specific error pages.
Related Status Codes
Related Headers
FAQ
What causes a Cloudflare 521 error and how do I fix it?
A 521 means Cloudflare tried to connect to your origin server but the connection was actively refused (TCP RST). The three most common causes: (1) Your web server process (nginx, Apache, Node.js) has stopped — check with 'systemctl status nginx' or equivalent and restart it. (2) Your origin firewall is blocking Cloudflare's IP ranges — download the list from cloudflare.com/ips and whitelist all ranges in your firewall rules (iptables, ufw, security groups). (3) Your server is only listening on localhost (127.0.0.1) instead of all interfaces (0.0.0.0) — check with 'ss -tlnp' and update your server config to bind to 0.0.0.0 or the public IP.
What is the difference between Cloudflare 520, 521, 522, and 523 errors?
Each code represents a different failure mode in the Cloudflare-to-origin connection: 520 means the origin responded but with something Cloudflare couldn't parse (empty response, malformed headers, oversized headers). 521 means the TCP connection was actively refused — the origin said 'no' at the transport layer (nothing listening, or firewall rejected). 522 means the TCP connection timed out — the origin never responded to the SYN packet (network issue, overloaded server, packets being silently dropped). 523 means the origin is DNS-unreachable — Cloudflare couldn't even resolve the origin hostname. The key distinction: 521 is immediate rejection, 522 is silence/timeout.
Why do I only see 521 errors intermittently rather than constantly?
Intermittent 521s typically indicate one of these scenarios: (1) Your web server is crash-looping — it starts, serves a few requests, then crashes (check for OOM kills with 'dmesg | grep -i oom' or segfaults in error logs). (2) During deployments — the old process stops before the new one binds to the port, creating a window where connections are refused (use zero-downtime deployment strategies like socket activation or blue-green deploys). (3) Connection-level rate limiting at your firewall — Cloudflare sends all traffic from a small IP range, so naive per-IP rate limits trigger under load. (4) Multiple origin servers behind a load balancer where some backends are healthy and others are down — Cloudflare sees 521 when routed to a dead backend.