HTTP status codes are three-digit numbers that servers send in response to client requests. They communicate the outcome of the request: whether it succeeded, failed, requires further action, or encountered an error. Status codes are a fundamental part of the HTTP protocol and essential for building reliable web applications and APIs.
Every HTTP response includes a status code in the response header, along with a human-readable reason phrase. For example:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1234
{"status": "success", "data": {...}}
The status code 200 tells the client the request was successful. The reason phrase "OK" is a human-readable description, but clients should rely on the numeric code for decision-making.
Status codes are grouped into five categories based on their first digit:
| Range | Category | Meaning |
|---|---|---|
| 1xx | Informational | Request received, continuing process |
| 2xx | Success | Request successfully received and accepted |
| 3xx | Redirection | Further action needed to complete request |
| 4xx | Client Error | Request contains errors or cannot be fulfilled |
| 5xx | Server Error | Server failed to fulfill a valid request |
1xx status codes indicate that the request has been received and the server is continuing to process it. These are provisional responses and are rarely seen in typical web applications. They are used primarily for protocol-level communication.
The client should continue with the request. This is used when the client sends an Expect: 100-continue header to check if the server will accept the request body before sending it.
// Client sends initial request with Expect header
POST /upload HTTP/1.1
Host: example.com
Expect: 100-continue
Content-Length: 1048576
// Server responds to indicate it's ready
HTTP/1.1 100 Continue
// Client then sends the request body
This is useful for large file uploads to avoid sending gigabytes of data if the server will reject the request anyway.
The server is switching to a different protocol as requested by the client via the Upgrade header. Most commonly used when upgrading HTTP to WebSocket:
// Client requests WebSocket upgrade
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
// Server accepts and switches protocols
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Used to send preliminary response headers while the server prepares the full response. Browsers can use this to preload resources:
HTTP/1.1 103 Early Hints
Link: </style.css>; rel=preload; as=style
Link: </script.js>; rel=preload; as=script
HTTP/1.1 200 OK
Content-Type: text/html
...
2xx status codes indicate that the request was successfully received, understood, and accepted. These are the responses you want to see in your applications.
The request succeeded. The most common success status code. The response body contains the requested resource or the result of the action.
GET /api/users/123
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 123, "name": "John Doe", "email": "[email protected]"}
A new resource was successfully created. The Location header should contain the URI of the newly created resource:
POST /api/users
HTTP/1.1 201 Created
Location: /api/users/456
Content-Type: application/json
{"id": 456, "name": "Jane Smith", "email": "[email protected]"}
The request has been accepted for processing, but processing is not complete. Used for asynchronous operations:
POST /api/jobs/process-video
HTTP/1.1 202 Accepted
Content-Type: application/json
{"jobId": "abc123", "status": "processing", "estimatedTime": "5 minutes"}
The request succeeded, but there is no content to return. Common for DELETE operations or updates that don't return data:
DELETE /api/users/123
HTTP/1.1 204 No Content
Used for range requests. The server is delivering only part of the resource due to a Range header:
GET /video.mp4
Range: bytes=0-1023
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/5242880
Content-Length: 1024
3xx status codes indicate that the client must take additional action to complete the request, typically following a redirect to a different URI.
The resource has permanently moved to a new URI. Search engines update their indexes, and browsers cache the redirect:
GET /old-page
HTTP/1.1 301 Moved Permanently
Location: https://example.com/new-page
Use 301 for permanent URL changes, site migrations, and HTTPS redirects.
The resource is temporarily located at a different URI. The original URI should be used for future requests:
GET /login-required-page
HTTP/1.1 302 Found
Location: /login?redirect=/login-required-page
The response to the request can be found at another URI using GET. Used after POST requests to prevent duplicate form submissions:
POST /api/create-order
HTTP/1.1 303 See Other
Location: /orders/789
The resource has not been modified since the version specified by If-Modified-Since or If-None-Match headers. Used for caching:
GET /api/data
If-None-Match: "abc123"
HTTP/1.1 304 Not Modified
ETag: "abc123"
Similar to 302, but guarantees the request method won't change. If the original request was POST, the redirected request will also be POST:
POST /api/submit
HTTP/1.1 307 Temporary Redirect
Location: /api/submit-v2
Similar to 301, but guarantees the request method won't change. The permanent equivalent of 307:
POST /api/old-endpoint
HTTP/1.1 308 Permanent Redirect
Location: /api/new-endpoint
4xx status codes indicate that the client sent an invalid request or lacks authorization. These errors are the client's responsibility to fix.
The server cannot process the request due to client error (malformed syntax, invalid parameters, etc.):
POST /api/users
{"name": "John"} // Missing required field "email"
HTTP/1.1 400 Bad Request
Content-Type: application/json
{"error": "Validation failed", "details": {"email": "Email is required"}}
Authentication is required and has failed or has not been provided. The client should authenticate and retry:
GET /api/protected-resource
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="API"
Content-Type: application/json
{"error": "Authentication required", "message": "Please provide a valid access token"}
The client is authenticated but does not have permission to access the resource:
DELETE /api/admin/users/123
HTTP/1.1 403 Forbidden
Content-Type: application/json
{"error": "Insufficient permissions", "message": "Admin role required"}
The requested resource does not exist. The most common error code:
GET /api/users/99999
HTTP/1.1 404 Not Found
Content-Type: application/json
{"error": "User not found", "userId": 99999}
The request method is not supported for the requested resource. The Allow header lists valid methods:
PUT /api/read-only-resource
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD
Content-Type: application/json
{"error": "Method not allowed", "allowedMethods": ["GET", "HEAD"]}
The request conflicts with the current state of the server. Common for concurrent modifications:
PUT /api/users/123
{"version": 5, "name": "Updated Name"}
HTTP/1.1 409 Conflict
Content-Type: application/json
{"error": "Conflict", "message": "Resource has been modified (current version: 7)"}
The resource is permanently gone and will not be available again. Unlike 404, which suggests the resource might return:
GET /api/deprecated-endpoint
HTTP/1.1 410 Gone
Content-Type: application/json
{"error": "Endpoint removed", "message": "This endpoint was deprecated on 2025-01-01"}
The request body is larger than the server is willing to process:
POST /api/upload
Content-Length: 104857600 // 100 MB
HTTP/1.1 413 Payload Too Large
Content-Type: application/json
{"error": "File too large", "maxSize": "10 MB"}
The request payload format is not supported by the server:
POST /api/users
Content-Type: text/xml
HTTP/1.1 415 Unsupported Media Type
Content-Type: application/json
{"error": "Unsupported media type", "supportedTypes": ["application/json"]}
The request is well-formed but contains semantic errors. Common for validation failures:
POST /api/users
{"email": "invalid-email", "age": -5}
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"error": "Validation failed",
"details": {
"email": "Invalid email format",
"age": "Age must be positive"
}
}
The client has sent too many requests in a given time (rate limiting):
GET /api/data
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1678886400
{"error": "Rate limit exceeded", "retryAfter": "1 hour"}
5xx status codes indicate that the server encountered an error while processing a valid request. These errors are the server's responsibility to fix.
A generic error indicating the server encountered an unexpected condition:
GET /api/users
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{"error": "Internal server error", "requestId": "abc-123-def-456"}
Never expose detailed error information (stack traces, database errors) to clients in production. Log these server-side and return generic error messages.
The server does not support the functionality required to fulfill the request:
TRACE /api/users
HTTP/1.1 501 Not Implemented
Content-Type: application/json
{"error": "Not implemented", "message": "TRACE method not supported"}
The server, acting as a gateway or proxy, received an invalid response from an upstream server:
GET /api/external-service
HTTP/1.1 502 Bad Gateway
Content-Type: application/json
{"error": "Bad gateway", "message": "Upstream service unavailable"}
The server is temporarily unable to handle the request, usually due to maintenance or overload:
GET /api/users
HTTP/1.1 503 Service Unavailable
Retry-After: 300
Content-Type: application/json
{"error": "Service unavailable", "message": "Scheduled maintenance", "retryAfter": 300}
The server, acting as a gateway, did not receive a timely response from an upstream server:
GET /api/slow-service
HTTP/1.1 504 Gateway Timeout
Content-Type: application/json
{"error": "Gateway timeout", "message": "Upstream service timed out after 30 seconds"}
Choosing the right status codes is essential for building intuitive, well-designed REST APIs.
| Operation | Method | Success Code | Response Body |
|---|---|---|---|
| Create | POST | 201 Created | Created resource + Location header |
| Read (single) | GET | 200 OK | Resource representation |
| Read (list) | GET | 200 OK | Array of resources + pagination |
| Update (full) | PUT | 200 OK or 204 | Updated resource or empty |
| Update (partial) | PATCH | 200 OK or 204 | Updated resource or empty |
| Delete | DELETE | 204 No Content | Empty (or 200 with details) |
Use a consistent error response structure across your API:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "email",
"message": "Invalid email format"
},
{
"field": "age",
"message": "Age must be between 0 and 120"
}
],
"requestId": "abc-123",
"timestamp": "2026-03-12T14:30:00Z"
}
}
Ensure idempotent operations (GET, PUT, DELETE) return consistent status codes:
// First DELETE request
DELETE /api/users/123
HTTP/1.1 204 No Content
// Second DELETE request (resource already deleted)
DELETE /api/users/123
HTTP/1.1 404 Not Found // or 410 Gone for stricter semantics
Effective debugging requires understanding status codes, inspecting headers, and using the right tools.
Use the Network tab to inspect HTTP traffic:
# Verbose output with headers
curl -v https://api.example.com/users
# Include response headers in output
curl -i https://api.example.com/users
# Follow redirects
curl -L https://example.com/redirect
# Custom headers
curl -H "Authorization: Bearer token123" https://api.example.com/protected
| Symptom | Likely Cause | Solution |
|---|---|---|
| CORS errors in browser | Missing CORS headers | Configure Access-Control-* headers on server |
| 401 on authenticated requests | Expired or invalid token | Refresh authentication token |
| 429 rate limit errors | Too many requests | Implement exponential backoff |
| 502/503/504 errors | Backend service issues | Check upstream service health |
| Redirect loops | Circular redirects | Fix redirect configuration |
Follow these guidelines when working with HTTP status codes.
Don't return generic codes when more specific ones exist. Use 422 instead of 400 for validation errors, 429 instead of 403 for rate limiting, etc.
Status codes alone aren't enough. Include descriptive error messages and details in the response body.
Document which status codes your API returns for each endpoint and what they mean in your context.
Use the same status codes for the same scenarios across your entire API.
5xx errors indicate server problems. Log them, monitor them, and fix the underlying issues.
Write tests for error scenarios, not just happy paths. Verify correct status codes for validation failures, authentication errors, etc.
Our free HTTP Status Codes Reference tool provides a comprehensive, searchable database of all HTTP status codes with detailed descriptions, use cases, and examples.
Search by status code number (e.g., "404") or category (e.g., "client error") to instantly find the status code you need. Perfect for quick reference during development.
Each status code includes:
Browse status codes by category (1xx, 2xx, 3xx, 4xx, 5xx) to understand the full range of responses in each group.
Copy ready-to-use HTTP response examples to your clipboard for quick integration into documentation or code.
Access our comprehensive HTTP status codes reference with detailed descriptions, examples, and best practices. Perfect for API development and debugging.
View HTTP Status Codes ReferenceMaster JSON syntax, formatting best practices, validation techniques, and common parsing errors.
Learn how JWT authentication works, token structure, claims, and security best practices.
Master Base64 encoding and decoding with algorithm details, use cases, code examples, and security best practices.