tallge

Reference / HTTP status codes

HTTP status codes and when you meet them

Not every registered code, only those that show up in browsers, logs and API clients. For each one: what usually causes it, and what the client should do next.

The five classes

The five classes of HTTP status codes from 100 to 599, with a tick for each code on this page1xx informational1002xx success2003xx redirection3004xx client error4005xx server error500599
Each tick is one code listed below. 4xx means the request should change; 5xx means retrying later may help.

Clients that do not know a code must treat it as the x00 code of its class, so an unknown 4xx is handled as 400 and an unknown 5xx as 500.

1xx: informational

CodeNameWhen you meet it
100ContinueA client sent Expect: 100-continue before a large upload, and the other side agrees to receive the body. curl sends this header on its own for larger uploads.
101Switching ProtocolsThe response to a WebSocket upgrade request over HTTP/1.1. Over HTTP/2 a WebSocket opens with an extended CONNECT answered by 200 (RFC 8441).

2xx: success

CodeNameWhen you meet it
200OKThe normal success response with a body.
201CreatedA POST or PUT created a resource. A Location header should point to it.
202AcceptedThe request was queued for later processing; nothing has happened yet.
204No ContentSuccess with no body, typical for DELETE and for PUT that returns nothing. A 204 response cannot carry content (RFC 9110).
206Partial ContentThe answer to a Range request: resumed downloads, video seeking.

3xx: redirection

CodeNameWhen you meet it
301Moved PermanentlyThe URL changed for good. Browsers cache it hard, so test a new 301 carefully. Clients may turn a POST into a GET.
302FoundA temporary redirect. Like 301, clients usually switch POST to GET.
303See OtherAfter a form POST, send the browser to a result page with GET. This is the redirect to use after a POST.
304Not ModifiedThe cached copy is still valid after a conditional request with If-None-Match or If-Modified-Since. No body.
307Temporary RedirectLike 302, but the method and body must be kept. Chrome’s developer tools also show the browser’s own HSTS upgrade from http to https as a 307 "Internal Redirect"; that one never came from the server.
308Permanent RedirectLike 301, but the method and body must be kept.

Choosing a redirect: permanent and safe for any method, 308. Temporary and method-preserving, 307. After a form submission, 303.

4xx: client errors

CodeNameWhen you meet it
400Bad RequestThe request is malformed: broken JSON, a missing required field, a header that cannot be parsed.
401UnauthorizedMeans unauthenticated: no credentials, or expired ones. Must include WWW-Authenticate.
403ForbiddenCredentials are known but not sufficient, or access is refused for another reason, such as file permissions or an access rule.
404Not FoundNothing at this URL. Also used deliberately instead of 403 to avoid confirming that a resource exists.
405Method Not AllowedThe URL exists but not for this method, for example POST to a static file. Must include Allow, listing the methods that do work.
406Not AcceptableNo representation matches the Accept headers. Rare; most sites ignore Accept and return what they have.
408Request TimeoutThe client opened a connection but did not finish sending a request in time. Browsers that open connections in advance and leave them unused can cause it.
409ConflictThe request conflicts with current state: a duplicate unique key, an edit to an outdated version.
410GoneRemoved on purpose and not coming back. It states the intent more clearly than 404, but Google documents that its crawler treats every 4xx code except 429 the same way.
412Precondition FailedAn If-Match check failed: someone else changed the resource first. This is the basis of optimistic locking over HTTP.
413Content Too LargeThe body exceeds a size limit. An upload limit configured in front of the application is the usual cause.
414URI Too LongUsually a GET with a huge query string that should have been a POST body.
415Unsupported Media TypeWrong or missing Content-Type, for example JSON sent as text/plain.
422Unprocessable ContentSyntactically valid but semantically wrong input; many APIs use it for validation errors.
429Too Many RequestsRate limited. If Retry-After is present, it gives a number of seconds or a date to wait for; respect it, and without it back off exponentially.
431Request Header Fields Too LargeUsually an oversized cookie or a very long Authorization header. Clearing cookies for the site fixes it for users.

401 versus 403: if logging in (again) could help, it is 401. If the user is known and still not allowed, it is 403.

5xx: server errors

CodeNameWhen you meet it
500Internal Server ErrorAn unhandled exception in the application. The response says nothing useful; the application log does.
501Not ImplementedThe method is not supported at all. Rare in practice.
502Bad GatewayA gateway or load balancer in front of the application got no valid response from it: the application crashed, is restarting, or closed the connection.
503Service UnavailableOverloaded or in maintenance; temporary by definition. Retry-After may say when to try again.
504Gateway TimeoutThe gateway waited for the application longer than its timeout. The request may still be running and may still complete.

A 502 or 504 is produced by whatever sits in front of the application, so the useful log is often there rather than in the application.

Checking a status quickly

TaskCommand
Status line and headers onlycurl -sI "$URL"
Just the codecurl -s -o /dev/null -w "%{http_code}\n" "$URL"
Follow redirects and show each hopcurl -sIL "$URL" | grep -iE "^(HTTP|location)"

Sources