Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild
Back to Blog Troubleshooting

Cloudflare Error 500: Whose Server Actually Failed?

Sean

Platform Writer

Aug 10, 2026
7 min read

An error 500 served through Cloudflare is almost always your origin server failing — Cloudflare is passing along the status it received. This differs from Cloudflare’s own error codes, which live in the 520-530 range and mean the proxy itself could not complete the request. Telling the two apart is the first move and it takes one command.

Cloudflare Error 500: Whose Server Actually Failed?

The confusion is structural: two servers are involved and only one page is shown. Cloudflare’s branded error pages make people assume Cloudflare failed, when the far more common case is that your application failed and Cloudflare relayed the news.

Table of contents

Which 5xx codes mean what

The number tells you where to look, and the distinction is worth memorising.

  • 500, 502, 503, 504 without a Cloudflare-branded page — these came from your origin. Cloudflare proxied them unchanged. Debug your application.
  • 520 Web Server Returned an Unknown Error — the origin returned something Cloudflare could not parse: an empty response, a connection reset, or malformed headers.
  • 521 Web Server Is Down — Cloudflare could not open a TCP connection to your origin. Usually the service is stopped or a firewall is blocking Cloudflare’s IPs.
  • 522 Connection Timed Out — the TCP handshake did not complete in time. Typically a firewall dropping packets silently rather than rejecting them.
  • 523 Origin Is Unreachable — Cloudflare could not route to the origin at all. Usually a wrong DNS record or a deleted server.
  • 524 A Timeout Occurred — connection established, but the origin did not respond within 100 seconds. Your application is too slow, not down.
  • 525 / 526 — TLS handshake failed or the origin certificate is invalid. Almost always an SSL/TLS mode mismatch.

520 through 527 are Cloudflare’s own codes and are not standard HTTP. If you see one, the problem is between Cloudflare and your origin — which usually still means something on your side.

Proving where it came from

The decisive test is to bypass Cloudflare entirely and request the origin directly. If it fails there too, Cloudflare is not involved in your problem.

# What does the world see?
curl -sI https://example.com/ | head -20

# Talk to the origin directly, keeping the Host header and SNI
curl -sI https://example.com/ --resolve example.com:443:203.0.113.10

# Plain HTTP against the origin, skipping TLS as a variable
curl -sI http://203.0.113.10/ -H 'Host: example.com'

--resolve is the right tool here — it overrides DNS for that one request while keeping the Host header and TLS SNI intact, so your server routes it exactly as it would a real request. Editing /etc/hosts achieves the same thing more permanently and is easier to forget about.

  • Fails direct and through Cloudflare → your origin. Cloudflare is a bystander.
  • Works direct, fails through Cloudflare → configuration between them: SSL mode, a firewall rule, a Worker, or a page rule.
  • Works both ways but users report failures → intermittent, or specific to a region or a cached response.

Capture the cf-ray header from a failing response. It identifies that specific request in Cloudflare’s logs and is what support will ask for first.

Reading your origin’s logs, which is usually the answer

For a genuine 500, the detail is in your application, not at the edge. Cloudflare cannot tell you which line of PHP threw.

# Nginx / PHP-FPM
tail -100 /var/log/nginx/error.log
tail -100 /var/log/php8.2-fpm.log

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

# systemd services
journalctl -u myapp -n 100 --no-pager

# Find the specific request by time and path
grep '"POST /api/checkout' /var/log/nginx/access.log | tail -20

Log the cf-ray header at the origin. It lets you match a user’s report directly to a request in your own logs, which turns the site was broken around three o’clock into a specific line.

# Nginx: include CF headers and the real client IP in the log format
log_format cf '$remote_addr $http_cf_connecting_ip $http_cf_ray '
              '"$request" $status $body_bytes_sent $request_time';

access_log /var/log/nginx/access.log cf;

CF-Connecting-IP is also essential: without it every request in your logs appears to come from a Cloudflare address, and rate limiting and abuse detection based on client IP silently stop working.

The 5xx codes that are configuration, not failure

525 and 526 are the most common self-inflicted Cloudflare errors, and both come from the SSL/TLS encryption mode.

  • Flexible — Cloudflare uses HTTPS to the browser and plain HTTP to your origin. If your origin redirects HTTP to HTTPS, you get an infinite redirect loop.
  • Full — HTTPS to the origin, certificate not validated. Works with a self-signed certificate.
  • Full (strict) — HTTPS with certificate validation. Correct for production and the source of 526 when the origin certificate has expired or does not match.
  • Strict (SSL-Only Origin Pull) — mutual TLS. The most secure and the most to go wrong.

