HTTP Status Codes, Explained

After reading this you will be able to read any HTTP status code, know which of the five classes it belongs to, predict what a well-behaved client should do about it, and avoid the handful of mistakes that break caches, redirects and error handling.

Every HTTP response starts with a status line. A server that answers a request for a page sends something like HTTP/1.1 200 OK. The three-digit number is the status code, and the words after it are the reason phrase. The number is what machines act on. The reason phrase is only for humans, and RFC 9110 says clients should ignore it (Section 15).

Here is the hook. A browser asks for /report, the server answers 301 Moved Permanently with a Location: /reports/2024 header. The browser does not show an error. It quietly fetches the new URL, and next time it may skip the old address entirely because 301 means the move is permanent and cacheable. Change that one digit to 302 and the browser stops caching the redirect. That single digit is the difference between a URL that disappears from history and one that keeps working. This is why the codes are worth learning precisely.

The five classes and what they promise

Every status code is a three-digit number from 100 to 599. The first digit sets the class, and the class alone tells you how to react even if you have never seen the specific code.

1xx informational
The request was received and processing continues. The response is provisional. Example: 100 Continue.
2xx success
The request was received, understood and accepted. Example: 200 OK, 201 Created, 204 No Content.
3xx redirection
Further action is needed to complete the request, usually following a Location header. Example: 301, 302, 304 Not Modified.
4xx client error
The request was malformed or not allowed. The client should not repeat it unchanged. Example: 400, 401, 404.
5xx server error
The server failed to fulfil an apparently valid request. Retrying later may work. Example: 500, 502, 503.

RFC 9110 Section 15 states the key rule: a client that does not recognize a status code must treat it as the x00 code of its class. So an unknown 499 is handled like 400, and an unknown 522 is handled like 500. This is why the first digit matters more than the exact number.

Only these five classes exist. There is no 6xx class in HTTP. Codes like Cloudflare's 520 through 530 are non-standard extensions that still fall inside the 5xx server-error class, so clients treat them like 500.

Codes are registered, not invented

You do not get to make up a code and expect it to work. The Internet Assigned Numbers Authority (IANA) keeps the official HTTP Status Code Registry. As of the 2022 update, roughly 60 codes are registered across the five classes. That is far fewer than the 500 slots the numbering scheme allows, which leaves room for future additions.

The counts per class in the registry look roughly like this. Use them to see where the real detail lives: the 2xx, 4xx and 5xx classes carry most of the working codes.

The 4xx client-error class is the largest, with around 28 registered codes, because there are many distinct ways for a request to be wrong.

When the code matters and when it does not

The status code is authoritative for machines. Caches key on it, browsers redirect on it, and API clients branch on it. So set it correctly on the server and read it correctly on the client.

What does not matter is the reason phrase. You can send 200 Totally Fine or 404 Nope and a compliant client behaves identically to 200 OK and 404 Not Found. HTTP/2 and HTTP/3 drop the reason phrase from the wire entirely (RFC 9113 Section 8.3.1), so any code that carries meaning in its text is already broken on modern connections.

Do not return 200 OK with an error message in the body. This is the most common API bug. A client that sees 200 treats the response as success, caches it, and never triggers its error path. If the request failed, send a 4xx or 5xx code so the machine agrees with the human.

Reading a code in three steps

You can decode any status code, including ones you have never met, with a fixed procedure. There is no formula to compute here, only a decision you repeat.

  1. Read the first digit to get the class. That tells you success, redirect, or which side of the wire made the mistake.
  2. If you recognize the exact code, use its specific meaning. If you do not, fall back to the x00 behavior for the class, exactly as RFC 9110 requires.
  3. Check the headers the code depends on. A 3xx needs Location. A 401 needs WWW-Authenticate. A 405 needs Allow. A 503 may carry Retry-After.

Worked example: the classic teapot and its neighbors

