The Five Classes
Status codes are grouped by their first digit. Each class has a specific semantic meaning that all HTTP-aware infrastructure understands:
- 1xx — Informational: Request received, continuing process.
- 2xx — Success: Request was received, understood, and accepted.
- 3xx — Redirection: Further action required to complete the request.
- 4xx — Client Error: The request contains bad syntax or cannot be fulfilled by the server.
- 5xx — Server Error: The server failed to fulfil a valid request.
Complete Reference by Class
1xx — Informational
100
Continue
Server received headers; client should proceed with the body. Used with
Expect: 100-continue for large uploads.101
Switching Protocols
Server agrees to upgrade protocol (e.g., HTTP → WebSocket). Sent in response to
Upgrade header.2xx — Success
200
OK
Standard success. The response body contains the resource or result.
Use for: GET, PUT, PATCH that return a body.
201
Created
A new resource was created. Include
Location header pointing to the new resource URL.Use for: successful POST that creates a resource.
202
Accepted
Request accepted for processing, but processing is not yet complete (async operations, queued jobs).
Use for: background jobs, async pipelines.
204
No Content
Success, but no body to return. Response must not include a message body.
Use for: DELETE, PATCH when no body is returned.
206
Partial Content
Server is delivering only part of the resource (range request). Used by video streaming and resumable downloads.
3xx — Redirection
301
Moved Permanently
Resource has a new permanent URL. Browsers and bots cache this forever. Method may change to GET.
Use for: permanent URL migrations. Affects SEO.
302
Found (Temporary Redirect)
Temporarily at a different URL. Not cached. Method may change to GET on redirect.
304
Not Modified
Conditional GET — resource not changed since
If-Modified-Since or ETag match. Client should use cached copy.307
Temporary Redirect
Like 302 but method must not change. A POST to /submit stays a POST after redirect.
308
Permanent Redirect
Like 301 but method must not change. The 301/308 and 302/307 pairs are often confused.
4xx — Client Errors
400
Bad Request
Malformed syntax, invalid request framing, deceptive routing. The catch-all for invalid client input.
Use for: missing required fields, invalid JSON body.
401
Unauthorized
Authentication required or failed. Despite the name, this means unauthenticated. Must include
WWW-Authenticate header.Use for: missing or invalid auth token.
403
Forbidden
Authenticated but not authorised. Server understood the request but refuses to fulfil it.
Use for: valid token, wrong permissions.
404
Not Found
Resource not found. Also used to deliberately obscure 403 (not revealing a resource exists to unauthorised users).
405
Method Not Allowed
HTTP method not supported for this resource. Must include
Allow header listing supported methods.409
Conflict
Request conflicts with current resource state. Duplicate create, optimistic lock failure, version conflict.
410
Gone
Resource permanently deleted and will not return. Unlike 404, signals this was intentional. Useful for cleanup of bookmarks/caches.
422
Unprocessable Entity
Syntactically valid but semantically incorrect. The JSON is valid but the values are wrong (e.g., end date before start date).
429
Too Many Requests
Rate limit exceeded. Include
Retry-After header. Clients must respect this to avoid bans.5xx — Server Errors
500
Internal Server Error
Unhandled exception. Generic catch-all. Log the full error server-side; return a safe message to clients.
502
Bad Gateway
Proxy/gateway received an invalid response from an upstream server. Common during deploys and upstream outages.
503
Service Unavailable
Server temporarily unable to handle requests (overload, maintenance). Include
Retry-After if known.504
Gateway Timeout
Upstream server did not respond in time. Common in microservices when one dependency is slow.
The Codes Most Developers Get Wrong
| Confusion | Correct Thinking |
|---|---|
| 401 vs 403 | 401 = not logged in (unauthenticated). 403 = logged in but not allowed (unauthorised). Two different problems. |
| 400 vs 422 | 400 = bad structure (malformed JSON, wrong content-type). 422 = valid structure, invalid values (business logic violation). |
| 200 for errors | Never return 200 with {"success": false}. Every HTTP-aware tool treats 200 as success. Use 4xx/5xx. |
| 301 vs 308 | 301 allows the method to change to GET on redirect. 308 preserves the original method. Use 308 for API redirects. |
| 404 vs 410 | 404 = resource doesn't exist (or location unknown). 410 = resource existed, was permanently removed. Use 410 to signal intentional deletion. |
✅ Retry Logic Rules
- Safe to auto-retry: 408, 429 (with back-off), 503, 504
- Never auto-retry: 400, 401, 403, 404, 405, 422 (client must fix the request first)
- Idempotent only: 500, 502 — only retry if the request is idempotent (GET, PUT, DELETE)