A definitive reference to HTTP status codes. Every response from an HTTP server includes a three-digit status code that tells the client what happened. The first digit defines the category: 1xx for informational, 2xx for success, 3xx for redirection, 4xx for client errors, and 5xx for server errors. This guide covers every commonly used code with practical guidance on when to use each one.
How HTTP Status Codes Work
When a client (browser, API consumer, or any HTTP agent) sends a request to a server, the server responds with a status line containing the HTTP version, a numeric status code, and a reason phrase. The status code is the machine-readable part; the reason phrase is human-readable and optional in HTTP/2+. Clients use the status code to decide what to do next: render content, follow a redirect, retry, or display an error.
HTTP/1.1 200 OKThe status code (200) is what matters programmatically. The reason phrase (OK) is for humans reading raw responses.
1xx Informational
Provisional responses indicating the server has received the request and the client should continue or wait.
| Code | Name | Description | When to Use |
|---|---|---|---|
| 100 | Continue | The server has received the request headers and the client should send the body. | Client sends Expect: 100-continue header before a large upload; server confirms it is ready to accept the body. |
| 101 | Switching Protocols | The server is switching to the protocol requested via the Upgrade header. | Upgrading an HTTP connection to WebSocket (Upgrade: websocket). |
| 103 | Early Hints | The server sends preliminary headers before the final response. | Sending Link headers to let the browser preload CSS or fonts while the server is still generating the full response. |
2xx Success
The request was received, understood, and accepted.
| Code | Name | Description | When to Use |
|---|---|---|---|
| 200 | OK | The standard success response. The body contains the requested resource or result. | GET returning a resource, POST that processes data and returns a result, PUT/PATCH that returns the updated resource. |
| 201 | Created | A new resource has been created. | POST /users creates a new user. Return with a Location header pointing to the new resource. |
| 202 | Accepted | The request has been accepted for processing but is not yet complete. | Queuing a long-running job (video encoding, report generation). The client can poll for status later. |
| 204 | No Content | The request succeeded but there is no body to return. | DELETE that removes a resource, or PUT/PATCH when the client does not need the updated representation back. |
| 206 | Partial Content | The server is delivering only part of the resource due to a Range header. | Resumable downloads, video streaming, or any scenario where the client requests byte ranges. |
3xx Redirection
The client must take additional action to complete the request, typically following a Location header.
| Code | Name | Description | When to Use |
|---|---|---|---|
| 301 | Moved Permanently | The resource has been permanently moved to a new URL. Search engines transfer ranking. | Domain migration, permanent URL restructuring. Browsers and crawlers cache this redirect. |
| 302 | Found | Temporary redirect. The resource is temporarily at a different URL. | Redirecting after login to a dashboard, A/B testing with different URLs. Historically ambiguous; prefer 307 for strict method preservation. |
| 303 | See Other | Redirect to a different resource using GET, regardless of the original method. | After a POST form submission, redirect to a confirmation page (POST-Redirect-GET pattern). |
| 304 | Not Modified | The resource has not changed since the version specified by the request headers (If-None-Match, If-Modified-Since). | Cache validation. The server tells the client to use its cached copy, saving bandwidth. |
| 307 | Temporary Redirect | Same as 302 but guarantees the HTTP method and body are not changed. | Temporarily routing traffic to a different server. The client must reuse the same method (POST stays POST). |
| 308 | Permanent Redirect | Same as 301 but guarantees the HTTP method and body are not changed. | Permanent URL change for an API endpoint where clients POST data. The client must reuse the same method. |
4xx Client Errors
The request contains bad syntax or cannot be fulfilled. The client should not retry without modification.
| Code | Name | Description | When to Use |
|---|---|---|---|
| 400 | Bad Request | The server cannot process the request due to malformed syntax or invalid parameters. | Missing required fields, invalid JSON body, query parameter type mismatch. |
| 401 | Unauthorized | Authentication is required and has either failed or not been provided. | No token provided, expired JWT, invalid API key. The client should authenticate and retry. |
| 403 | Forbidden | The server understood the request but refuses to authorize it. | Authenticated user lacks permission. Unlike 401, re-authenticating will not help. |
| 404 | Not Found | The requested resource does not exist. | GET /users/999 when user 999 does not exist. Also used to hide the existence of resources from unauthorized users. |
| 405 | Method Not Allowed | The HTTP method is not supported for this resource. | Client sends DELETE to an endpoint that only supports GET and POST. Include an Allow header listing valid methods. |
| 406 | Not Acceptable | The server cannot produce a response matching the Accept headers. | Client requests Accept: application/xml but the API only serves JSON. |
| 408 | Request Timeout | The server timed out waiting for the request from the client. | The client took too long to send the full request body. Not the same as a server-side processing timeout. |
| 409 | Conflict | The request conflicts with the current state of the resource. | Duplicate username on registration, optimistic concurrency conflict (version mismatch on update). |
| 410 | Gone | The resource existed but has been permanently removed. | Deprecated API version, deleted content that should not return 404. Tells crawlers to remove the URL from indexes. |
| 413 | Content Too Large | The request body exceeds the server's size limit. | File upload exceeds the maximum allowed size. Include a Retry-After header if the condition is temporary. |
| 415 | Unsupported Media Type | The request Content-Type is not supported by the endpoint. | Client sends text/plain to an endpoint that only accepts application/json. |
| 422 | Unprocessable Content | The request is well-formed but contains semantic errors. | JSON is valid but email field fails validation, date range is inverted, or business rule is violated. Preferred over 400 for validation errors in REST APIs. |
| 429 | Too Many Requests | The client has sent too many requests in a given time window. | Rate limiting. Include Retry-After header to tell the client when to try again. |
| 451 | Unavailable For Legal Reasons | The resource is unavailable due to legal demands (censorship, court order). | Content blocked due to GDPR, DMCA, or government-mandated restrictions. |
5xx Server Errors
The server failed to fulfill a valid request. These indicate bugs, outages, or infrastructure problems.
| Code | Name | Description | When to Use |
|---|---|---|---|
| 500 | Internal Server Error | A generic catch-all for unexpected server failures. | Unhandled exception, null pointer, database query failure. Log the details server-side; never expose internals to the client. |
| 501 | Not Implemented | The server does not recognize or support the request method. | A method like PATCH is not implemented for this resource. Different from 405: the method is not supported anywhere on the server. |
| 502 | Bad Gateway | The server acting as a gateway received an invalid response from an upstream server. | Reverse proxy (Nginx, load balancer) cannot reach or gets garbage from the application server. |
| 503 | Service Unavailable | The server is temporarily unable to handle the request. | Planned maintenance, server overload, or dependency outage. Include Retry-After header with an estimated recovery time. |
| 504 | Gateway Timeout | The server acting as a gateway did not receive a timely response from an upstream server. | Reverse proxy timed out waiting for the application server. Often caused by slow database queries or external API calls. |
Quick Decision Guide
Common scenarios and which status code to return.
| Scenario | Status Code |
|---|---|
| Request succeeded, returning data | 200 OK |
| Resource created successfully | 201 Created |
| Request accepted, processing asynchronously | 202 Accepted |
| Request succeeded, nothing to return | 204 No Content |
| Resource moved to a new permanent URL | 301 Moved Permanently |
| Redirect after form submission (POST-Redirect-GET) | 303 See Other |
| Resource has not changed (cache validation) | 304 Not Modified |
| Temporary redirect preserving the HTTP method | 307 Temporary Redirect |
| Malformed request syntax or invalid parameters | 400 Bad Request |
| Missing or invalid authentication credentials | 401 Unauthorized |
| Authenticated but lacking permission | 403 Forbidden |
| Resource does not exist | 404 Not Found |
| Duplicate entry or version conflict | 409 Conflict |
| Valid syntax but fails business validation | 422 Unprocessable Content |
| Client is being rate limited | 429 Too Many Requests |
| Unexpected server failure | 500 Internal Server Error |
| Upstream server is unreachable or returned garbage | 502 Bad Gateway |
| Server is down for maintenance or overloaded | 503 Service Unavailable |
| Upstream server took too long to respond | 504 Gateway Timeout |
Common Mistakes
Never return 200 with an error message in the body. Use the correct 4xx/5xx code so clients, proxies, and monitoring tools can detect failures automatically.
401 means "who are you?" (authentication). 403 means "I know who you are, but you cannot do this" (authorization). If re-authenticating could help, use 401.
Distinguish between malformed requests (400), validation errors (422), conflicts (409), and missing resources (404). Specific codes help clients handle errors programmatically.
302 historically allowed clients to change POST to GET on redirect. If you need to preserve the method, use 307 (temporary) or 308 (permanent).
If the client sent bad data, that is a 4xx. Reserve 500 for genuine server-side bugs. Misusing 500 makes it impossible to distinguish between client errors and server outages.
Test HTTP status codes and inspect response headers with the curl Cheat Sheet or explore more developer references in our cheatsheet collection.