How-To & Life · Guide · Developer Utilities
How to understand HTTP status codes
Class-by-class breakdown, 301 vs 302 vs 307, 401 vs 403, when to use 422, crawler implications, and the weird ones (418, 451).
HTTP status codes are the three-digit numbers every request comes back with. The first digit groups them into five classes, and once you know the class you know roughly what happened: 1xx still working, 2xx all good, 3xx look elsewhere, 4xx you asked wrong, 5xx we blew up. Underneath the simple framing lies RFC 9110 (the current HTTP semantics spec, published June 2022) plus about a dozen auxiliary RFCs that add codes for WebDAV, rate limiting, and legal constraints. Picking the right code matters: it drives cache behavior, retries, search-engine indexing, and browser UI like the default error page. This guide covers all five classes with the codes that actually get used in production, the common retry and indexing implications, the difference between 301 and 302, when 503 is correct and when it is lazy, and the codes people reach for that they should not.
Advertisement
The five classes
The first digit of the status code determines the class:
1xx informational — request received, continuing to process. Rare to see in application code.
2xx success — the request worked.
3xx redirection — further action needed (usually a different URL).
4xx client error — the client sent a bad request.
5xx server error — the server failed to handle a valid request.
1xx informational
100 Continue — server has received the request headers and the client may send the body. Used with Expect: 100-continue for large uploads so the client can abandon early if the server is going to reject.
101 Switching Protocols — sent in response to an Upgrade header, most commonly switching HTTP to WebSocket.
103 Early Hints — lets the server hint at resources the client should preload while the real response is still being generated. Supported in Chrome 103+ and increasingly used by CDNs.
2xx success
200 OK — the default success. The response body contains whatever was asked for.
201 Created — a new resource was created. Include a Location header pointing at the new resource. REST convention for POSTs that create.
202 Accepted — the request has been queued but not yet processed. Used for async jobs.
204 No Content — success, and there is intentionally no body. DELETE typically returns 204.
206 Partial Content — response to a Range request. Used for resumable downloads and video streaming.
3xx redirection
301 Moved Permanently — the resource has a new canonical URL and will not move back. Search engines transfer link equity to the new URL. Browsers cache 301s aggressively; a wrong 301 is painful to reverse. Use when you mean it forever.
302 Found — temporary redirect. Browsers follow it but do not cache the redirect itself. Historical note: RFC 2616 allowed clients to change POST to GET on 302; RFC 9110 says they should not, but many do anyway, which is why 307 and 308 exist.
303 See Other — explicitly changes the method to GET. Classic use: after a POST that creates a resource, respond with 303 pointing at the created resource’s URL, so a browser refresh does not re-submit.
304 Not Modified — response to a conditional GET (If-Modified-Since or If-None-Match) when the resource has not changed. No body. The browser uses its cached copy.
307 Temporary Redirect — like 302 but the method must not change. POST stays POST.
308 Permanent Redirect — like 301 but the method must not change. Useful for permanently redirecting API endpoints.
4xx client errors
400 Bad Request — the request is malformed (bad JSON, missing required field). Generic.
401 Unauthorized — authentication is required and was not provided or is invalid. Misleadingly named — this is really “unauthenticated.” Include a WWW-Authenticate header.
403 Forbidden — authenticated, but the credentials do not permit this action. Use for authorization failures.
404 Not Found — the resource does not exist. Search engines will eventually deindex 404 URLs.
405 Method Not Allowed — the URL exists but does not handle this HTTP method. Include an Allow header listing the valid methods.
408 Request Timeout — the client took too long to send the request. Some CDNs use 408 where they should use 504.
409 Conflict — the request would create a conflict (duplicate key, edit conflict in a wiki). Client can usually fix and retry.
410 Gone — the resource used to exist and has been permanently removed. Stronger than 404 for SEO; tells Google to deindex faster.
413 Payload Too Large — body exceeds server limits.
418 I'm a teapot — from RFC 2324, the HTCPCP April Fools’ spec. Some teams use it as a joke health-check response.
422 Unprocessable Content — syntactically valid but semantically invalid (e.g., JSON parsed but fields failed validation). Preferred by APIs over plain 400 for validation errors.
429 Too Many Requests — rate limit exceeded. Include a Retry-After header with seconds to wait.
451 Unavailable For Legal Reasons — the resource is blocked by a court or government order. The number is a Fahrenheit 451 reference.
5xx server errors
500 Internal Server Error — generic server-side failure. Usually means an unhandled exception.
501 Not Implemented — the server does not support the method. Different from 405 (method not allowed for this URL).
502 Bad Gateway — an upstream server gave a bad response. Usually means the reverse proxy (Nginx, CDN) could not reach or parse the origin.
503 Service Unavailable — the server is temporarily unable to handle the request. Use for planned maintenance or overload. Include Retry-After. Search engines treat brief 503s as transient; prolonged 503s start to hurt rankings.
504 Gateway Timeout — upstream server did not respond in time.
511 Network Authentication Required — captive portals use this to tell clients the network requires login.
Caching implications
Proxies and browsers cache certain codes by default even without explicit headers: 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501. Everything else requires explicit Cache-Control. A 301 you serve today may be cached for a year — if you change your mind, the cache is the enemy.
Retry behavior
Well-behaved clients retry automatically on certain codes. 408, 425, 429, 500, 502, 503, 504 are generally retriable with exponential backoff. 4xx other than those are not — retrying a 400 or 404 gives you the same result.
Idempotent methods (GET, PUT, DELETE, HEAD, OPTIONS) are safe to retry. POST generally is not — retrying after a network failure might create the resource twice. Use an idempotency key header on write endpoints for safe retries.
Status codes and search engines
Googlebot and other crawlers key heavily off status codes.
200: crawl and index.
301, 308: transfer signals to the new URL, update the index.
302, 307: follow, but do not transfer signals. Prolonged 302s eventually get treated as 301.
404, 410: drop from index. 410 is faster.
503: come back later. A site returning 503s for a week starts losing rankings.
Common mistakes
Returning 200 with an error body. “HTTP 200, JSON says success: false.” Breaks every retry policy, every monitoring alert, every CDN stat. Use the right status code.
Using 401 for authorization failures. 401 means “authenticate, please;” 403 means “authenticated but forbidden.” Mixing them up breaks OAuth flows.
301 when you mean 302. A permanent redirect caches in browsers and search engines long after you change your mind. Use 302 for anything you might reverse.
500 for every error. A 500 is “we crashed.” Validation failures are 400 or 422. Not-found is 404. Use the specific code so monitoring can triage.
Missing Retry-After on 429 and 503. Clients have no idea how long to wait. Libraries often default to aggressive retries that amplify the problem.
Using 404 for access-control hiding. Some sites return 404 when a resource exists but the user cannot see it (to avoid leaking existence). Valid privacy technique but breaks clients expecting 403.
Run the numbers
Look up any status code with expected behavior and caching rules via the HTTP status code lookup. Pair with the MIME type lookup when both Content-Type and status are in play, and the user agent parser for debugging bot-specific status behavior.
Advertisement