Complete HTTP Error Code Reference: What Each Status Code Means and How to Fix It
HTTP status codes are the protocol layer’s verdict on every request. The class (4xx vs 5xx) tells you who is responsible. The specific code tells you exactly what failed. Here is the complete technical reference.
4xx = Client error: The server understood the request but refused or could not fulfill it because the request itself is malformed, unauthorized, or points to a non-existent resource.
5xx = Server error: The request was valid but the server failed to process it due to an internal fault, overload, upstream dependency failure, or timeout. 5xx errors always indicate the problem is on the server side — not the client’s.
Quick Reference
| Code | Name | Responsible Party | Jump to |
|---|---|---|---|
| 400 | Bad Request | Client — malformed syntax | ↓ Details |
| 401 | Unauthorized | Client — missing/invalid credentials | ↓ Details |
| 403 | Forbidden | Server — access denied regardless of credentials | ↓ Details |
| 404 | Not Found | Client — wrong URL or deleted resource | ↓ Details |
| 410 | Gone | Server — resource permanently removed | ↓ Details |
| 429 | Too Many Requests | Client — rate limit exceeded | ↓ Details |
| 500 | Internal Server Error | Server — unhandled application exception | ↓ Details |
| 502 | Bad Gateway | Proxy — invalid upstream response | ↓ Details |
| 503 | Service Unavailable | Server — overloaded or in maintenance | ↓ Details |
| 504 | Gateway Timeout | Proxy — upstream response timeout | ↓ Details |
| 520–527 | Cloudflare Errors | CDN edge — Cloudflare-to-origin failure | ↓ Details |
4xx Client Errors vs 5xx Server Errors — The Core Distinction
4xx errors indicate the client’s request is malformed, unauthorized, or references a resource the server cannot locate — the origin server received and understood the request, but declined to fulfill it because of a problem with the request itself. This class covers authentication failures (401), permission denials (403), missing resources (404), and protocol violations (400) — all conditions where the fix lies on the requesting side.
5xx errors indicate the opposite: the server received a valid, well-formed request but failed to process it due to an internal fault. The request was correct; the server is the problem. 5xx errors originate in application crashes (500), upstream dependency failures (502), server overload (503), and network timeouts between layers (504). Because these errors always represent server-side failures, they are the primary signal that a service is genuinely “down” — not a misconfigured client.
The practical diagnosis rule: a 4xx error on a URL you control means your request or routing is wrong; a 5xx error means your server, CDN, or upstream dependency needs investigation. Use DownCheck to confirm whether a 5xx you are seeing is isolated to your network or global — a global 5xx confirms the origin itself is failing, while a local 5xx may indicate CDN misconfiguration or geographic routing failure.
HTTP 400 Bad Request
HTTP 400 is returned when the server cannot process a request due to malformed syntax, invalid framing, or deceptive request routing. The server received the TCP connection and the HTTP message, but the message itself violates the HTTP/1.1 or HTTP/2 protocol specification in a way the server refuses to handle.
Common causes include invalid characters in the URL (unencoded spaces or special characters), an oversized request header that exceeds the server’s configured limit (client_header_buffer_size in nginx), a malformed Content-Type header that does not match the body payload, or a corrupt multipart form boundary. In API contexts, 400 typically means the JSON or XML body failed schema validation — a missing required field, wrong data type, or invalid enum value.
Resolve a 400 by inspecting the exact request being sent: URL-encode all special characters, verify Content-Type matches the body format, reduce header size, and validate the request body against the API schema. If you are a site owner receiving unexpected 400s, check your reverse proxy’s header buffer limits and any WAF (Web Application Firewall) rules that may be rejecting legitimate traffic.
HTTP 401 Unauthorized vs HTTP 403 Forbidden (Exact Difference)
These two codes are the most frequently confused in HTTP — they are semantically distinct in a way that matters for both debugging and security design.
HTTP 401 means the request lacks valid authentication credentials for the target resource. Despite its name, 401 is specifically an authentication failure, not an authorization failure. The server is saying: “I don’t know who you are. Provide credentials and try again.”
A 401 response must include a WWW-Authenticate header specifying the authentication scheme required (e.g., Bearer, Basic, Digest). The client can retry the same request with a valid Authorization header and may succeed. This is the critical behavioral difference from 403 — 401 is recoverable by providing credentials; 403 is not.
Common causes: expired JWT token, missing Authorization: Bearer header, revoked API key, session cookie expiry, or an OAuth token with insufficient scope for the requested endpoint.
HTTP 403 means the server understood the request and identified the requester, but refuses to authorize access regardless of credentials. This is an authorization failure: the server knows who you are, and has decided you are not permitted to access this resource — not now, not with different credentials.
403 differs from 401 in that retrying with different credentials will not help — the denial is based on identity or role, not missing authentication. A 403 does not include a WWW-Authenticate header. It may also be returned deliberately to mask the existence of a resource (returning 403 instead of 404 prevents enumeration attacks where attackers probe for hidden endpoints).
Common causes: insufficient role permissions (e.g., a non-admin user accessing an admin endpoint), IP allowlist enforcement, CORS policy blocking cross-origin access, file system permissions preventing the web server from reading a file, or a CDN/WAF geo-blocking rule.
| 401 Unauthorized | 403 Forbidden | |
|---|---|---|
| Failure type | Authentication | Authorization |
| Server knows who you are? | No | Yes |
| Recoverable by adding credentials? | Yes | No |
| WWW-Authenticate header? | Required | Not included |
| Fix | Add or refresh credentials | Request elevated permissions |
HTTP 404 Not Found vs HTTP 410 Gone (Why 410 Matters for SEO)
HTTP 404 means the server cannot locate a resource at the requested URL, but makes no claim about whether the resource ever existed or might exist in the future. The absence is ambiguous — the resource may have moved, may return, or may never have existed. The server is not committing to permanence.
Google’s crawlers treat 404 as a soft signal: they will revisit the URL periodically for weeks or months before fully de-indexing it, in case the resource returns. This crawl budget consumption matters at scale — a site with thousands of 404 URLs wastes crawl budget that could be spent on live content. For site owners, a 404 on a URL that previously ranked should be addressed immediately: either restore the content, issue a 301 redirect to the most relevant live page, or return 410 to signal permanence.
HTTP 410 explicitly declares that the requested resource has been permanently and intentionally removed with no forwarding address. Unlike 404, 410 communicates intent: the server knows the resource existed, knows it was deleted, and is asserting it will not return. This semantic precision is why 410 matters more than 404 in specific scenarios.
Search engines treat 410 as a hard signal: Googlebot de-indexes a 410 URL significantly faster than a 404, typically within days rather than weeks. This makes 410 the correct response when permanently deleting content you do not want re-crawled — expired promotions, discontinued products, removed user accounts, or GDPR-deleted content. 410 also eliminates the “soft 404” ambiguity that causes crawlers to waste time rechecking URLs.
Use 410 when: permanently deleting indexed content, removing product pages for discontinued items, complying with right-to-erasure requests, or retiring old API endpoints. Use 404 only when the missing resource is temporary or its absence is genuinely unknown.
HTTP 429 Too Many Requests — Rate Limiting Explained
HTTP 429 is returned when the client has sent more requests than the server’s rate limiting policy permits within a defined time window. Rate limiting protects origin infrastructure from abuse, scraping, brute-force authentication attacks, and traffic spikes that would otherwise exhaust connection pools or database query capacity.
The 429 response should include a Retry-After header specifying either the number of seconds to wait or an HTTP-date after which the client may retry. Rate limits are enforced at multiple layers simultaneously: at the origin application (per-user, per-API-key, per-endpoint), at the reverse proxy or API gateway (per-IP), and at the CDN edge (Cloudflare Rate Limiting rules). A 429 from Cloudflare’s edge means the request never reached your origin server — a 429 from the origin means it did reach the server and was refused by application logic.
If you are an API consumer hitting 429 errors, implement exponential backoff with jitter: wait min(base * 2^attempt + random_jitter, max_wait) seconds between retries. If you are a site owner seeing unexpected 429s on your own traffic, check CDN rate limiting rules for overly aggressive IP-level thresholds and ensure authenticated users get higher quota allocations than anonymous traffic.
Retry-After header: RFC 6585 requires 429 responses to include Retry-After. If the response omits it, default to exponential backoff starting at 1 second. Never retry a 429 immediately — it will extend your ban window at most CDN and API gateway implementations.
HTTP 500 Internal Server Error
HTTP 500 is the server’s generic catch-all for any unhandled exception or unexpected condition that prevents it from fulfilling a valid request. It is the server-side equivalent of an unhandled exception in application code: something went wrong that the application did not anticipate and did not handle gracefully.
500 is distinct from 502–504 in a critical way: a 500 originates at the application layer of the origin server itself, not at a proxy or gateway. The web server process (nginx, Apache) is running, the application framework (Django, Rails, Laravel, Express) received the request, but the application code threw an uncaught exception, encountered a null pointer, failed a database query, ran out of memory, or hit a misconfigured environment variable. The TCP connection to the origin succeeded; it’s the application logic that crashed.
Diagnose a 500 by checking application logs immediately after the error (stack traces, error messages), verifying database connectivity and query execution time, checking for recent code deployments or configuration changes, and confirming environment variables and secrets are correctly populated. Use DownCheck to determine if the 500 is affecting all users globally or is isolated to specific request patterns — a global 500 indicates a broken deployment; a partial 500 may indicate a database connection pool exhaustion or a specific code path failure.
HTTP 502 Bad Gateway — What the Reverse Proxy Received
HTTP 502 is returned by a reverse proxy (nginx, Cloudflare, AWS ALB, Traefik) when the upstream origin server returns an invalid, malformed, or empty response that violates HTTP protocol specification. The proxy itself is operational and handling client connections normally; the problem is in the response it received from the upstream server sitting behind it.
Understanding 502 requires understanding the two-leg connection model: the client connects to the proxy (leg 1), and the proxy connects to the origin server (leg 2). A 502 means leg 2 failed — not leg 1. The proxy successfully accepted the client’s request, forwarded it upstream, but received back either nothing (crashed origin process), an HTTP protocol violation, a TCP connection reset (RST packet), or a response with an unparseable status line. Common upstream failures that trigger 502: the application server process (gunicorn, puma, node) crashed and is not responding on its socket; a Docker container exited unexpectedly; the upstream returned an invalid HTTP response headers; or the upstream is returning a response too slowly and the proxy has already given up (in which case you would more typically see a 504).
Resolve a 502 by checking the origin server process status (systemctl status nginx, pm2 status, container health), reviewing application crash logs for the timestamp of the first 502, verifying the proxy upstream configuration points to the correct host and port, and confirming the origin’s firewall allows connections from the proxy IP. Use DownCheck’s multi-probe tool to determine if the 502 is global or isolated to specific CDN edge nodes.
502 vs 504: Both originate at the proxy, but the cause differs. 502 = the upstream responded with something invalid. 504 = the upstream never responded within the timeout window. If you see both codes intermittently, the upstream is partially running — some requests hit a healthy process instance, others hit a crashed one or time out.
HTTP 503 Service Unavailable — Load vs Maintenance vs DDoS
HTTP 503 means the server is temporarily unable to handle the request, but is deliberately communicating this unavailability rather than silently failing. Unlike 500 (unexpected crash) or 502 (proxy receiving garbage), 503 is an intentional response — the server knows it cannot serve the request and is saying so explicitly. This means the server software is still operational enough to respond, but is choosing to reject incoming requests.
Three distinct conditions produce 503, and diagnosing which one matters for the fix. Overload: the server’s worker process pool, connection queue, or database connection limit is exhausted — new requests are being shed. nginx returns 503 when its upstream worker pool is full (upstream no live upstreams while connecting to upstream). Scheduled maintenance: the operator has intentionally taken the service offline and configured the server to return 503 with a Retry-After header indicating when it will return. DDoS mitigation: Cloudflare and other CDNs return 503 as part of Under Attack Mode, rejecting traffic that fails challenge verification. A 503 during a known DDoS matches the third pattern; a 503 following a traffic spike matches the first.
Resolve a load-induced 503 by scaling horizontally (adding more origin instances), increasing the worker process count, optimizing slow database queries that are holding connections open, or enabling request queuing with a backpressure mechanism. A maintenance 503 resolves when the maintenance window ends. A DDoS-triggered 503 requires verifying whether legitimate traffic is also being blocked and adjusting CDN challenge sensitivity thresholds accordingly.
HTTP 504 Gateway Timeout — Network vs Application Layer
HTTP 504 occurs when a reverse proxy or CDN edge node forwards a request to the upstream origin server and receives no complete response within the configured timeout threshold. The proxy made the connection to the upstream (unlike 502, where the upstream responded invalidly), but the upstream either accepted the connection and then went silent, or completed the TCP handshake but never sent HTTP response headers within the time limit.
The root cause is almost always in the upstream’s processing time, not in network latency. The two dominant causes are: a slow database query blocking the application thread that is handling the request, causing it to hold the connection open without sending a response while the query runs; and a downstream microservice call the origin is waiting on that is itself experiencing latency or failure. A 10-second nginx timeout with a 12-second database query will produce a 504 every time. The application code is alive; it is just not finishing fast enough. Network-layer 504s occur when there is packet loss or high latency between the proxy and origin data center — this produces a 504 where the upstream TCP connection itself times out before HTTP headers are exchanged.
Diagnose a 504 by correlating its timestamp with slow query logs in the database, checking application performance monitoring (APM) for the slowest endpoint traces, verifying network latency between proxy and origin via traceroute or VPN path analysis, and reviewing upstream connection timeout settings in the proxy configuration (proxy_read_timeout in nginx). Increasing the timeout is a short-term fix — the correct resolution is optimizing the slow operation, adding indexes, caching query results, or implementing async processing for long-running tasks.
HTTP 520–527 — Cloudflare-Specific Error Codes
Cloudflare 520–527 are proprietary error codes that Cloudflare returns when it cannot establish or maintain a healthy connection to your origin server. These codes are not part of the HTTP specification — they are Cloudflare’s internal language for classifying exactly which part of the Cloudflare-to-origin connection failed. They only appear when Cloudflare is acting as a reverse proxy in front of your origin (orange-cloud mode in your DNS settings).
The critical insight for diagnosis: a 5xx Cloudflare error means the client-to-Cloudflare leg is working fine — Cloudflare accepted the request without issue. The failure is exclusively in the Cloudflare-to-origin leg. Your origin server is either not responding, sending invalid responses, closing connections prematurely, or presenting an invalid TLS certificate. Knowing the specific code narrows the fix to a precise origin-side issue.
Origin returned an empty, unknown, or unexpected response. Causes: origin crashed mid-response, returned a non-HTTP response, or sent only headers with no body. Check origin error logs for crash timestamps matching the 520s.
Cloudflare’s connection to origin port 80 or 443 was refused (TCP RST received). The web server process is not running. Fix: restart nginx/Apache/Caddy on the origin server, verify firewall allows Cloudflare IP ranges.
Cloudflare’s TCP connection to the origin timed out (15-second limit). Causes: origin firewall blocking Cloudflare IP ranges, origin server overloaded and not accepting new connections, network path issue between Cloudflare PoP and origin data center.
Cloudflare cannot route to the origin IP address — no route to host. Typically caused by the origin server being offline, wrong IP in DNS A record, or BGP routing failure between Cloudflare and the origin AS.
Cloudflare established a TCP connection but the origin did not send an HTTP response within 100 seconds. This is Cloudflare’s equivalent of 504. Cause: a long-running server process (database query, file upload, API call). Fix: use Cloudflare’s no-timeout streaming or optimize the slow operation.
Cloudflare established a TCP connection but the TLS handshake with the origin failed. Causes: origin SSL certificate expired, cipher suite mismatch, invalid SSL configuration when Cloudflare SSL mode is “Full (strict)” but origin has a self-signed cert.
Cloudflare could not validate the origin’s SSL certificate when SSL mode is “Full (strict)”. The cert is expired, self-signed, or the hostname does not match. Fix: install a valid certificate (Let’s Encrypt) or use a Cloudflare Origin Certificate.
Timeout or error with Cloudflare’s Railgun WAN optimization protocol (now deprecated). If you are seeing 527s, Railgun is misconfigured or the Railgun listener process on your origin is down.
Quick diagnosis for all 52x errors: Check your origin server’s error logs, verify the web server process is running (systemctl status nginx), confirm Cloudflare IP ranges are allowlisted in your firewall, and verify SSL certificate validity and expiry. The specific 52x code tells you which step of the Cloudflare-to-origin handshake failed.
How to Check if a 5xx Error is Global or Isolated
The most important diagnostic step for any 5xx error is determining whether it affects all users globally or only a subset of traffic — because the fix is completely different depending on the answer. A global 5xx means your origin server, CDN configuration, or DNS infrastructure has failed at a fundamental level. A partial 5xx means a specific region, CDN edge node, server instance, or request pattern is affected.
DownCheck’s 3-probe architecture provides exactly this signal. An HTTP probe from Railway’s US servers, a Cloudflare Edge fetch from the nearest PoP, and a DNS resolution check across 4 resolvers are dispatched simultaneously. If all three probes return 5xx responses, the outage is global — the origin itself is returning errors to every network path. If the HTTP probe returns 5xx but the Cloudflare Edge probe returns 200, the failure is isolated to the specific routing path between Railway’s infrastructure and your origin — which may indicate a network path issue or an origin that is only partially failed. If DNS succeeds but both HTTP probes fail, the origin is up but returning errors from the application layer. See the full outage diagnosis guide for the complete decision tree.
For site owners, the fastest way to confirm scope is to query your origin directly (bypassing the CDN) using curl -I https://your-origin-ip --header "Host: yourdomain.com" while simultaneously checking what the CDN’s edge is serving. If the origin returns 200 but the CDN returns 5xx, the CDN configuration is the problem (incorrect upstream address, SSL mismatch, rate limit on Cloudflare). If the origin also returns 5xx, the application or server itself has failed and requires investigation of logs, process status, and database connectivity.
Check your status page: Major service 5xx events are tracked in real time on DownCheck’s service status dashboard — covering 2,675+ services including AWS, Cloudflare, Vercel, and GitHub. If your 5xx coincides with a listed service incident, the root cause is a dependency, not your code.
Frequently Asked Questions
Seeing a 5xx error right now?
DownCheck runs an HTTP probe and a 4-resolver DNS consensus to tell you in seconds whether the error is global or isolated to your network.
Check a site →