How HTTP status codes work
An HTTP status code is the three-digit number at the start of every response that tells the client how its request went. The first digit sets the class: 2xx means success, 3xx means look elsewhere, 4xx means the request has a problem, and 5xx means the server failed.
Clients only need to understand the class. RFC 9110 requires a client to treat an unfamiliar code like the x00 code of its class. An unknown 471, for example, is handled as 400 Bad Request.
1xx and 2xx: informational and success
1xx codes are interim messages sent before the final response, such as 101 Switching Protocols when a connection upgrades to WebSocket. You rarely need to act on them. 2xx codes mean the request worked:
- 200 OK: the request succeeded and the body holds the result. Check that a 200 page has real content, since a not-found page sent with 200 is a soft 404.
- 201 Created: a new resource exists, usually after a POST. The Location header should point to it.
- 204 No Content: success with no body, common after a DELETE or an autosave. A browser that gets 204 from a form or link stays on the current page.
3xx: redirects and cached copies
3xx codes tell the client to look somewhere else, usually at the URL in the Location header. The main differences are whether the move is permanent and whether the client may switch a POST to a GET.
- 301 Moved Permanently: the resource has a new permanent URL. Browsers may cache it, and search engines show the new URL in place of the old one. Browsers may change a POST to a GET when following it.
- 302 Found: a temporary move. Search engines keep the original URL, and browsers may also switch POST to GET.
- 303 See Other: fetch the Location URL with GET. It is used after a form POST, so refreshing the result page doesn't submit the form again.
- 304 Not Modified: the client's cached copy is still current, in answer to a conditional request with If-None-Match or If-Modified-Since. It has no body and is not an error.
- 307 Temporary Redirect: like 302, but the client must repeat the same method and body.
- 308 Permanent Redirect: like 301, but the method and body must be kept, which makes it the right choice when moving an API endpoint that receives POST requests.
4xx: problems with the request
4xx codes say the server can't or won't act on the request as sent. Apart from 429, repeating the same request gives the same result, so the request, the URL or the credentials have to change.
- 400 Bad Request: the server couldn't parse the request, for example malformed JSON, invalid URL encoding or an oversized cookie. Check what the client sent; the response body often names the problem.
- 401 Unauthorized: no valid credentials, so despite the name it means unauthenticated. Sign in again or refresh the token; the WWW-Authenticate header names the scheme the server expects.
- 403 Forbidden: the server understood the request and refuses it, and new credentials only help if a different account has access. Firewalls and bot protection also send 403 to automated tools, so a checker can see 403 where your browser sees the page.
- 404 Not Found: the server has nothing at this URL, or won't reveal that it does. Fix or remove links that point to it, or add a 301 if the content moved.
- 405 Method Not Allowed: the URL exists but doesn't accept this method, such as a POST to a read-only page. The Allow header lists the methods it does accept.
- 410 Gone: the resource was removed on purpose and won't return. Google's crawlers treat it the same as a 404.
- 422 Unprocessable Content: the request is well formed but its data fails validation, such as an end date before the start date. It is common in APIs, which usually explain the failure in the body.
- 429 Too Many Requests: the client hit a rate limit. Slow down, and wait for the time given in the Retry-After header if there is one.
5xx: failures on the server side
5xx codes mean the request may have been fine but the server, or something between you and it, failed. The fix usually lies on the server side, so start with the logs from the time of the error.
- 500 Internal Server Error: an unhandled error in the application, such as an exception or a failed database query. The server log or error tracker holds the details.
- 502 Bad Gateway: a proxy, load balancer or CDN got an invalid response from the server behind it, often because the application crashed, restarted or refused the connection.
- 503 Service Unavailable: the server is overloaded or down for maintenance. During planned maintenance, send 503 with a Retry-After header instead of a maintenance page with 200, so clients and crawlers know the outage is temporary.
- 504 Gateway Timeout: a proxy waited too long for the server behind it. Look for slow queries or slow upstream calls, and compare the proxy's timeout with the application's.
Reading status codes in a site audit
In an audit, the final status of each URL matters more than the first one. A link that returns 301, then 301, then 200 works, but each hop costs a round trip. A chain that ends in 404 is a broken link that first looks like a redirect.
Fix 5xx errors and internal links that end in 404 first, then shorten redirect chains, then look for pages that return 200 but show an error. Automated checkers can get 403 or 429 where your browser gets the page, so treat those results as a report on public, automated access.