Every HTTP response carries a three-digit status code, and most developers know maybe eight of them by heart. The rest get looked up — usually at the worst possible moment, while something is broken. This is the full list, organised so you can find what you need, with real attention to the handful of codes people consistently use incorrectly.
The one-line version
The first digit is the whole story: 1xx wait, 2xx it worked, 3xx look elsewhere, 4xx you made a mistake, 5xx the server made a mistake. If you remember nothing else, remember that 4xx blames the client and 5xx blames the server — that single distinction resolves most debugging arguments.
How the five classes work
Status codes are deliberately designed so a client that has never seen a particular code can still handle it sensibly. A client encountering an unknown 418 is required to treat it as a generic 400; an unknown 503 is treated as a generic 500. This is why the classes matter more than the individual numbers — the class carries the actionable meaning, and the specific code carries the detail.
| Class | Name | Meaning | Whose fault |
|---|---|---|---|
| 1xx | Informational | Request received, still processing | Nobody |
| 2xx | Success | Received, understood, accepted | Nobody |
| 3xx | Redirection | Further action needed to complete | Nobody |
| 4xx | Client Error | The request was wrong | The caller |
| 5xx | Server Error | The request was fine; the server failed | The server |
⚠️ The most common status code mistake
Returning 200 OK with an error message in the body. Every monitoring tool, every retry policy, every cache and every search engine reads the status code, not your JSON. An API that answers 200 {"error": "not found"} is invisible to your own alerting. If something went wrong, say so in the status line.
1xx — Informational
| Code | Name | What it means |
|---|---|---|
| 100 | Continue | Headers received; the client may send the body. Used with Expect: 100-continue so a large upload is not wasted on a request the server would reject. |
| 101 | Switching Protocols | The server is changing protocol as requested — this is how a WebSocket handshake completes. |
| 102 | Processing | WebDAV. The request is underway but no response is ready. Largely deprecated. |
| 103 | Early Hints | Sends Link headers before the real response so the browser can start preloading critical assets. A genuine performance win, increasingly supported by CDNs. |
2xx — Success
| Code | Name | What it means |
|---|---|---|
| 200 | OK | The general-purpose success. A GET returns the resource; a POST returns the result. |
| 201 | Created | A new resource now exists. Should include a Location header pointing at it. The correct answer to a successful POST that creates something. |
| 202 | Accepted | Queued, not done. For asynchronous work — the response says "I took this", not "I finished this". |
| 203 | Non-Authoritative Information | A proxy modified the response. Rare. |
| 204 | No Content | Success with an intentionally empty body. The right answer to a DELETE, or a PUT where you have nothing to return. |
| 205 | Reset Content | Tells the client to clear the form it just submitted. Almost never used. |
| 206 | Partial Content | The response to a Range request. Powers video seeking and resumable downloads. |
| 207 | Multi-Status | WebDAV. An XML body carrying several independent statuses. |
| 226 | IM Used | Delta encoding applied. Effectively unused in practice. |
201 vs 202 vs 204
These three are all "it worked" but promise different things, and picking the wrong one misleads clients. 201 guarantees the resource exists now and tells you where. 202 guarantees nothing except that the work is queued — the operation may still fail later, so the client must poll or subscribe to find out. 204 says the operation completed and there is deliberately nothing to send back, which is different from sending an empty body with 200 (that implies there was something to send and it happened to be empty).
3xx — Redirection
| Code | Name | What it means |
|---|---|---|
| 301 | Moved Permanently | The resource has a new permanent URL. Cached indefinitely by browsers. Passes SEO signals. |
| 302 | Found | Temporary. The original URL remains canonical. Historically clients turned POST into GET here. |
| 303 | See Other | "Go GET this other thing." The classic post-then-redirect pattern that stops form resubmission on refresh. |
| 304 | Not Modified | Your cached copy is still fresh. Sent in reply to a conditional request. No body — that is the entire point. |
| 307 | Temporary Redirect | Like 302, but the method and body are guaranteed to be preserved. |
| 308 | Permanent Redirect | Like 301, but the method and body are guaranteed to be preserved. |
💡 The 301/302/307/308 grid
There are only two questions: is the move permanent, and must the HTTP method survive? That gives a two-by-two grid.
- Permanent, method may change: 301
- Permanent, method preserved: 308
- Temporary, method may change: 302
- Temporary, method preserved: 307
The "method may change" wording is historical baggage: the specification for 301 and 302 said the method should be preserved, but browsers converted POST to GET anyway, and the behaviour became too entrenched to fix. 307 and 308 were introduced purely to have codes whose behaviour is unambiguous.
Why 304 matters more than you think
A 304 is the cheapest possible successful response. The client sends If-None-Match with the ETag it already has, or If-Modified-Since with a timestamp; if nothing changed, the server replies 304 with headers only and no body. For a site serving large images or bundles, correct 304 handling can cut bandwidth dramatically while keeping content instantly fresh when it does change.
4xx — Client Error
| Code | Name | What it means |
|---|---|---|
| 400 | Bad Request | Malformed syntax. The server could not parse what you sent. |
| 401 | Unauthorized | Authentication required or failed. Must include a WWW-Authenticate header. Misnamed — it means unauthenticated. |
| 402 | Payment Required | Reserved since 1997. Some APIs now use it for billing failures. |
| 403 | Forbidden | Authenticated but not permitted. Re-authenticating will not help. |
| 404 | Not Found | No resource at this URL. The server will not say whether it ever existed. |
| 405 | Method Not Allowed | The URL exists but not for this verb. Must include an Allow header listing what is permitted. |
| 406 | Not Acceptable | Cannot produce a response matching the client's Accept headers. |
| 407 | Proxy Authentication Required | Like 401, but for the proxy rather than the origin. |
| 408 | Request Timeout | The client took too long to send its request. |
| 409 | Conflict | The request clashes with current state — an edit conflict, or a duplicate unique key. |
| 410 | Gone | Deliberately deleted and not coming back. Stronger than 404; search engines de-index faster. |
| 411 | Length Required | A Content-Length header is mandatory here. |
| 412 | Precondition Failed | An If-Match style condition was not met. The basis of optimistic locking. |
| 413 | Content Too Large | The upload exceeds the server limit. Formerly "Payload Too Large". |
| 414 | URI Too Long | Usually a GET that should have been a POST. |
| 415 | Unsupported Media Type | The Content-Type is one the endpoint will not accept. |
| 416 | Range Not Satisfiable | The requested byte range lies outside the file. |
| 417 | Expectation Failed | The Expect header cannot be met. |
| 418 | I'm a Teapot | An April Fools' joke from 1998 that was never removed. Genuinely reserved. |
| 421 | Misdirected Request | This server cannot produce a response for the requested authority. |
| 422 | Unprocessable Content | Syntax is valid; semantics are not. The standard validation-failure code. |
| 423 | Locked | WebDAV. The resource is locked. |
| 424 | Failed Dependency | WebDAV. A previous request in the chain failed. |
| 425 | Too Early | Refusing to risk replay of an early-data request. |
| 426 | Upgrade Required | Switch protocol — usually to TLS. |
| 428 | Precondition Required | Forces conditional requests to prevent lost updates. |
| 429 | Too Many Requests | Rate limited. Should include Retry-After. |
| 431 | Request Header Fields Too Large | Usually an oversized cookie. |
| 451 | Unavailable For Legal Reasons | Blocked by law. The number references Fahrenheit 451. |
404 vs 410, and why it matters for search
Both say the resource is not here. 404 is agnostic — it might return, it might never have existed. 410 Gone is a definite statement: this existed, we removed it deliberately, stop asking. Search engines act on that difference: a 410 typically drops out of the index faster than a 404, which they may re-crawl for weeks in case it was a mistake. If you have permanently retired a section of a site, 410 is the honest and faster signal.
The soft 404 problem
A soft 404 is a page that looks like an error to a human but returns 200 OK to a machine. It happens most often with single-page applications, where the server returns the app shell for every path and the router decides afterwards that the route does not exist. By then the status code has already been sent. Search engines index these as real pages, filling your index with hundreds of identical "page not found" entries. The fix is server-side: the server must know which routes exist and return a genuine 404 status for the rest.
5xx — Server Error
| Code | Name | What it means |
|---|---|---|
| 500 | Internal Server Error | The catch-all. Something threw an exception and nobody handled it. |
| 501 | Not Implemented | The server does not support this method at all, for any resource. |
| 502 | Bad Gateway | A proxy got an invalid response from upstream. Classic sign that your application server is down behind nginx. |
| 503 | Service Unavailable | Temporarily overloaded or in maintenance. Should include Retry-After. The correct code for planned downtime. |
| 504 | Gateway Timeout | The upstream server did not answer in time. The app is up but too slow. |
| 505 | HTTP Version Not Supported | Rare. |
| 507 | Insufficient Storage | WebDAV. Out of disk. |
| 508 | Loop Detected | WebDAV. Infinite recursion while processing. |
| 511 | Network Authentication Required | A captive portal — the hotel wifi login page. |
502 vs 503 vs 504 tells you where to look
These three are the everyday operational codes and they point at genuinely different failures:
- 502 Bad Gateway — the proxy reached your app and got garbage back, or could not connect at all. Check whether the application process is running and listening on the expected port.
- 503 Service Unavailable — the server is deliberately refusing work. Check for maintenance mode, a full connection pool, or a load shedder doing its job.
- 504 Gateway Timeout — the app accepted the connection and never finished. Check for slow database queries, deadlocks, or an external API you depend on hanging.
The distinction is worth wiring into your alerting. A spike in 504s and a spike in 502s call for completely different first moves, and treating them as one "5xx rate" metric throws away the most useful signal you have.
✅ Always send Retry-After with 503 and 429
Both codes mean "try again later", and without Retry-After the client has to guess. Guessing usually means retrying immediately, which is exactly what you do not want from a service that is already overloaded. The header accepts either a number of seconds or an HTTP date.
Choosing the right code: a decision path
When you are writing an endpoint and are unsure, walk this in order:
- Did the server fail through no fault of the caller? → 5xx. Pick 503 if it is temporary and expected, 500 if it is an unhandled bug.
- Could the client not be identified? → 401.
- Is the client identified but not permitted? → 403.
- Does the resource not exist? → 404, or 410 if it was deliberately removed.
- Does the URL exist but not for this method? → 405, with an
Allowheader. - Could the body not be parsed? → 400.
- Did it parse but fail validation? → 422.
- Does it clash with current state? → 409.
- Did you create something? → 201 with a
Locationheader. - Did it work with nothing to return? → 204.
- Otherwise → 200.
Checking status codes yourself
The fastest way to see what a server is really sending — bypassing any friendly error page your browser might substitute:
In the browser, the Network tab of developer tools shows the status for every request. Two things to watch for: a chain of several redirects where one would do (each hop costs a full round trip), and any request returning 200 that should have failed.
Reading a messy API response?
Paste the JSON body and get it formatted, validated and readable in a second — entirely in your browser, nothing uploaded.
Open the JSON Formatter →The short list worth memorising
You will never need most of the codes above. In day-to-day work these twelve cover almost everything: 200, 201, 204, 301, 302, 304, 400, 401, 403, 404, 429, 500. Learn those properly, understand the 401/403 and 400/422 distinctions, and bookmark this page for the rest.
The underlying principle is worth more than the list: a status code is a machine-readable contract about what happened and what the client should do next. Every time you reach for 200 because it is easier, you are breaking that contract for every cache, proxy, monitor and crawler between you and your user.
Frequently Asked Questions
What is the difference between 401 and 403?
401 Unauthorized means the server does not know who you are — you sent no credentials, or the ones you sent were invalid. Retrying with valid credentials could succeed. 403 Forbidden means the server knows exactly who you are and you are still not allowed. Retrying with the same identity will never succeed. In short: 401 is 'who are you?', 403 is 'not you'.
Should I use 301 or 308 for a permanent redirect?
Use 301 for ordinary page moves. It is universally supported and is what search engines expect. Use 308 only when you must guarantee that a POST request stays a POST after redirecting — 301 historically allowed clients to convert POST to GET, and many still do. For SEO purposes both pass ranking signals, but 301 has decades of proven behaviour behind it.
Is a 404 bad for SEO?
No. A 404 for a page that genuinely does not exist is correct and healthy. What harms you is returning 200 OK for a missing page — a soft 404 — because search engines then index an error page as real content. Also avoid redirecting every 404 to your homepage; Google treats that as a soft 404 too. Return a real 404 with a helpful page.
What does 429 Too Many Requests mean?
You have exceeded a rate limit. The response should include a Retry-After header telling you how many seconds to wait, or a date after which to retry. Well-behaved clients read that header and back off; clients that immediately retry usually make the situation worse and get blocked for longer.
When should an API return 422 instead of 400?
Return 400 Bad Request when the request itself is malformed — broken JSON, a missing required header, a payload the parser cannot read. Return 422 Unprocessable Content when the syntax is perfectly valid but the meaning is wrong, such as a well-formed JSON body with an email field that is not an email address. The distinction tells the client whether to fix its serialisation or its data.