Cheatsheet

Every HTTP status code and what it actually means

Grouped by class, with the name from the spec and the situation that actually produces it. The last two sections cover the codes that are not in any RFC: the ones nginx and Cloudflare invent, which is where a lot of confusing production traffic comes from.

The five classes at a glance

Range Meaning Whose fault
1xx Informational. The request was received and processing continues. Nobody. Rarely surfaced to application code.
2xx Success. The request was received, understood, and accepted. Nobody.
3xx Redirection. Further action is needed to complete the request. Nobody, unless it loops.
4xx Client error. The request was malformed, unauthenticated, or asked for something absent. The caller, in theory. Often the API contract in practice.
5xx Server error. The request was valid but the server failed to fulfill it. You. Page someone.

Gotcha: only 4xx and 5xx are errors. A client library that treats every non 200 response as a failure will break on 201, 204, and 304, all of which are perfectly successful.

1xx informational and 2xx success

Code Name When you see it
100 Continue The client sent Expect: 100-continue before a big body and the server is telling it to proceed.
101 Switching Protocols A WebSocket handshake succeeding. The connection stops being HTTP after this.
102 Processing A long running WebDAV request. Deprecated and effectively dead.
103 Early Hints A CDN sending preload Link headers before the real response. Cuts real page load time.
200 OK The default success. A body is expected on GET.
201 Created A POST created a resource. Include a Location header pointing at it.
202 Accepted The work was queued, not done. The right answer for an async job endpoint.
203 Non-Authoritative Information A proxy modified the origin's response. Rare and usually a surprise.
204 No Content Success with nothing to return. The correct answer to a DELETE or a silent PUT.
205 Reset Content Tells the client to clear the form it just submitted. Almost never used.
206 Partial Content A Range request succeeded: video scrubbing, resumable downloads.
207 Multi-Status WebDAV: one response body carrying per resource statuses.
208 Already Reported WebDAV: this binding was already enumerated earlier in the same response.
226 IM Used Delta encoding was applied. You will go a career without meeting it.

Gotcha: a 204 must carry no body at all. Sending JSON with it makes some HTTP clients hang waiting for content length that never arrives. If you have something to say, use 200.

3xx redirection

Code Name When you see it
300 Multiple Choices Several representations exist and the client must pick. Vanishingly rare.
301 Moved Permanently A permanent URL change. Browsers cache it aggressively and search engines pass ranking through it.
302 Found A temporary redirect. Most clients switch POST to GET on it, which the spec never intended.
303 See Other Explicitly says to follow with GET. The correct post and redirect pattern after a form.
304 Not Modified A conditional request matched an ETag or Last-Modified. Success, with no body.
305 Use Proxy Deprecated for security reasons. Modern clients ignore it.
307 Temporary Redirect Like 302 but the method and body must be preserved. Use it instead of 302 for APIs.
308 Permanent Redirect Like 301 but the method is preserved. The right code for a permanent API move.

Gotcha: a 301 is close to irreversible in the field. Browsers cache it indefinitely, so a mistaken permanent redirect keeps firing for users who never see your fix. Ship 302 or 307 first, confirm the target, then promote it.

4xx client errors

Code Name When you see it
400 Bad Request Malformed syntax: broken JSON, a bad header, an impossible query string.
401 Unauthorized Not authenticated. Misnamed: it means unauthenticated. Must include WWW-Authenticate.
402 Payment Required Reserved for decades, now used by some APIs for a lapsed subscription.
403 Forbidden Authenticated but not allowed. Repeating the request will not help.
404 Not Found No resource at that URL. Also the polite way to hide something from a user who may not know it exists.
405 Method Not Allowed The route exists but not for that verb. Must return an Allow header listing the verbs that work.
406 Not Acceptable No representation matches the Accept header the client sent.
407 Proxy Authentication Required Like 401, but the proxy is the one demanding credentials. Common on corporate networks.
408 Request Timeout The client opened a connection and did not finish sending in time.
409 Conflict State conflict: a duplicate unique value, or an edit against a stale version.
410 Gone Deliberately deleted and not coming back. Search engines drop the URL faster than on a 404.
411 Length Required The server refuses a body without a Content-Length header.
412 Precondition Failed An If-Match or If-Unmodified-Since guard did not hold. Optimistic locking working correctly.
413 Content Too Large Upload over the limit. Usually the proxy, not your app. Formerly Payload Too Large.
414 URI Too Long A GET with a giant query string. Switch to POST with a body.
415 Unsupported Media Type Wrong Content-Type on the request. The classic missing application/json header.
416 Range Not Satisfiable The requested byte range lies outside the file.
417 Expectation Failed The server will not honor the Expect header the client sent.
418 I'm a teapot An April Fools joke from 1998, permanently reserved. Handy as an unmistakable test value.
421 Misdirected Request The connection reached a server that cannot serve that authority. An HTTP/2 coalescing artifact.
422 Unprocessable Content Syntactically valid but semantically wrong. The standard validation failure code.
423 Locked WebDAV: the resource is locked by someone else.
424 Failed Dependency WebDAV: a previous request in the sequence failed, so this one cannot run.
425 Too Early Refusing a replayable early data request during a TLS 1.3 zero round trip handshake.
426 Upgrade Required The server insists on a different protocol, listed in the Upgrade header.
428 Precondition Required The server demands a conditional request, to stop blind overwrites.
429 Too Many Requests Rate limited. Always send Retry-After; clients cannot back off intelligently without it.
431 Request Header Fields Too Large Usually an oversized cookie jar rather than a genuinely huge header.
451 Unavailable For Legal Reasons Censorship or a takedown. The number is a Fahrenheit 451 reference.

