HTTP Status Codes Explained: The Five Classes and a Practical List
Every HTTP response starts with a three-digit number: the status code. In one line it says whether the request worked, whether the client should go elsewhere, whether the client made a mistake or whether the server failed. Browsers, search engines, proxies, caches and API clients all make decisions from that number alone, so choosing the right code is part of an API's contract, not a detail.
Where the status code appears
It is the first thing the server sends, on the status line, before the headers and the body:
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/orders/1042
{"id": 1042, "status": "pending"}
The text after the number (Created, Not Found) is only a hint. HTTP/2 and HTTP/3 do not send it at all, and clients must decide by the number. Changing the text therefore changes nothing: a 200 Error is still a success to every program that reads it.
To check a status code in the browser, open developer tools (F12) and look at the Status column in the Network tab. On the command line, curl -I https://example.com shows the status line and headers, and curl -s -o /dev/null -w '%{http_code}' URL prints just the number, which is handy in scripts and uptime checks.
The five classes
The first digit defines the class, and it is what a client must understand even when it does not know the specific code. RFC 9110 says an unrecognised code is treated as the x00 code of its class: an unknown 299 behaves like 200, and an unknown 499 like 400.
1xx Informational request still in progress 100 Continue, 101 Switching Protocols, 103 Early Hints
2xx Success the request worked 200, 201, 202, 204, 206
3xx Redirection another action or URL is needed 301, 302, 303, 304, 307, 308
4xx Client error the request is wrong 400, 401, 403, 404, 409, 422, 429
5xx Server error the server failed 500, 502, 503, 504
2xx: success
200 OK is the standard response with content. 201 Created says a resource was created, and should carry a Location header pointing to it. 202 Accepted means the request was accepted for later processing, for example by a queue, and the client must check the result later.
204 No Content is success without a body, typical after a DELETE or a PUT that returns nothing. A client that parses every response as JSON throws on a 204, so check before parsing. 206 Partial Content answers requests with a Range header, and powers resumable downloads and video seeking.
3xx: redirects and caching
301 Moved Permanently and 308 Permanent Redirect say the resource moved for good, and search engines transfer ranking to the new URL. 302 Found and 307 Temporary Redirect are temporary. The difference within each pair is the method: browsers turn a POST into a GET when following 301 and 302, while 307 and 308 keep the method and body. 303 See Other is used after a form submission to send the browser to a result page with GET.
304 Not Modified is not a real redirect. It answers a conditional request (If-None-Match with an ETag, or If-Modified-Since) and says the cached copy is still valid. It has no body and saves transferring the resource again. Monitoring that counts every non-200 as a failure misreports it.
4xx: client errors
400 Bad Request: the request is malformed, such as invalid JSON or unreadable parameters. 401 Unauthorized: authentication is missing or invalid. 403 Forbidden: authenticated, but not allowed. 404 Not Found: nothing exists at this URL. 405 Method Not Allowed: the path exists but does not accept this method, and the response must include an Allow header listing the methods that work.
409 Conflict: the request clashes with the current state, such as a username already taken or an edit based on an outdated version. 410 Gone: the resource was removed permanently. 415 Unsupported Media Type: the body's Content-Type is not accepted. 422 Unprocessable Content: the request is syntactically fine but the data is invalid. 429 Too Many Requests: a rate limit was exceeded, usually with a Retry-After header.
What they share: repeating the same request unchanged will fail again. Something on the client side must change: the URL, the credentials or the data.
5xx: server errors
500 Internal Server Error: an unhandled failure in the application. 502 Bad Gateway: a proxy received an invalid response from the application, which has often crashed. 503 Service Unavailable: the service is overloaded or in maintenance, temporarily. 504 Gateway Timeout: the application did not answer the proxy in time.
Here the same request may succeed later, so well-behaved clients retry 502, 503 and 504 with exponential backoff. They should only do so for idempotent operations such as GET, PUT and DELETE, or with idempotency keys, so that a retry does not create a second order.
Choosing the right code in an API
The most damaging design mistake is returning 200 with an error in the body, such as {"ok": false, "error": "not found"}. Caches, monitoring, automatic retries and client libraries all see a success. Use the matching status code and put the details in the body, ideally in the standard application/problem+json format from RFC 9457.
HTTP/1.1 404 Not Found
Content-Type: application/problem+json
{
"type": "https://api.example.com/errors/order-not-found",
"title": "Order not found",
"status": 404,
"detail": "Order 1042 does not exist in this account."
}
Other rules that hold up: 201 with Location on creation, 204 when there is nothing to return, 401 versus 403 depending on whether credentials or permissions are missing, and never 500 for expected situations such as failed validation. A small set of codes used consistently is worth more than the full list used at random.
Sources and further reading
RFC 9110 (HTTP Semantics), section 15, defines the status codes and classes. RFC 6585 adds 429, RFC 8297 defines 103 Early Hints, and RFC 9457 defines application/problem+json. The IANA HTTP Status Code Registry lists every registered code, and MDN has a reference page with examples for each one.
Frequently asked questions
What are HTTP status codes?
Three-digit numbers the server sends at the start of every response to report the outcome: success (2xx), redirection (3xx), client error (4xx) or server error (5xx). Clients act on the number, not on the text after it.
What does HTTP status code 201 mean?
`201 Created`: the request created a new resource. The response should include a `Location` header with the new resource's URL, and often its representation in the body.
What does a 400 status code mean?
`400 Bad Request`: the server could not process the request because it is malformed, for example invalid JSON or unreadable parameters. Fix the request on the client before retrying.
What is the difference between 4xx and 5xx errors?
4xx means the client's request is wrong and will fail again unchanged. 5xx means the server failed, and the same request may succeed later.
How do I check the status code of a URL?
In the browser, use the Status column in the developer tools' Network tab. On the command line, run `curl -I URL`, or `curl -s -o /dev/null -w '%{http_code}' URL` to print only the number.
Is it OK to return 200 with an error message?
No. Caches, monitoring and clients treat 200 as success. Return the matching error code and put the details in the body, ideally as `application/problem+json`.