Load the tool with its defaults and search the reference. Work through four codes the same way each time.

  1. 418 I'm a teapot: first digit 4, so client error. Defined by RFC 2324 as an April Fools joke, it means the server refuses to brew coffee because it is a teapot. Some real servers send it to reject bots. A client should treat it like 400 and not retry unchanged.
  2. 301 Moved Permanently: first digit 3, redirection. Follow the Location header. Cache the redirect and update stored links, because the move is permanent.
  3. 429 Too Many Requests: first digit 4, client error. You sent too many requests in a window. Read Retry-After and wait that many seconds before trying again.
  4. 511 Network Authentication Required: first digit 5, server error. A captive portal wants you to log in before it grants network access. Defined in RFC 6585.

Notice that 418 and 429 share the leading 4, so the fallback behavior is the same even though their meanings differ. That shared class is the safety net.

The nine codes you will actually meet

A handful of codes cover the vast majority of real traffic. Learn these nine and you can read most logs on sight.

The common codes, their class, and the client's next move
CodeMeaningClassWhat the client does
200OK2xxUse the body as the result
201Created2xxRead the new resource from Location
301Moved Permanently3xxFollow and cache the redirect
304Not Modified3xxReuse the cached copy
400Bad Request4xxFix the request, do not retry as is
401Unauthorized4xxAuthenticate, then retry
404Not Found4xxStop; the resource is absent
500Internal Server Error5xxRetry with backoff, then report
503Service Unavailable5xxWait for Retry-After, then retry

Pick any code from 100 to 599 and the reference tells you its class from the first digit, its registered meaning if one exists, and the fallback behavior a client uses when the code is unknown. For example, code 407 is class 4xx (client error) with meaning "Proxy Authentication Required", and an unknown 4xx falls back to 400 handling.

Common mistakes that break real systems

These are the errors that cost hours of debugging.

  • Using 302 for a permanent move. Search engines and browsers may not update their stored links, so the old URL never retires. Use 301 for permanent, 302 or 307 for temporary.
  • Changing the method on redirect. Old clients turned a POST into a GET after a 302. If you need the method preserved, use 307 Temporary Redirect or 308 Permanent Redirect, which RFC 9110 defines to keep the method and body intact.
  • Returning 200 on failure. Covered above. The machine believes you.
  • Confusing 401 and 403. 401 means "you are not authenticated, log in." 403 means "you are authenticated but not allowed." Sending 401 without a WWW-Authenticate header violates RFC 9110 Section 15.5.2.
  • Sending a body with 204 or 304. Both codes forbid a message body. A body here confuses parsers and can desync the connection.

Related tools

Status codes rarely travel alone. When you inspect a response you often need to decode the surrounding parts too.

Use the URL Parser & Query Editor to split the Location header of a redirect into its parts, the MIME Type Lookup to check that the Content-Type matches the body you got with a 200, and the User-Agent Parser when a server returns 403 or 418 based on the client that asked. For front-end work on the pages behind those responses, the Color Converter & Contrast Checker, the CSS Gradient, Shadow & Radius Generator, the HTML Entity Reference and the Keycode Inspector cover the rest.

Frequently asked questions

What is the difference between 401 and 403?

401 Unauthorized means the request lacks valid authentication, so logging in may fix it, and the response must include a WWW-Authenticate header. 403 Forbidden means the server understood who you are and still refuses; logging in again will not help.

Is 418 I'm a teapot a real status code?

Yes. It is defined by RFC 2324, the Hyper Text Coffee Pot Control Protocol, as an April Fools joke in 1998. It is in the IANA registry, and some servers send it to reject automated traffic. Clients treat it like any other 4xx: a client error, do not retry unchanged.

Which redirect code should I use?

For a permanent move use 301. For a temporary one use 302. If the request method and body must survive the redirect, use 307 (temporary) or 308 (permanent), which are guaranteed not to change the method.

Should I retry a request after a 500 or a 503?

A 503 Service Unavailable often carries a Retry-After header telling you how long to wait, so retry after that delay. A 500 Internal Server Error gives no such promise; retry once or twice with exponential backoff, then report the failure. Never retry a 4xx unchanged, because the fault is on your side.

Does the reason phrase text matter?

No. Clients act on the three-digit number only, and HTTP/2 and HTTP/3 do not send the reason phrase at all. Treat the text as a comment for humans.