Gotcha: 401 versus 403 trips up nearly every API. 401 means "I do not know who you are, try authenticating"; 403 means "I know exactly who you are and the answer is still no". Returning 401 for a permissions failure sends clients into a pointless token refresh loop.

5xx server errors

Code Name When you see it
500 Internal Server Error An unhandled exception. Generic by design, so the detail belongs in your logs.
501 Not Implemented The server does not recognize the method at all. Not the same as 405.
502 Bad Gateway A proxy got garbage or nothing from upstream. Usually your app crashed or never bound its port.
503 Service Unavailable Overloaded or in maintenance. Send Retry-After. This is the correct maintenance page code.
504 Gateway Timeout Upstream accepted the connection but never answered in time. The slow query smell.
505 HTTP Version Not Supported The protocol version in the request line is refused.
506 Variant Also Negotiates A content negotiation misconfiguration that loops on itself.
507 Insufficient Storage WebDAV: out of disk. Occasionally repurposed by storage APIs.
508 Loop Detected WebDAV: an infinite loop while processing the request.
510 Not Extended An extension the server requires was missing from the request.
511 Network Authentication Required A captive portal. Hotel and airport wifi, not your server.

Gotcha: 502 and 504 both come from the proxy, never from your application code. 502 means upstream answered with something invalid or died mid response; 504 means it never answered at all. Check the process on a 502 and the query or the timeout on a 504.

Non standard codes from proxies and CDNs

These are not in any RFC. They appear in access logs and dashboards, so knowing them saves an hour of searching the spec for something that is not there.

Code Source Meaning
444 nginx Connection closed with no response at all. Usually a deliberate abuse rule.
494 nginx Request headers exceeded the buffer. The nginx flavor of 431.
497 nginx A plain HTTP request arrived on an HTTPS port.
499 nginx The client gave up and disconnected first. A spike means your responses are too slow.
520 Cloudflare Origin returned something Cloudflare could not parse. The catch all.
521 Cloudflare Origin refused the connection. Often a firewall blocking Cloudflare's IP ranges.
522 Cloudflare TCP handshake to the origin timed out.
523 Cloudflare Origin unreachable. Normally a DNS record pointing at nothing.
524 Cloudflare Origin connected but did not finish responding inside the timeout window.
525 Cloudflare TLS handshake with the origin failed, usually a cipher or protocol mismatch.
526 Cloudflare The origin certificate is invalid or expired while strict SSL is on.
530 Cloudflare Always paired with a 1xxx error in the body. Read that number, not the 530.

Choosing the right code in your own API

Situation Return
POST created a record 201 with a Location header
POST queued a background job 202 with a status URL
DELETE succeeded, nothing to say 204
Body parsed but a field is invalid 422 with per field errors
Body would not parse at all 400
Token missing or expired 401 with WWW-Authenticate
Valid user, wrong role 403
Valid user, other tenant's record 404, to avoid leaking existence
Email already registered 409
Client is over its quota 429 with Retry-After
Planned maintenance window 503 with Retry-After
Any error body at all application/problem+json per RFC 9457

Gotcha: never return 200 with an error object in the body. Monitoring, retries, circuit breakers, and CDN caching all key off the status line, and a 200 tells every one of them that everything is fine.

Keep going

Status codes are one design decision inside a bigger one: REST vs GraphQL covers where they stop being the error channel at all, and the API stack guide covers the layers around them.

For the proxy side of a 502, see the Docker cheatsheet on container health checks, or browse the monitoring tools that alert on these codes. The cheatsheet index has everything else.