HTTP status codes
Every status code, what it means, and when to actually use it.
The five classes
31 status codes
| Code | Name | Meaning |
|---|---|---|
| 100 | Continue | Keep sending the request body. |
| 101 | Switching Protocols | Upgrading, usually to WebSocket. |
| 103 | Early Hints | Preload hints before the real response. |
| 200 | OK | Success. The response body carries the result. |
| 201 | Created | A new resource exists. Should include a Location header pointing at it. |
| 202 | Accepted | Queued for processing; not done yet. |
| 204 | No Content | Success, and there is deliberately no body. The correct reply to a DELETE that worked. |
| 206 | Partial Content | A byte range, for resumable downloads and video seeking. |
| 301 | Moved Permanently | Use the new URL from now on. Cached aggressively and hard to undo — be certain before sending it. |
| 302 | Found | Temporary redirect. May change the method to GET. |
| 303 | See Other | Fetch the result elsewhere with GET. The correct POST-redirect-GET status. |
| 304 | Not Modified | Your cached copy is still good. |
| 307 | Temporary Redirect | Like 302 but the method is preserved. |
| 308 | Permanent Redirect | Like 301 but the method is preserved. |
| 400 | Bad Request | Malformed — the server cannot parse it. |
| 401 | Unauthorized | Not authenticated. Misnamed: it means unauthenticated. Authorisation failure is 403. |
| 403 | Forbidden | Authenticated, but not allowed. |
| 404 | Not Found | No such resource. Also used deliberately to hide the existence of something from unauthorised users. |
| 405 | Method Not Allowed | Wrong verb for this URL. Must include an Allow header listing what is permitted. |
| 409 | Conflict | Collides with the current state — an edit conflict, a duplicate key. |
| 410 | Gone | It existed and was deliberately removed. |
| 413 | Payload Too Large | The body exceeds the limit. |
| 415 | Unsupported Media Type | Wrong Content-Type. |
| 418 | I'm a Teapot | An April Fools joke from 1998 that never went away. RFC 2324. Deliberately never removed from the registry. |
| 422 | Unprocessable Content | Syntactically valid but semantically wrong — validation failed. |
| 429 | Too Many Requests | Rate limited. Should include Retry-After. |
| 500 | Internal Server Error | Something broke and was not handled. |
| 501 | Not Implemented | The server does not support this method at all. |
| 502 | Bad Gateway | An upstream server returned something invalid. |
| 503 | Service Unavailable | Overloaded or down for maintenance. Should include Retry-After. Use this rather than 500 during a deploy. |
| 504 | Gateway Timeout | An upstream server did not answer in time. |
How it works
The first digit is the whole story: 2 worked, 3 go elsewhere, 4 you made a mistake, 5 we made a mistake. Clients are required to understand the class even when they do not recognise the specific code, so an unknown 499 is safely treated as a 400.
401 versus 403
The most commonly confused pair, not helped by 401 being named “Unauthorized” when it actually means unauthenticated. Use 401 when the caller has not proven who they are — no token, expired token. Use 403 when you know exactly who they are and they still may not do this.
301 is close to permanent
Browsers cache 301 responses aggressively, sometimes indefinitely, and there is no reliable way to make a client forget one. A mistaken 301 can be effectively irreversible for a user who already received it. Use 302 or 307 unless you are certain.
307 and 308 exist because of a bug in history
Early browsers changed POST to GET when following a 301 or 302, contradicting the specification. Rather than break the web, the standard added 307 and 308 with identical semantics but an explicit guarantee that the method is preserved. Use them when the method matters.
422 versus 400
400 means the server could not parse the request at all — broken JSON, a malformed header. 422 means it parsed perfectly and the contents are wrong: a missing required field, an email that is not an email. The distinction genuinely helps API consumers debug.
503 during deployments
A 503 with a Retry-After header tells clients and crawlers this is temporary, so
they should come back rather than de-index your pages. Returning 500 or a 200 with an error
page during a deploy is a common and avoidable mistake.
Sources
Definitions follow RFC 9110 (HTTP Semantics, 2022), which supersedes the older RFC 7231 family, plus the IANA HTTP Status Code Registry. And RFC 2324 for the teapot.