HTTP Status Codes Reference
Every HTTP response code explained: 1xx through 5xx. When each is used, what to do about it.
The complete HTTP status code reference
Every HTTP response carries a 3-digit status code. The first digit indicates the category (1=info, 2=success, 3=redirect, 4=client error, 5=server error). Here are all the codes you'll see in real traffic, plus what each means.
1xx — Informational
| Code | Status | Meaning |
|---|---|---|
| 100 | Continue | Initial part of request received, continue. Used with Expect: 100-continue. |
| 101 | Switching Protocols | Server agrees to switch protocols (HTTP→WebSocket upgrade). |
| 103 | Early Hints | Preload hints sent before final response. Used by Cloudflare for performance. |
2xx — Success
| Code | Status | Meaning |
|---|---|---|
| 200 | OK | Standard success. Most common response. |
| 201 | Created | Resource created. Usually with a Location header pointing to the new resource. |
| 202 | Accepted | Accepted for processing but not complete. Async operations. |
| 204 | No Content | Success, nothing to return. Common for DELETE and PUT. |
| 206 | Partial Content | Range request fulfilled. Video streaming, resumable downloads. |
3xx — Redirection
| Code | Status | When to use |
|---|---|---|
| 301 | Moved Permanently | Resource has moved forever. Search engines update their index. Cacheable. |
| 302 | Found | Temporary redirect. Historically browsers GET-ify POSTs after this. |
| 303 | See Other | Always GET the new URL. Used after POST to redirect to the result. |
| 304 | Not Modified | Conditional GET — your cached copy is still valid. No body returned. |
| 307 | Temporary Redirect | Same as 302 but explicitly preserves method (POST stays POST). |
| 308 | Permanent Redirect | Same as 301 but explicitly preserves method. |
Use 301 when the URL has permanently changed (renamed pages, new domain). Search engines transfer ranking signals. Use 302 for temporary redirects (A/B tests, maintenance, login redirects). Picking the wrong one can hurt SEO badly.
4xx — Client Error
| Code | Status | Meaning |
|---|---|---|
| 400 | Bad Request | Generic client error — malformed JSON, missing field. |
| 401 | Unauthorized | No (or invalid) auth. Must include WWW-Authenticate header. |
| 402 | Payment Required | Originally reserved for paid APIs. Stripe and some others use it. |
| 403 | Forbidden | Authenticated but lack permission. Don't retry with same creds. |
| 404 | Not Found | Resource doesn't exist. May also hide that 403 would apply. |
| 405 | Method Not Allowed | Resource exists but you used the wrong method (GET instead of POST). |
| 408 | Request Timeout | Client took too long to send the request. |
| 409 | Conflict | Request conflicts with current state. Optimistic locking, version mismatch. |
| 410 | Gone | Resource permanently removed. Stronger than 404 — search engines deindex. |
| 413 | Payload Too Large | Request body exceeds server's limit. |
| 414 | URI Too Long | URL exceeds the limit (usually around 8 KB). |
| 415 | Unsupported Media Type | Server can't process this Content-Type. |
| 418 | I'm a teapot | April Fool's joke from 1998 (RFC 2324). Some sites use it for "blocked". |
| 422 | Unprocessable Entity | JSON parsed but semantically wrong. Validation errors. |
| 429 | Too Many Requests | Rate limited. Retry-After header tells you when. |
| 431 | Request Header Fields Too Large | Headers exceed server limit. Often too-many cookies. |
| 451 | Unavailable For Legal Reasons | Content blocked by court order. Named after Fahrenheit 451. |
5xx — Server Error
| Code | Status | Meaning |
|---|---|---|
| 500 | Internal Server Error | Generic server error. Stack trace ate the request. Check logs. |
| 501 | Not Implemented | Server doesn't recognize the method (PATCH on a server that doesn't support it). |
| 502 | Bad Gateway | Reverse proxy got an invalid response from upstream. Backend is down. |
| 503 | Service Unavailable | Server overloaded or under maintenance. Retry-After may say when. |
| 504 | Gateway Timeout | Reverse proxy timed out waiting for upstream. Backend is slow. |
| 507 | Insufficient Storage | Server is out of disk (WebDAV). |
| 511 | Network Authentication Required | Captive portal — sign in to Wi-Fi to continue. |
| 520-527 | Cloudflare codes | 520=Unknown, 521=Web Server Down, 522=Timeout, 523=Origin Unreachable, 524=Timeout, 525=SSL Handshake, 526=Invalid SSL. |
Quick reference: when to return which code
| Scenario | Code |
|---|---|
| GET request worked | 200 |
| POST created a new resource | 201 (with Location header) |
| DELETE succeeded | 204 or 200 |
| User not logged in | 401 |
| User logged in but lacks permission | 403 |
| JSON validation failed | 422 (or 400) |
| Rate limit hit | 429 (with Retry-After) |
| Permanent URL change | 301 |
| Temporary URL change (login flow, A/B test) | 302 or 307 |
| Database connection failed | 503 |
| Unhandled exception in your code | 500 |
Reading status codes fast
HTTP status codes tell you the outcome of every request at a glance if you know how to read them. The first digit tells you the category — 2xx success, 3xx redirect, 4xx client error, 5xx server error. That single-digit read is enough to decide what to do next in almost every troubleshooting scenario.
Common patterns worth internalizing:
- Everything working: 200 responses everywhere
- User error (bad URL, unauthorized, wrong method): 4xx
- Server broken: 5xx
- Something moved or requires redirection: 3xx
- Waiting on something: 1xx or 202
The status codes I see most often
200 OK
Everything worked. Response contains the requested content. The default success response for GET requests.
201 Created
The request created a new resource. Common response from REST APIs after a successful POST. Response should include a Location header pointing at the new resource's URL.
204 No Content
Success, but there's no body to return. Common after DELETE operations, and after PUT operations that don't need to echo back the state.
301 Moved Permanently
The resource has permanently moved. Browsers cache this aggressively and update their bookmarks. Use for permanent URL changes — a page that used to be at /old-url now lives at /new-url.
302 Found (temporary redirect)
The resource is at a different URL right now, but this might change. Browsers don't cache this. Use for temporary redirects like "user isn't logged in, send them to the login page and they'll come back afterward."
304 Not Modified
Response to conditional requests. The client sent an If-Modified-Since or If-None-Match header, and the server confirms the client's cached copy is still current. No body returned, saving bandwidth. Critical for CDN and browser caching efficiency.
400 Bad Request
The client sent something malformed. Bad JSON, missing required fields, invalid parameters. The response body should explain what specifically was wrong.
401 Unauthorized
Authentication required or authentication failed. Response includes a WWW-Authenticate header describing what kind of auth is expected. The name "unauthorized" is a bit misleading — 401 means "not authenticated" more than "not authorized."
403 Forbidden
Authenticated but not permitted to access this resource. Distinct from 401. Common cause: valid session but the user doesn't have permission for this specific action.
404 Not Found
The resource doesn't exist. Also commonly used when the resource exists but the requester isn't supposed to know about it (returning 404 instead of 403 hides the existence of restricted content).
405 Method Not Allowed
The URL exists but doesn't support the HTTP method you used. Common: trying to POST to a URL that only accepts GET. Response includes an Allow header listing what methods are supported.
409 Conflict
The request can't be completed because it conflicts with the current state. Common in REST APIs when trying to create something that already exists, or updating a resource that's changed since you fetched it.
410 Gone
The resource used to exist but is permanently removed. More explicit than 404. Rarely used because 404 is easier and clients handle it the same way.
418 I'm a teapot
A joke from RFC 2324 (April Fools 1998). Still occasionally used by services that want to indicate a specific "I refuse to do this" without a real reason. Not to be relied on for anything serious.
429 Too Many Requests
Rate limiting. The client has sent too many requests in some time window. Response should include a Retry-After header indicating when to try again.
500 Internal Server Error
Something went wrong on the server and the server doesn't want to be more specific about what. Generic catch-all for unexpected exceptions in server code.
502 Bad Gateway
The server acting as a gateway or proxy received an invalid response from the upstream server. Common in reverse-proxy setups when the backend is unavailable or crashing.
503 Service Unavailable
The server is temporarily unable to handle the request. Maintenance mode, overload, or upstream dependency failure. Should include a Retry-After header.
504 Gateway Timeout
Similar to 502, but the specific issue is that the upstream took too long to respond. Common in situations where an origin server is slow or unreachable.
Where status codes commonly get misused
Using 200 for errors
APIs that return 200 with an error message in the body defeat all the standard tooling around HTTP status codes. Monitoring can't detect errors, retries don't happen automatically, and every client has to parse the body to figure out what happened. Use appropriate 4xx or 5xx codes for actual errors.
Using 404 for authorization failures
Some APIs return 404 when the resource exists but the caller isn't authorized to see it. This is defensible for security reasons (avoiding revealing what resources exist), but it makes debugging confusing. Use 403 unless there's a specific reason to obfuscate.
Returning 200 in a 3xx-shaped response
A response with a Location header but a 200 status doesn't trigger a browser redirect. Use 301 or 302 for actual redirects.
Returning 500 for expected error conditions
500 should be for truly unexpected exceptions. Validation failures, authentication problems, and other expected error paths should have appropriate 4xx codes so clients can react appropriately.
Not using 304 for cacheable content
Serving fresh 200 responses for content that hasn't changed wastes bandwidth. Proper Cache-Control and ETag or Last-Modified headers, combined with 304 responses to conditional requests, dramatically reduce load and improve performance.
Status codes and CDN behavior
CDNs cache responses based on status codes and headers. Common behaviors:
- 200 with cache-control public: cached for the specified duration
- 301 permanent redirect: cached aggressively; hard to invalidate later
- 302 temporary redirect: usually not cached
- 404: sometimes cached with a short TTL to avoid hammering origin for missing content
- 5xx: usually not cached; treated as errors that shouldn't propagate
Understanding your CDN's specific caching behavior for each status code prevents surprises when 301s stick around longer than expected or when 404s stop showing for content you've just added.
Debugging status codes from the client side
Browser dev tools
The Network tab shows every request's status code, response headers, and timing. First stop for any browser-based debugging.
curl
curl -v shows the full request and response including headers. curl -I sends a HEAD request to just get the response headers without the body.
Server logs
Every request's status code is logged. Grepping for 5xx responses is the fast way to find real errors. Grepping for 4xx responses reveals client-side issues (bad URLs, authentication problems, method mismatches).
Related tools
For inspecting HTTP headers (which pair with status codes to tell you what actually happened), use the HTTP Headers Inspector. For understanding whether a site's TLS is working correctly (a broken TLS is one cause of hard-to-diagnose connection errors), use the SSL/TLS Cert Inspector. For seeing where a domain's traffic actually goes, use the Domain Infrastructure Lookup.
