# 520 Web Server Returned an Unknown Error

> Cloudflare-specific error when the origin server returns an unexpected response. Learn about 520 errors and how to troubleshoot them.

Source: https://howhttpworks.com/status-codes/520
Last reviewed: 2026-10-04

> **TL;DR:** Cloudflare reached your origin but got something it could not use: an empty reply, a reset connection, malformed or oversized headers. Reproduce against the origin IP with `curl --resolve`, then read the origin's own error log for a crash or reset at the same timestamp.

## What it means

520 is Cloudflare's catch-all for "the origin connection succeeded but the response was invalid". It is not an HTTP standard code and the origin never sends it; it exists only when Cloudflare proxies the site. Documented triggers include:

- The origin closed the connection or reset it (TCP RST) before sending a complete response.
- An empty response: no status line, no headers, no body.
- Response headers larger than 32 KB, or more than 100 headers. Runaway `Set-Cookie` headers are the classic cause.
- Malformed headers (missing colon, invalid characters) or an invalid status line.
- The origin process crashing mid-request (PHP-FPM segfault, OOM kill, worker timeout in gunicorn/uWSGI).

Browsers show Cloudflare's own page titled "Web server is returning an unknown error", with a Ray ID.

```http
HTTP/2 520
server: cloudflare
cf-ray: 8a1b2c3d4e5f6789-LHR
content-type: text/html; charset=UTF-8
```

## Who sent it?

`server: cloudflare` plus a `cf-ray` header means the edge generated the error. If the 520 only occurs through Cloudflare and the origin answers normally when hit directly, suspect headers, firewall or keepalive handling. Match the Ray ID against your origin logs to find the failing request.

## Fix it

1. **Hit the origin directly**, bypassing Cloudflare:

   ```bash
   curl -sv --resolve example.com:443:203.0.113.10 https://example.com/path -o /dev/null
   ```

   Look for `Empty reply from server` or `Connection reset by peer`; both confirm the origin is the problem.

2. **Read the origin log** at the Ray ID timestamp: nginx `error.log` (`upstream prematurely closed connection`, `recv() failed (104: Connection reset by peer)`), `dmesg | grep -i 'killed process'` for OOM, PHP-FPM or gunicorn logs for crashes and worker timeouts.
3. **Measure header size.** Over 32 KB total or 100+ headers triggers 520.

   ```bash
   curl -s -D - -o /dev/null https://origin.example.com/ | wc -c
   ```

   Fix cookie loops, trim `Set-Cookie`, `Link` or custom debug headers.
4. **Check the firewall and connection limits.** Fail2ban, ModSecurity, `iptables` rate limits or CSF may reset Cloudflare edge IPs because many requests share a few addresses. Allow Cloudflare ranges from `https://www.cloudflare.com/ips-v4` and `ips-v6`.
5. **Check keepalive mismatches.** If the origin closes idle connections more aggressively than Cloudflare reuses them, a request can hit a closed socket. Raise `keepalive_timeout` on nginx (for example `keepalive_timeout 75s;`) above Cloudflare's idle behavior, and in Apache keep `KeepAlive On`.
6. **Application crashes.** Fix the underlying fatal error; make sure the framework returns a real 500 response rather than exiting without output (PHP `exit()` before headers, Node `process.exit()` in a request handler).
7. **Pause Cloudflare** (grey-cloud the DNS record) briefly to see if the origin alone serves correctly.

### nginx pointer

```nginx
# Keep upstream responses bounded and log what the origin saw
large_client_header_buffers 4 16k;
log_format cf '$remote_addr cf-ray=$http_cf_ray "$request" $status $upstream_status';
access_log /var/log/nginx/access.log cf;
```

## 520 vs the other Cloudflare 52x errors

| Code | Origin behavior                                                |
| ---- | -------------------------------------------------------------- |
| 520  | Connected, but the response was empty, reset or malformed      |
| 521  | Connection refused (nothing listening, or blocked)             |
| 522  | TCP connection or response acknowledgement timed out           |
| 523  | Origin unreachable (DNS or routing)                            |
| 524  | Connected, but no HTTP response within 125 seconds (default)   |

If the origin itself sends a normal 500 or 502, Cloudflare passes it through as-is; see [500](https://howhttpworks.com/status-codes/500) and [502](https://howhttpworks.com/status-codes/502).

## Related

- [521 Web Server Is Down](https://howhttpworks.com/status-codes/521)
- [522 Connection Timed Out](https://howhttpworks.com/status-codes/522)
- [523 Origin Is Unreachable](https://howhttpworks.com/status-codes/523)
- [524 A Timeout Occurred](https://howhttpworks.com/status-codes/524)
- [502 Bad Gateway](https://howhttpworks.com/status-codes/502)
- [525 SSL Handshake Failed](https://howhttpworks.com/status-codes/525)
- [526 Invalid SSL Certificate](https://howhttpworks.com/status-codes/526)
