HTTP status codes: 1xx to 5xx with meaning and common causes
- tool
- HTTP
- versions
- RFC 9110
- os
- any
HTTP status codes are three-digit numbers grouped by their first digit: 1xx informational, 2xx success, 3xx redirection, 4xx client error (fix the request) and 5xx server error (the server failed a valid request). The official registry is maintained by IANA; RFC 9110 defines the core codes.
Most used codes
| Code | Reason phrase | When you see it |
|---|---|---|
| 200 | OK | success with a body |
| 201 | Created | resource created; Location header points to it |
| 204 | No Content | success without a body (DELETE, PUT) |
| 301 | Moved Permanently | permanent redirect; clients may change POST to GET |
| 302 | Found | temporary redirect; clients may change POST to GET |
| 304 | Not Modified | cached copy is still valid (ETag / If-Modified-Since) |
| 307 | Temporary Redirect | temporary, method and body preserved |
| 308 | Permanent Redirect | permanent, method and body preserved |
| 400 | Bad Request | malformed syntax or invalid body |
| 401 | Unauthorized | missing or invalid credentials (authentication) |
| 403 | Forbidden | authenticated but not allowed (authorization) |
| 404 | Not Found | no resource at this URL |
| 405 | Method Not Allowed | method not supported; Allow header lists valid ones |
| 409 | Conflict | state conflict, for example a duplicate or a version clash |
| 413 | Content Too Large | body exceeds the server limit (was Payload Too Large) |
| 415 | Unsupported Media Type | wrong Content-Type |
| 422 | Unprocessable Content | well-formed but semantically invalid |
| 429 | Too Many Requests | rate limited; Retry-After may tell you when to retry |
| 500 | Internal Server Error | unhandled exception on the server |
| 502 | Bad Gateway | a proxy got an invalid response from the upstream |
| 503 | Service Unavailable | overloaded or in maintenance |
| 504 | Gateway Timeout | a proxy waited too long for the upstream |
Reason phrases as Node.js knows them
node -e '
const { STATUS_CODES } = require("http");
for (const code of [200, 204, 301, 304, 308, 401, 403, 404, 413, 418, 422, 429, 500, 502, 503, 504]) {
console.log(code, STATUS_CODES[code]);
}'Output
200 OK 204 No Content 301 Moved Permanently 304 Not Modified 308 Permanent Redirect 401 Unauthorized 403 Forbidden 404 Not Found 413 Payload Too Large 418 I'm a Teapot 422 Unprocessable Entity 429 Too Many Requests 500 Internal Server Error 502 Bad Gateway 503 Service Unavailable 504 Gateway Timeout
Node.js still uses the older phrases for 413 (Payload Too Large) and 422 (Unprocessable Entity); RFC 9110 renamed them Content Too Large and Unprocessable Content. Reason phrases are informational only: clients must act on the number, and HTTP/2 and HTTP/3 do not transmit a reason phrase at all.
401 vs 403
401 Unauthorized means "who are you?": send credentials (and the response should carry WWW-Authenticate). 403 Forbidden means "I know who you are, and the answer is no": different credentials will not help unless they carry more permissions.