HTTP

Status Code

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.

8 min read intermediate Try in Playground

TL;DR: Cloudflare received an invalid or empty response from your origin server. Check origin server logs and ensure it returns valid HTTP responses.

What is 520 Web Server Returned an Unknown Error?

A 520 Web Server Returned an Unknown Error is a Cloudflare-specific status code that indicates the origin server returned an unexpected, empty, or unidentified response to Cloudflare. Think of it like a translator receiving gibberish from someone—they can’t relay the message because they can’t understand what was said.

This error is not part of the official HTTP specification but is used by Cloudflare’s edge servers when they receive an abnormal response from your origin server.

When Does This Happen?

You’ll see a 520 error in these common situations:

1. Empty Response from Origin

Cloudflare sends request to origin
→ Origin returns empty response (no headers, no body)
→ Cloudflare returns 520 to client

2. Malformed HTTP Response

Origin sends invalid HTTP format
→ Missing status line or malformed headers
→ Cloudflare can't parse response
→ Returns 520

3. Origin Server Crash

Request reaches origin server
→ Server crashes mid-response
→ Connection closes unexpectedly
→ Cloudflare returns 520

4. Protocol Mismatch

Cloudflare uses HTTP/1.1
→ Origin responds with incompatible protocol
→ Cloudflare can't process response
→ Returns 520

5. Premature Connection Close

Origin starts sending response
→ Connection terminates before completion
→ Cloudflare receives incomplete response
→ Returns 520

Example Responses

Basic 520 Response:

HTTP/1.1 520 Web Server Returned an Unknown Error
Server: cloudflare
Date: Sat, 18 Jan 2026 10:00:00 GMT
Content-Type: text/html
CF-RAY: 7d1234567890abcd-LAX

<!DOCTYPE html>
<html>
<head>
  <title>520: Web Server Returned an Unknown Error</title>
</head>
<body>
  <h1>Web server is returning an unknown error</h1>
  <p>There is an unknown connection issue between Cloudflare and the origin web server.</p>
  <p>As a result, the web page can not be displayed.</p>
  <p>Ray ID: 7d1234567890abcd</p>
  <p>Your IP: 203.0.113.42</p>
