HTTP status codes
Every status code, what triggers it, and what to actually do about it — not just the one-line definition from the spec.
1xx — Informational
The request was received and the process is continuing. These are rarely seen by application code.
| Code | Name | Meaning |
|---|---|---|
| 100 | Continue | The client sent an Expect: 100-continue header and the server is telling it to go ahead and send the request body. |
| 101 | Switching Protocols | The server is switching to the protocol the client asked for in the Upgrade header — almost always a WebSocket handshake. |
| 103 | Early Hints | The server is sending Link headers so the browser can start preloading critical resources before the real response is ready. |
2xx — Success
The request was received, understood and accepted.
| Code | Name | Meaning |
|---|---|---|
| 200 | OK | The request succeeded. |
| 201 | Created | The request succeeded and a new resource was created, usually by a POST or PUT. |
| 202 | Accepted | The request was accepted for processing, but the work has not finished. |
| 204 | No Content | The request succeeded and there is deliberately no body to return. |
| 206 | Partial Content | The server is returning only part of the resource because the client sent a Range header. |
3xx — Redirection
Further action is needed to complete the request — usually following a redirect.
| Code | Name | Meaning |
|---|---|---|
| 301 | Moved Permanently | The resource has a new permanent URL. |
| 302 | Found | A temporary redirect. |
| 303 | See Other | Redirects the client to fetch the result with GET, regardless of the original method. |
| 304 | Not Modified | The cached copy the client already has is still current, so no body is sent. |
| 307 | Temporary Redirect | Like 302, but guarantees the method and body are preserved. |
| 308 | Permanent Redirect | Like 301, but the method and body are preserved. |
4xx — Client Error
The request contains something the server will not or cannot process. The fix is normally on the client side.
| Code | Name | Meaning |
|---|---|---|
| 400 | Bad Request | The server could not understand the request: malformed JSON, an invalid query parameter, a header that does not parse. |
| 401 | Unauthorized | Authentication is required and either missing or invalid. |
| 403 | Forbidden | The server understood the request and knows who you are, but you are not allowed to do this. |
| 404 | Not Found | The server has no resource at this URL. |
| 405 | Method Not Allowed | The URL exists but does not accept this HTTP method — a POST to a GET-only endpoint, for example. |
| 406 | Not Acceptable | The server cannot produce a response matching the client's Accept header. |
| 408 | Request Timeout | The client took too long to send the complete request and the server gave up waiting. |
| 409 | Conflict | The request conflicts with the current state — a duplicate unique key, or an edit based on a stale version. |
| 410 | Gone | The resource existed but has been deliberately and permanently removed. |
| 413 | Payload Too Large | The request body exceeds a limit the server imposes. |
| 415 | Unsupported Media Type | The server does not accept the Content-Type the client sent. |
| 418 | I'm a Teapot | Defined in a 1998 April Fools' RFC for the Hyper Text Coffee Pot Control Protocol. |
| 422 | Unprocessable Content | The request is syntactically valid but semantically wrong — well-formed JSON where a field fails validation. |
| 429 | Too Many Requests | The client has been rate limited. |
| 431 | Request Header Fields Too Large | The headers exceed the server's limit, usually because of oversized cookies. |
| 451 | Unavailable For Legal Reasons | The content is blocked for legal reasons — a court order, a takedown, a regional restriction. |
5xx — Server Error
The server failed to fulfil an apparently valid request. The fix is on the server side.
| Code | Name | Meaning |
|---|---|---|
| 500 | Internal Server Error | The server hit an unhandled error. |
| 501 | Not Implemented | The server does not support the functionality required to fulfil the request. |
| 502 | Bad Gateway | A server acting as a proxy got an invalid response from the upstream server. |
| 503 | Service Unavailable | The server is temporarily unable to handle the request — overloaded, or down for maintenance. |
| 504 | Gateway Timeout | A proxy did not get a response from the upstream server in time. |
| 505 | HTTP Version Not Supported | The server does not support the HTTP protocol version the client used. |
| 507 | Insufficient Storage | The server cannot store the representation needed to complete the request. |
| 511 | Network Authentication Required | The client must authenticate to get network access — a captive portal on hotel or airport Wi-Fi. |
The four redirects, and why there are four
301 and 302 came first, and HTTP/1.1 said a user agent must not automatically redirect a non-GET request without asking the user. Browsers did something else: they redirected it silently as a GET and dropped the body. Enough of the web came to depend on that to make it unfixable, and RFC 7231 ended up documenting it as something a user agent may do “for historical reasons” — a specification conceding to what had already been built.
307 and 308 exist because of that concession. They carry the same two meanings, temporary and permanent, with the method and body guaranteed to survive rather than merely expected to.
| Code | Meaning | Method after | Cached by default |
|---|---|---|---|
301 | Permanent | POST usually becomes GET | Yes |
302 | Temporary | POST usually becomes GET | No |
307 | Temporary | Preserved | No |
308 | Permanent | Preserved | Yes |
The cache column is the one that bites. A 301 or 308 is cacheable without any headers saying so, and browsers hold them hard — send one by mistake and visitors who saw it keep being redirected long after the server stopped sending it, with nothing you can do from the server side. During a migration, use 302 or 307 until you are certain, then switch to the permanent form.
For an API that redirects a POST, 307 or 308 is the only correct choice. Using 301 or 302 will silently turn the request into a GET and drop the body, and the failure shows up as a mysteriously empty request rather than as a redirect problem.
The three you will actually debug
- 404 vs 410. 404 means "not here"; 410 means "gone deliberately". Search engines drop 410s from the index much faster.
- 401 vs 403. 401 is "I do not know who you are"; 403 is "I know who you are and the answer is no". Sending 401 when you mean 403 sends clients into a pointless re-authentication loop.
- 502 vs 504. 502 means the upstream answered with garbage or refused the connection; 504 means it never answered at all. The first points at a crashed process, the second at a slow one.