Master all 5xx, 4xx, 3xx, 2xx, and 1xx HTTP status codes with real-world examples and when to use each in your API design.
HTTP status codes are three-digit numbers that tell clients what happened to their request. They are grouped into five classes by their first digit:
| Class | Range | Meaning |
|---|---|---|
| 1xx | 100–199 | Informational — request received, process continuing |
| 2xx | 200–299 | Success — request was understood and accepted |
| 3xx | 300–399 | Redirection — further action must be taken |
| 4xx | 400–499 | Client Error — request contains bad syntax or cannot be fulfilled |
| 5xx | 500–599 | Server Error — server failed to fulfill a valid request |
The request succeeded. The most common status code. Use it for successful GET and POST (non-creating) responses.
A new resource was created as a result of the request. Always include a Location header pointing to the new resource:
HTTP/1.1 201 Created
Location: /users/123
Content-Type: application/json
{"id": 123, "name": "Alice"}
The request succeeded but there is no content to return. Use for DELETE and PUT operations where you don't need to return data:
DELETE /users/123 HTTP/1.1
HTTP/1.1 204 No Content
Used for range requests (video streaming, file downloads with resume support).
The resource has permanently moved to a new URL. Browsers and search engines will update their caches. Use when you rename URLs permanently.
Temporary redirect. The method may change from POST to GET. Use for login redirects.
Like 302, but guarantees the method won't change. Use when you need to redirect a POST request temporarily.
Like 301, but the method is preserved. Use when permanently redirecting POST endpoints.
The cached version is still valid. Used with ETag and If-None-Match or Last-Modified and If-Modified-Since headers for efficient caching.
The request is malformed. Include error details in the response body:
{
"error": "VALIDATION_ERROR",
"message": "Invalid email format",
"field": "email"
}
Authentication is required and has failed or not been provided. Despite the name, this is about authentication, not authorization. Include a WWW-Authenticate header.
The client is authenticated but not authorized to perform this action. The user exists and is identified, but lacks permission.
401 → "Who are you?"
403 → "I know who you are, but you can't do that."
The resource doesn't exist. Also use when you want to hide the existence of a resource from unauthorized users (instead of 403).
The request conflicts with the current state. Common for duplicate creation attempts:
{"error": "EMAIL_ALREADY_EXISTS"}
The request is well-formed but has semantic errors. Preferred over 400 for validation failures in REST APIs.
Rate limiting. Always include Retry-After and X-RateLimit-* headers:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1706745600
Something went wrong on the server. Log the actual error internally but never expose it to the client.
The gateway or proxy received an invalid response from an upstream service. Common when a microservice goes down.
The server is temporarily unable to handle requests (overload or maintenance). Include Retry-After.
The upstream service didn't respond in time. Different from 503 — the downstream service is up but the upstream isn't responding.
For sensitive resources (admin panels, private data), returning 404 instead of 403 prevents information disclosure. Attackers don't know whether the resource exists or whether they just lack permission.
GraphQL APIs typically return 200 even for errors, with error details in the response body. This is by design — the HTTP layer is the transport, not the business logic layer.
Browse all HTTP status codes with descriptions in HeoLab's HTTP Status Codes reference. Search by code number, name, or description.
Choosing the right status code communicates intent to clients and keeps your API predictable. The key rules: 2xx for success with appropriate granularity (200 vs 201 vs 204), 4xx for client mistakes with helpful error messages, and 5xx for server-side failures that you log and fix.