</body>
</html>
```text

**Detailed Cloudflare Error Page:**

```http
HTTP/1.1 520 Web Server Returned an Unknown Error
Server: cloudflare
CF-RAY: 7d1234567890abcd-SJC
CF-Cache-Status: DYNAMIC
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Error 520 - Web server is returning an unknown error</title>
  <style>
    body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
           max-width: 800px; margin: 50px auto; padding: 20px; }
    .error-code { font-size: 72px; color: #cf6a4c; font-weight: bold; }
    .ray-id { background: #f4f4f4; padding: 10px; margin: 20px 0; font-family: monospace; }
  </style>
</head>
<body>
  <div class="error-code">520</div>
  <h1>Web server is returning an unknown error</h1>

  <p>There is an unknown connection issue between Cloudflare and the origin web server.
  As a result, the web page can not be displayed.</p>

  <div class="details">
    <h2>What happened?</h2>
    <p>Cloudflare attempted to connect to your origin server, but received an invalid or
    unexpected response.</p>

    <h2>What can I do?</h2>
    <p><strong>If you're a visitor of this website:</strong></p>
    <ul>
      <li>Try again in a few minutes</li>
      <li>Contact the website owner if the issue persists</li>
    </ul>

    <p><strong>If you're the owner of this website:</strong></p>
    <ul>
      <li>Check your origin server's error logs</li>
      <li>Ensure your origin server is responding correctly to Cloudflare requests</li>
      <li>Verify your origin server isn't blocking Cloudflare IPs</li>
      <li>Review Cloudflare Analytics for traffic patterns</li>
      <li>Contact your hosting provider for server issues</li>
    </ul>
  </div>

  <div class="ray-id">
    <strong>Cloudflare Ray ID:</strong> 7d1234567890abcd<br>
    <strong>Your IP:</strong> 203.0.113.42<br>
    <strong>Timestamp:</strong> 2026-01-18 10:00:00 UTC
  </div>

  <div class="links">
    <a href="https://www.cloudflare.com/5xx-error-landing">Cloudflare Error Information</a> |
    <a href="https://community.cloudflare.com">Cloudflare Community</a>
  </div>
</body>
</html>

Real-World Example

Imagine a scenario where your origin server has a misconfiguration:

Client Request to Cloudflare:

GET /api/users HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0...
Accept: application/json
CF-Connecting-IP: 203.0.113.42
```http

**Cloudflare Forwards to Origin:**

```http
GET /api/users HTTP/1.1
Host: origin.example.com
X-Forwarded-For: 203.0.113.42
CF-RAY: 7d1234567890abcd
CF-Visitor: {"scheme":"https"}

Origin Returns Malformed Response:

[Empty response - no status line, no headers]
[Connection closed abruptly]

Cloudflare Returns 520 to Client:

HTTP/1.1 520 Web Server Returned an Unknown Error
Server: cloudflare
Date: Sat, 18 Jan 2026 10:00:00 GMT
Content-Type: text/html; charset=UTF-8
CF-RAY: 7d1234567890abcd-LAX
CF-Cache-Status: DYNAMIC

<!DOCTYPE html>
<html>
<head><title>520: Web Server Returned an Unknown Error</title></head>
<body>
  <h1>Web server is returning an unknown error</h1>
  <p>Error 520 indicates that Cloudflare successfully connected to your origin server,
  but the origin returned an invalid HTTP response.</p>

  <h2>Troubleshooting Steps:</h2>
  <ol>
    <li>Check your origin server error logs at the following timestamp: 2026-01-18 10:00:00 UTC</li>
    <li>Look for Ray ID: 7d1234567890abcd in your logs</li>
    <li>Verify your web server (Apache, Nginx, etc.) is running correctly</li>
    <li>Check for any recent configuration changes</li>
    <li>Ensure your origin isn't blocking Cloudflare IPs</li>
  </ol>

  <p>Ray ID: 7d1234567890abcd • Your IP: 203.0.113.42</p>
</body>
</html>
```text

## 520 vs Other Cloudflare Errors

| Code    | Meaning              | Origin Status          | Issue Location         |
| ------- | -------------------- | ---------------------- | ---------------------- |
| **520** | Unknown error        | Responding but invalid | Origin response format |
| **521** | Web Server Is Down   | Not responding         | Origin offline         |
| **522** | Connection Timed Out | Timeout                | Network/origin slow    |
| **523** | Origin Unreachable   | Can't connect          | DNS/routing            |
| **524** | Timeout Occurred     | Processing too long    | Origin processing      |

## Important Characteristics

**Cloudflare-Specific:**

```text
Not in official HTTP spec
Used only by Cloudflare
Won't appear without Cloudflare proxy
```text

**Origin is Reachable:**

```text
Cloudflare successfully connected to origin
Origin is online and accepting connections
But response is malformed or empty
```text

**Includes Ray ID:**

```http
CF-RAY: 7d1234567890abcd-LAX
         ↑                  ↑
    Unique identifier   Data center

Indicates Origin Issue:

520 = Problem is at your origin server
NOT a Cloudflare infrastructure issue
NOT a client/browser issue

Common Causes

1. Web Server Crash:

# Origin server crashes during response
Jan 18 10:00:00 kernel: nginx[1234]: segmentation fault
Jan 18 10:00:00 systemd: nginx.service: Main process exited
```text

**2. Empty Response:**

```php
<?php
// Bad: Script exits without output
if ($error) {
    exit(); // No headers, no body 520
}

3. Malformed Headers:

HTTP/1.1 200 OK
Content-Type text/html  ← Missing colon
Content-Length: 1234

[body]

4. Connection Dropped:

# Server closes connection prematurely
import socket

s = socket.socket()
s.accept()
s.close()  # Closed without sending response → 520
```text

**5. Firewall Blocking Cloudflare:**

```bash
# Origin firewall blocking Cloudflare IPs
iptables -A INPUT -s 173.245.48.0/20 -j DROP
# Cloudflare can connect but gets RST → 520

Troubleshooting Steps

1. Check Origin Error Logs:

# Nginx
tail -f /var/log/nginx/error.log

# Apache
tail -f /var/log/apache2/error.log

# Node.js
journalctl -u myapp.service -f
```text

**2. Test Origin Directly:**

```bash
# Bypass Cloudflare and test origin
curl -v https://origin.example.com/

# Should return valid HTTP response

3. Check for Empty Responses:

# Test if origin returns anything
curl -i https://origin.example.com/ | head -20

# Should see HTTP status line and headers
```text

**4. Verify Cloudflare IPs Not Blocked:**

```bash
# Test from Cloudflare IP range
curl --interface 173.245.48.1 https://origin.example.com/

# Should not be blocked

5. Review Recent Changes:

# Check recent configuration changes
git log --since="24 hours ago" -- nginx.conf
git log --since="24 hours ago" -- apache2.conf
```javascript

## Best Practices

**Implement Proper Error Handling:**

```javascript
// Express.js - Always send valid HTTP response
app.use((err, req, res, next) => {
  console.error('Error:', err)

  // Always send proper HTTP response
  res.status(500).json({
    error: 'Internal Server Error',
    message: 'An unexpected error occurred'
  })

  // Don't let server crash or close connection
})

Monitor Origin Health:

// Health check endpoint
app.get('/health', (req, res) => {
  res.status(200).json({
    status: 'healthy',
    timestamp: new Date().toISOString()
  })
})

// Cloudflare can monitor this endpoint
```javascript

**Log Cloudflare Ray IDs:**

```javascript
app.use((req, res, next) => {
  const rayId = req.headers['cf-ray']
  const connectingIp = req.headers['cf-connecting-ip']

  // Log for correlation with 520 errors
  console.log(`CF-RAY: ${rayId}, IP: ${connectingIp}`)

  next()
})

Ensure Complete Responses:

# Django - Always return complete response
from django.http import HttpResponse

def my_view(request):
    try:
        data = process_request()
        return HttpResponse(data, content_type='application/json')
    except Exception as e:
        # Always return valid HTTP response, never crash
        return HttpResponse(
            json.dumps({'error': str(e)}),
            status=500,
            content_type='application/json'
        )
```text

**Whitelist Cloudflare IPs:**

```nginx
# Nginx - Allow Cloudflare IPs
# https://www.cloudflare.com/ips/

# IPv4
allow 173.245.48.0/20;
allow 103.21.244.0/22;
allow 103.22.200.0/22;
# ... more ranges

# Deny all others (optional)
# deny all;

Implementation Examples

Express.js Error Handler:

const express = require('express')
const app = express()

// Ensure all responses are valid
app.use((req, res, next) => {
  // Override res.end to ensure headers sent
  const originalEnd = res.end

  res.end = function (chunk, encoding) {
    if (!res.headersSent) {
      res.status(200) // Ensure status sent
    }
    originalEnd.call(this, chunk, encoding)
  }

  next()
})

// Your routes...

// Final error handler
app.use((err, req, res, next) => {
  console.error('Error:', err)
  console.log('CF-RAY:', req.headers['cf-ray'])

  if (!res.headersSent) {
    res.status(500).json({
      error: 'Internal Server Error',
      ray_id: req.headers['cf-ray']
    })
  }
})

app.listen(3000)
```nginx

**Nginx Configuration:**

```nginx
# Ensure Nginx always returns valid response
http {
    # Increase timeouts to prevent abrupt closures
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;

    # Always send error page, never close connection
    proxy_intercept_errors on;

    server {
        listen 80;
        server_name origin.example.com;

        location / {
            # Your application
            proxy_pass http://localhost:3000;

            # Ensure headers always sent
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # Custom error pages
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;
        }
    }
}

Apache Configuration:

# Ensure Apache handles errors gracefully
<VirtualHost *:80>
    ServerName origin.example.com

    # Custom error documents
    ErrorDocument 500 /errors/500.html

    # Ensure headers always sent
    Header always set Content-Type "text/html"

    # Application
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>
```javascript

## Monitoring and Alerting

**Set Up Cloudflare Analytics:**

```javascript
// Monitor 520 errors via Cloudflare API
const checkCloudflareErrors = async () => {
  const response = await fetch(
    'https://api.cloudflare.com/client/v4/zones/ZONE_ID/analytics/dashboard',
    {
      headers: {
        'X-Auth-Email': 'your@email.com',
        'X-Auth-Key': 'your-api-key'
      }
    }
  )

  const data = await response.json()
  const error520Count = data.result.totals.requests.http_status['520'] || 0

  if (error520Count > threshold) {
    alert('High number of 520 errors detected!')
  }
}

Try It Yourself

Visit our request builder to understand 520 errors:

  1. Learn about 520 error causes
  2. See example scenarios
  3. Review troubleshooting steps
  4. Understand origin server requirements

Frequently Asked Questions

What does Cloudflare error 520 mean?

A 520 error means Cloudflare received an empty, unknown, or unexpected response from your origin server. The connection was made but the response was invalid.

How do I fix a 520 error?

Check your origin server logs for errors, ensure your server returns valid HTTP responses, verify firewall rules allow Cloudflare IPs, and check for application crashes.

What causes 520 errors?

Common causes include origin server crashes, empty responses, connection resets, response headers exceeding limits, or the origin closing the connection unexpectedly.

Is 520 a standard HTTP status code?

No, 520 is a Cloudflare-specific error code. It indicates issues between Cloudflare and your origin server that do not map to standard HTTP status codes.

Keep Learning