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

CodeStatusMeaning
100ContinueInitial part of request received, continue. Used with Expect: 100-continue.
101Switching ProtocolsServer agrees to switch protocols (HTTP→WebSocket upgrade).
103Early HintsPreload hints sent before final response. Used by Cloudflare for performance.

2xx — Success

CodeStatusMeaning
200OKStandard success. Most common response.
201CreatedResource created. Usually with a Location header pointing to the new resource.
202AcceptedAccepted for processing but not complete. Async operations.
204No ContentSuccess, nothing to return. Common for DELETE and PUT.
206Partial ContentRange request fulfilled. Video streaming, resumable downloads.

3xx — Redirection

CodeStatusWhen to use
301Moved PermanentlyResource has moved forever. Search engines update their index. Cacheable.
302FoundTemporary redirect. Historically browsers GET-ify POSTs after this.
303See OtherAlways GET the new URL. Used after POST to redirect to the result.
304Not ModifiedConditional GET — your cached copy is still valid. No body returned.
307Temporary RedirectSame as 302 but explicitly preserves method (POST stays POST).
308Permanent RedirectSame as 301 but explicitly preserves method.
301 vs 302 in practice

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

CodeStatusMeaning
400Bad RequestGeneric client error — malformed JSON, missing field.
401UnauthorizedNo (or invalid) auth. Must include WWW-Authenticate header.
402Payment RequiredOriginally reserved for paid APIs. Stripe and some others use it.
403ForbiddenAuthenticated but lack permission. Don't retry with same creds.
404Not FoundResource doesn't exist. May also hide that 403 would apply.
405Method Not AllowedResource exists but you used the wrong method (GET instead of POST).
408Request TimeoutClient took too long to send the request.
409ConflictRequest conflicts with current state. Optimistic locking, version mismatch.
410GoneResource permanently removed. Stronger than 404 — search engines deindex.
413Payload Too LargeRequest body exceeds server's limit.
414URI Too LongURL exceeds the limit (usually around 8 KB).
415Unsupported Media TypeServer can't process this Content-Type.
418I'm a teapotApril Fool's joke from 1998 (RFC 2324). Some sites use it for "blocked".
422Unprocessable EntityJSON parsed but semantically wrong. Validation errors.
429Too Many RequestsRate limited. Retry-After header tells you when.
431Request Header Fields Too LargeHeaders exceed server limit. Often too-many cookies.
451Unavailable For Legal ReasonsContent blocked by court order. Named after Fahrenheit 451.

5xx — Server Error

CodeStatusMeaning
500Internal Server ErrorGeneric server error. Stack trace ate the request. Check logs.
501Not ImplementedServer doesn't recognize the method (PATCH on a server that doesn't support it).
502Bad GatewayReverse proxy got an invalid response from upstream. Backend is down.
503Service UnavailableServer overloaded or under maintenance. Retry-After may say when.
504Gateway TimeoutReverse proxy timed out waiting for upstream. Backend is slow.
507Insufficient StorageServer is out of disk (WebDAV).
511Network Authentication RequiredCaptive portal — sign in to Wi-Fi to continue.
520-527Cloudflare codes520=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

ScenarioCode
GET request worked200
POST created a new resource201 (with Location header)
DELETE succeeded204 or 200
User not logged in401
User logged in but lacks permission403
JSON validation failed422 (or 400)
Rate limit hit429 (with Retry-After)
Permanent URL change301
Temporary URL change (login flow, A/B test)302 or 307
Database connection failed503
Unhandled exception in your code500

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:

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:

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.