HTTP Cheatsheet
Status Codes
Use this HTTP reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
The five classes
| Class | Range | Meaning | Client should |
|---|---|---|---|
| 1xx | 100-103 | informational, interim | keep waiting |
| 2xx | 200-226 | success | proceed |
| 3xx | 300-308 | redirection | follow, or use the cache |
| 4xx | 400-451 | client error | fix the request, do not blindly retry |
| 5xx | 500-511 | server error | retry with backoff |
The rule that matters in production: 4xx is your fault, 5xx is theirs.
Returning 500 for bad input hides real bugs behind noise, and returning 200 with
{"error": ...} inside defeats every retry, cache, and monitoring layer above
you.
1xx informational
| Code | Name | When it is correct |
|---|---|---|
| 100 | Continue | server accepts headers, client may send the body after Expect: 100-continue |
| 101 | Switching Protocols | WebSocket upgrade, Upgrade: websocket |
| 103 | Early Hints | preload hints sent before the real response |
2xx success
| Code | Name | When it is correct |
|---|---|---|
| 200 | OK | the generic success, body present |
| 201 | Created | a new resource exists, include Location |
| 202 | Accepted | queued for async processing, not done yet |
| 203 | Non-Authoritative Information | a proxy modified the payload |
| 204 | No Content | success with no body, common for DELETE and PUT |
| 205 | Reset Content | clear the form, rare |
| 206 | Partial Content | answering a Range request, needs Content-Range |
| 207 | Multi-Status | WebDAV, per-item results |
| 208 | Already Reported | WebDAV |
| 226 | IM Used | delta encoding |
204 must send no body at all. Sending one is a protocol violation and some
clients will hang waiting to frame it.
3xx redirection
| Code | Name | Method preserved | Cacheable | Use for |
|---|---|---|---|---|
| 300 | Multiple Choices | — | yes | rare, agent-driven negotiation |
| 301 | Moved Permanently | no, POST → GET | yes, aggressively | permanent URL change, SEO |
| 302 | Found | no, POST → GET | only with explicit headers | temporary, ambiguous, avoid |
| 303 | See Other | no, always GET | no | post-then-redirect-to-result |
| 304 | Not Modified | n/a | n/a | conditional GET, no body |
| 307 | Temporary Redirect | yes | no | temporary, method safe |
| 308 | Permanent Redirect | yes | yes | permanent, method safe |
Choosing between them:
- Renaming a URL forever: 301 (or 308 if a POST must stay a POST). - Sending a browser somewhere after a form POST: 303, which converts to GET and stops the refresh-resubmits-the-form problem. - Temporary maintenance page or A/B route: 307. - Never use 302 in new work. Its historical method rewriting is exactly the ambiguity 303 and 307 were added to remove.
301 and 308 are cached hard, sometimes permanently by browsers. A wrong permanent redirect is very hard to take back, so test with 307 first.
4xx client errors
| Code | Name | When it is correct |
|---|---|---|
| 400 | Bad Request | malformed syntax, unparseable JSON, bad framing |
| 401 | Unauthorized | no or invalid credentials, must send WWW-Authenticate |
| 402 | Payment Required | reserved, rarely used |
| 403 | Forbidden | authenticated but not permitted, or refused outright |
| 404 | Not Found | no such resource, also used to hide existence from 403 |
| 405 | Method Not Allowed | wrong method, must send Allow |
| 406 | Not Acceptable | cannot satisfy Accept |
| 407 | Proxy Authentication Required | proxy credentials needed |
| 408 | Request Timeout | client was too slow sending |
| 409 | Conflict | state conflict, duplicate, edit collision |
| 410 | Gone | deleted on purpose and it will not come back |
| 411 | Length Required | Content-Length missing where required |
| 412 | Precondition Failed | If-Match or If-Unmodified-Since did not hold |
| 413 | Content Too Large | body over the limit |
| 414 | URI Too Long | usually a GET that should have been a POST |
| 415 | Unsupported Media Type | wrong or missing Content-Type |
| 416 | Range Not Satisfiable | the requested range is outside the resource |
| 417 | Expectation Failed | cannot meet the Expect header |
| 418 | I'm a teapot | a joke code from RFC 2324, reserved forever |
| 421 | Misdirected Request | wrong connection for this authority |
| 422 | Unprocessable Content | syntax valid, semantics invalid, validation errors |
| 425 | Too Early | replay risk on TLS 1.3 early data |
| 426 | Upgrade Required | must switch protocol, for example to TLS |
| 428 | Precondition Required | server demands a conditional request |
| 429 | Too Many Requests | rate limited, send Retry-After |
| 431 | Request Header Fields Too Large | oversized headers or cookies |
| 451 | Unavailable For Legal Reasons | censorship, takedown |
401 vs 403 is the pair everyone gets wrong. 401 means "I do not know who you
are, authenticate", so it always carries WWW-Authenticate. 403 means "I know who
you are and the answer is no", and re-authenticating will not help.
400 vs 422 is the second. 400 for a body the parser cannot read, 422 for a body that parses fine but fails your rules.
5xx server errors
| Code | Name | When it is correct |
|---|---|---|
| 500 | Internal Server Error | an unhandled exception, the catch-all |
| 501 | Not Implemented | the server does not support this method at all |
| 502 | Bad Gateway | upstream returned garbage or refused the connection |
| 503 | Service Unavailable | down or overloaded, send Retry-After |
| 504 | Gateway Timeout | upstream did not answer in time |
| 505 | HTTP Version Not Supported | version refused |
| 507 | Insufficient Storage | WebDAV, out of space |
| 508 | Loop Detected | infinite loop in processing |
| 511 | Network Authentication Required | captive portal |
The proxy trio, read literally, points straight at the layer to check:
| Code | Meaning behind a reverse proxy | Where to look |
|---|---|---|
| 502 | the app crashed, refused the socket, or spoke nonsense | app process, port, protocol |
| 503 | nothing healthy to route to, or shed load | health checks, replica count, upstream pool |
| 504 | the app is alive but too slow | slow queries, deadlocks, upstream timeouts |
Retrying and error bodies
| Code | Retry? | With what |
|---|---|---|
| 408, 425 | yes | immediately, once |
| 429 | yes | honor Retry-After, then exponential backoff plus jitter |
| 500 | cautiously | only if the request is idempotent |
| 502, 503, 504 | yes | exponential backoff plus jitter, respect Retry-After |
| 4xx (others) | no | fix the request first |
Report errors with RFC 9457 problem details rather than an ad hoc shape, so clients can parse failures generically.
{
"type": "https://example.com/probs/insufficient-stock",
"title": "Not enough stock",
"status": 409,
"detail": "SKU HU-100 has 1 unit left, 2 requested",
"instance": "/orders/8814"
}Serve it as Content-Type: application/problem+json, and keep the status field
identical to the real HTTP status.