Skip to content

HTTP status codes

Every HTTP status code with what it means, when to use it, and the ones that are routinely used wrongly.

Runs in your browser — nothing is sent anywhere.

Two different reasons to be here

Either you have received a code and want to know what it means, or you are writing an API and want to know which one to send. The second is the harder question, and it is the one a plain copy of the registry does not help with — so the notes here say when to use a code, not just what it is called.

The five classes

1xx informational, and you will almost never see one. 2xx it worked. 3xx look somewhere else. 4xx the request was wrong. 5xx the request was fine and the server failed.

The 4xx/5xx line is the one that matters most and is crossed most often. If you can describe what the client did wrong, it is a 4xx. If you cannot, it is a 5xx — and a 500 with a message saying "email is required" is a bug in the error handling, not a server error.

The pairs that get confused

401 and 403. 401 is named "Unauthorized" and actually means unauthenticated — you have not proved who you are, and it must come with a WWW-Authenticate header. 403 means we know exactly who you are and you still may not. Sending 401 when you mean 403 tells the client to try logging in again, which will not help.

400 and 422. 400 is for a request the server could not parse — broken JSON, a malformed header. 422 is for a request that parsed perfectly and failed a rule, which is what a form with an invalid email address is. Using 400 for validation failures throws away that distinction, and clients cannot tell "your code is broken" from "your user typed something wrong".

301 and 302. 301 is permanent and browsers cache it aggressively — often until the browser is reinstalled. Ship a wrong 301 and visitors keep going to the old address long after you fix it. 302 is temporary and safe to change, which makes it the one to reach for when you are not certain.

302 and 307. Historically a 302 allowed the client to change a POST into a GET, and most do. 307 guarantees the method is preserved. If you are redirecting a form submission and it matters that it stays a POST, use 307.

The ones worth knowing about

204 succeeded with deliberately no body, which is the right answer to a DELETE. 206 is partial content, and it is how video seeking and resumable downloads work. 409 is a conflict — a duplicate that must be unique, or an edit against a version that has moved on. 410 says it was here and is deliberately gone, which tells crawlers to stop asking in a way 404 does not. 429 is rate limiting, and without a Retry-After header clients respond by retrying harder.

418 is a joke from an April Fools' specification in 1998 that has become a permanent fixture, and several real frameworks implement it.

Codes that require a header

A few are incomplete on their own, and this is a common oversight. 401 needs WWW-Authenticate. 405 needs Allow, listing the methods that do work. 429 and 503 should both carry Retry-After. 201 should include Location pointing at what was created.

Searching

A number, part of a name, or a class like 4xx to see a whole family at once.

01

Common questions

What is the difference between 401 and 403?

401 means unauthenticated — you have not proved who you are, and it must include a WWW-Authenticate header. 403 means we know who you are and you still may not.

Should a validation error be 400 or 422?

422. Use 400 when the request could not be parsed at all. A form with an invalid email parsed fine and failed a rule, which is 422.

301 or 302?

302 unless you are certain. 301 is cached hard by browsers, sometimes until reinstall, so a mistaken one keeps sending visitors to the old address long after you fix it.

Why did my POST become a GET after a redirect?

Because a 302 historically allows it and most clients do. Use 307, which guarantees the method is preserved.

When is a 500 wrong?

Whenever you can describe what the client did wrong. A 500 whose message says "email is required" should be a 422 — the request was not the server\u2019s fault.

Which codes need an extra header?

401 needs WWW-Authenticate, 405 needs Allow, 429 and 503 should send Retry-After, and 201 should send Location. Without them the response is incomplete.