Use Full (strict) with a valid certificate. Flexible mode means the connection between Cloudflare and your server is unencrypted, which defeats a large part of the point while displaying a padlock to users.

521 and 522 are firewall problems most of the time. If your origin only accepts traffic from Cloudflare — which it should — that allowlist has to stay current:

# Cloudflare publishes its ranges; refresh them periodically
curl -s https://www.cloudflare.com/ips-v4 -o /tmp/cf4
curl -s https://www.cloudflare.com/ips-v6 -o /tmp/cf6

while read -r cidr; do
  ufw allow from "$cidr" to any port 443 proto tcp
done < /tmp/cf4

A stale allowlist produces 521s that appear without any deploy, which is a genuinely confusing failure.

524 timeouts, which are a performance problem

Error 524 means Cloudflare connected fine and waited 100 seconds for a response that never came. Your application is not down; it is too slow.

The 100-second limit is fixed on most plans and cannot be raised meaningfully. So the fix is architectural rather than a setting.

  • Move long work off the request. A report that takes three minutes should return a job ID immediately and be polled or pushed, not held open.
  • Find the slow query. A missing index on a table that has grown is the most common cause of a request that used to be fast.
  • Check connection pool exhaustion. Requests queueing for a database connection look like slow application code and are not.
  • Use a subdomain that bypasses the proxy for genuinely long-running endpoints, if you must keep them.

524s that appear gradually are a capacity signal. A request creeping from 2 seconds to 40 over months is telling you something well before it crosses the threshold, and the timeout is just where it became visible.

This is where autoscaling and runtime metrics earn their place — scaling between a floor and ceiling plan as CPU rises, and having the request duration recorded so the trend is visible before the errors start. The autoscaling documentation covers the thresholds.

A working order for diagnosis

  1. Note the exact error number. 500 versus 522 versus 524 sends you to completely different places.
  2. Capture the cf-ray header from a failing request.
  3. Request the origin directly with curl --resolve. This alone resolves most cases.
  4. If the origin fails directly, stop looking at Cloudflare and read your application logs.
  5. If the origin is healthy, check SSL/TLS mode, firewall allowlists, page rules, and any Workers on the route.
  6. Pause Cloudflare temporarily — the Pause Cloudflare on Site option in the overview — to confirm. DNS-only mode for a single record achieves the same thing more surgically.

Pausing is the definitive test and it is reversible in one click. If the problem persists with Cloudflare out of the path, you have saved yourself from debugging the wrong system.

How this fits the rest of the stack

A 500 through Cloudflare is your origin’s error being relayed. Cloudflare’s own failures are the 520-527 range, and most of those are configuration — SSL mode, a stale firewall allowlist, or a request that takes longer than 100 seconds. Test the origin directly first; it answers the only question that matters. If you are sizing a deployment where autoscaling and runtime logs come with the service, the RunxBuild hosting calculator shows the plans as separate line items.

Useful related references:

FAQ

Is a Cloudflare 500 error Cloudflare’s fault?

Almost never. A plain 500 is your origin server’s response being relayed unchanged. Cloudflare’s own failures use codes 520 through 527 and display a branded error page identifying them.

What is the difference between error 502 and error 522 on Cloudflare?

A 502 came from your origin — your own reverse proxy could not reach its backend. A 522 means Cloudflare could not complete a TCP connection to your origin, usually because a firewall is dropping its requests.

How do I test my origin server directly, bypassing Cloudflare?

Use curl with —resolve to override DNS for one request while keeping the Host header and TLS SNI intact: curl -sI https://example.com/ —resolve example.com:443:YOUR_ORIGIN_IP.

What causes Cloudflare error 524?

Your origin took longer than 100 seconds to respond. The connection succeeded, so the server is up but too slow. Move long-running work into a background job rather than holding the request open.

Why do I get error 525 on Cloudflare?

The TLS handshake between Cloudflare and your origin failed. This is usually the SSL/TLS encryption mode set to Full (strict) while the origin certificate has expired, is self-signed, or does not match the hostname.

#what is error code 500 on cloudflare#cloudflare 5xx#origin server error#cf-ray#error 520