
A Cloudflare Error 520 means Cloudflare connected to your origin server, but the origin returned an empty, unexpected, or malformed response. It's Cloudflare's way of saying: "Your server responded, but I have no idea what it sent me."
This is one of the trickier Cloudflare errors to debug because it's a catch-all — any response that Cloudflare can't interpret gets classified as a 520. The root cause could be anything from a crashed application to oversized response headers.
When a visitor requests a page on a Cloudflare-proxied site, Cloudflare forwards the request to your origin server. Normally, your origin sends back a standard HTTP response. A 520 occurs when your origin server:
A 520 is distinct from other Cloudflare errors:
The most frequent cause. Your web application (PHP, Node.js, Python, Ruby) crashes while processing the request. It might start sending a response but die before completing it, or it might crash before sending anything at all.
# Check if your application process is running
sudo systemctl status php8.2-fpm
pm2 status
sudo systemctl status gunicorn
# Check application error logs
sudo tail -50 /var/log/nginx/error.log
sudo tail -50 /var/log/php-fpm/error.log
Your server accepts the connection but sends back zero bytes. This can happen when your application has an unhandled error that doesn't even generate an error page.
# Test the response directly (bypassing Cloudflare)
curl -v -H "Host: yourdomain.com" http://YOUR_ORIGIN_IP/
If you get an empty response or a connection reset, that confirms the 520 source.
Cloudflare has a limit on response header size (currently 32 KB). If your application sends excessively large headers — often caused by oversized cookies, too many Set-Cookie headers, or debug headers — Cloudflare can't process the response.
# Check the size of your response headers
curl -s -D - http://YOUR_ORIGIN_IP/ -o /dev/null | wc -c
Your server sends a response that doesn't follow HTTP standards. This can happen with custom-built servers, misconfigured proxies, or applications that manipulate raw response streams.
Your server accepts the TCP connection, receives the request, but then resets the connection (sends a TCP RST) instead of responding. Common causes:
# Check for OOM kills
sudo dmesg | grep -i "oom\|killed"
# Check system resources
free -h
top -bn1 | head -20
If your origin server's firewall doesn't allow Cloudflare's IP ranges, the connection may be accepted initially but blocked at the application level, resulting in empty or reset responses.
Bypass Cloudflare and hit your origin server directly to see what it returns:
# Replace with your actual origin IP
curl -v -H "Host: yourdomain.com" http://YOUR_ORIGIN_IP/
# Check for empty responses
curl -s -o /dev/null -w "Response code: %{http_code}\nSize: %{size_download} bytes\n" \
-H "Host: yourdomain.com" http://YOUR_ORIGIN_IP/
If the origin returns an empty response or an error directly, the problem is on your server, not Cloudflare.
# Restart common web services
sudo systemctl restart php8.2-fpm
sudo systemctl restart nginx
sudo systemctl restart apache2
# For Node.js apps
pm2 restart all
# For Python apps
sudo systemctl restart gunicorn
If large headers are the problem, reduce cookie sizes and remove unnecessary headers:
# Nginx - remove unnecessary proxy headers
proxy_hide_header X-Debug-Info;
proxy_hide_header X-Powered-By;
# Limit proxy header buffer size
proxy_buffer_size 16k;
proxy_buffers 4 16k;
Check your application for oversized cookies or excessive Set-Cookie headers and trim them down.
Ensure your firewall allows all Cloudflare IP ranges:
# Download current Cloudflare IP ranges
curl -s https://www.cloudflare.com/ips-v4 > /tmp/cf-ips.txt
curl -s https://www.cloudflare.com/ips-v6 >> /tmp/cf-ips.txt
# Add to iptables (example)
while read ip; do
sudo iptables -A INPUT -p tcp --dport 443 -s "$ip" -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -s "$ip" -j ACCEPT
done < /tmp/cf-ips.txt
# Memory
free -h
# Disk space
df -h
# CPU and process overview
top -bn1 | head -20
# Check for OOM events
sudo dmesg | tail -50 | grep -i "oom\|kill"
If your server is running out of memory, application processes get killed and connections reset — a direct path to 520 errors.
# Nginx
sudo tail -100 /var/log/nginx/error.log | grep -i "upstream\|reset\|abort\|broken"
# Apache
sudo tail -100 /var/log/apache2/error.log
Look for messages about upstream connections being reset, broken pipes, or segmentation faults.
A 520 error means your site is completely inaccessible to visitors behind Cloudflare — they see an error page instead of your content. Because the error originates from your origin server, it can be intermittent and hard to notice unless you're actively checking. Your origin might work fine for direct requests but fail under the specific conditions of a Cloudflare-proxied request.
Domain Monitor checks your site every minute from multiple locations, accessing it the same way real visitors do — through Cloudflare. If a 520 starts occurring, you'll get an alert via email, SMS, or Slack within seconds. You can set up downtime alerts so you're notified immediately, and website monitoring helps you track whether these errors are isolated incidents or recurring patterns that need deeper investigation.
| Cause | Fix |
|---|---|
| Application crash | Restart the app, check error logs |
| Empty response from origin | Debug the application, check process health |
| Headers too large | Reduce cookie/header sizes |
| Connection reset by origin | Check OOM kills, firewall rules |
| Cloudflare IPs not whitelisted | Add Cloudflare IP ranges to firewall |
| Malformed HTTP response | Fix application response formatting |
A 520 is Cloudflare's catch-all for "something is wrong with your origin's response." Start by testing your origin directly, check your application logs, and work through the causes systematically. The fix is almost always on your origin server.
Wildcard, SAN (multi-domain), and single-domain SSL certificates cover different use cases. Here's a clear comparison to help you pick the right type — and avoid paying for coverage you don't need.
Read moreDNS resolves correctly from your office but fails for users in other countries or on different ISPs. Here's why geographic DNS inconsistency happens and how to diagnose which layer is causing it.
Read moreRegistrar lock and transfer lock are often confused — and disabling the wrong one leaves your domain vulnerable. Here's a clear breakdown of what each does and when to use them.
Read moreLooking to monitor your website and domains? Join our platform and start today.