HTTP status codes
What each code means in practice, including the pairs everyone mixes up: 401 vs 403, 502 vs 504, 400 vs 422.
- 100Continue
Keep sending the body. You will rarely see it — clients handle it internally.
- 101Switching Protocols
The WebSocket upgrade handshake succeeded.
- 200OK
It worked. The body is the answer.
- 201Created
It worked and something now exists. Return where in a Location header.
- 202Accepted
Queued for later. Nothing is done yet — pair it with a way to check progress.
- 204No Content
It worked and there is deliberately no body. DELETEs often end here.
- 206Partial Content
A range request: this is a slice of the file. Video seeking lives on it.
- 301Moved Permanently
Gone for good, go here instead. Browsers and crawlers cache it hard — a wrong 301 is painful to claw back.
- 302Found
Temporary redirect that historically lets clients change POST to GET. When in doubt you probably want 303 or 307.
- 303See Other
Result is elsewhere; fetch it with GET. The right answer after a form POST.
- 304Not Modified
Your cached copy is still good. The reward for sending If-None-Match.
- 307Temporary Redirect
Like 302 but the method must not change — a POST stays a POST.
- 308Permanent Redirect
Like 301 but the method must not change.
- 400Bad Request
The request itself is malformed. If it parsed but fails your rules, 422 is often more precise.
- 401Unauthorized
Misnamed: it means UNAUTHENTICATED — we do not know who you are. Sign in and retry.
- 402Payment Required
Reserved for decades, now used honestly by billed APIs: you are out of credit.
- 403Forbidden
We know who you are, and the answer is no. Authenticating harder will not help.
- 404Not Found
No such thing — or you are not allowed to know whether there is; returning 404 for both avoids leaking existence.
- 405Method Not Allowed
The path exists but not with that verb. Send Allow: with the ones that work.
- 408Request Timeout
The client took too long to send. Compare 504, where a server upstream took too long to answer.
- 409Conflict
The request fights the current state — a duplicate slug, a stale version. Retrying unchanged will not fix it.
- 410Gone
Existed, deliberately removed, not coming back. A more honest 404 for retired resources.
- 412Precondition Failed
Your If-Match no longer matches — someone changed it first. Optimistic locking speaks in this code.
- 413Content Too Large
The body is over the limit. Say what the limit is in the response.
- 415Unsupported Media Type
Wrong Content-Type — often JSON sent without the header.
- 418I'm a teapot
An April Fools RFC. Never send it from anything you bill for.
- 422Unprocessable Content
Parsed fine, fails validation. The usual home of field-by-field error responses.
- 429Too Many Requests
Rate limited. Send Retry-After, and clients: honour it with backoff.
- 500Internal Server Error
The server broke. If you write it by hand, something more specific is usually truer.
- 501Not Implemented
The server does not know that verb at all. Rare in practice.
- 502Bad Gateway
A proxy reached the backend and got garbage — often a crashed or restarting app behind nginx or Caddy.
- 503Service Unavailable
Temporarily down or overloaded — deploys, maintenance, circuit breakers. Retry-After is polite.
- 504Gateway Timeout
A proxy waited for the backend and gave up. The request may STILL have executed — never assume it did not.