Guide
HTTP Status Codes: A Complete Reference Guide
Learn how HTTP status code classes (1xx-5xx) work and when to use each code. Master informational, success, redirect, client error, and server error responses.
TL;DR: Status codes indicate request outcomes: 2xx success, 3xx redirect, 4xx client error, 5xx server error. Choose the right code to help browsers, users, and developers understand what happened.
HTTP status codes are three-digit numbers that servers send to communicate the outcome of client requests. They’re the primary mechanism for indicating success, failure, or the need for additional action. Understanding status codes is essential for building robust web applications, debugging issues, and creating intuitive user experiences.
This guide provides a comprehensive overview of all five status code classes, practical decision-making frameworks, and real-world implementation patterns that will help you choose the right status code for every situation.
Introduction
Every HTTP response includes a status code that tells the client exactly what happened with their request. These codes are standardized across the web, ensuring consistent behavior between different servers, browsers, and applications. The three-digit format isn’t arbitrary—it creates a hierarchical system where the first digit indicates the general category of response.
Status codes serve multiple audiences: they help browsers decide how to handle responses, inform developers about API behavior, guide user interface decisions, and enable automated systems to react appropriately to different outcomes. Choosing the correct status code isn’t just about technical accuracy—it directly impacts user experience, SEO performance, and system reliability.
The five classes (1xx through 5xx) each serve distinct purposes in the HTTP communication protocol. Understanding when and how to use each class enables you to build more predictable, debuggable, and user-friendly applications.
The Five Status Code Classes
1xx Informational Responses
Informational status codes indicate that the request has been received and the server is continuing to process it. These are interim responses that don’t complete the request-response cycle.
Key Characteristics:
- Provisional responses during request processing
- Client should wait for final response
- Rarely used in typical web applications
- More common in streaming and long-running operations
Common 1xx Codes:
100 Continue
HTTP/1.1 100 Continue
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1247
{"status": "upload complete"}
```text
Used when client sends `Expect: 100-continue` header before sending large request body.
**101 Switching Protocols**
```http
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Indicates protocol upgrade (HTTP to WebSocket, HTTP/1.1 to HTTP/2).
102 Processing (WebDAV)
HTTP/1.1 102 Processing
```text
Informs client that server is still processing the request (prevents timeout).
### 2xx Success Responses
Success codes indicate that the client's request was received, understood, and successfully processed. The specific 2xx code provides details about what type of success occurred.
**Decision Framework for 2xx Codes:**
```text
Request successful?
├─ Yes → Was resource created?
│ ├─ Yes → 201 Created
│ └─ No → Was content returned?
│ ├─ Yes → 200 OK
│ ├─ No content → 204 No Content
│ └─ Accepted for processing → 202 Accepted
└─ No → Use 4xx or 5xx
```text
**Common 2xx Codes:**
**200 OK - Standard Success**
```http
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 156
{
"users": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]
}
Most common success response. Request succeeded and response contains requested data.
201 Created - Resource Creation
HTTP/1.1 201 Created
Location: /api/users/123
Content-Type: application/json
{
"id": 123,
"name": "Charlie",
"createdAt": "2026-01-18T10:30:00Z"
}
```text
New resource was successfully created. Include `Location` header pointing to new resource.
**202 Accepted - Asynchronous Processing**
```http
HTTP/1.1 202 Accepted
Content-Type: application/json
{
"jobId": "job_abc123",
"status": "processing",
"estimatedCompletion": "2026-01-18T10:35:00Z"
}
Request accepted but processing not complete. Common for background jobs.
204 No Content - Successful with No Response Body
HTTP/1.1 204 No Content
Cache-Control: no-cache
```nginx
Request succeeded but no content to return. Common for DELETE operations or updates.
### 3xx Redirection Responses
Redirection codes indicate that additional action is needed to complete the request. They guide clients to the correct resource location or inform them about resource status changes.
**Redirection Decision Tree:**
```text
Resource moved?
├─ Permanently → 301 Moved Permanently
├─ Temporarily → 302 Found or 307 Temporary Redirect
├─ Not modified → 304 Not Modified
└─ Multiple choices → 300 Multiple Choices
```text
**Common 3xx Codes:**
**301 Moved Permanently - Permanent Redirect**
```http
HTTP/1.1 301 Moved Permanently
Location: https://newdomain.com/api/users
Cache-Control: max-age=31536000
<html>
<body>Resource has moved to <a href="https://newdomain.com/api/users">new location</a></body>
</html>
Resource permanently moved. Search engines update their indexes.
302 Found - Temporary Redirect
HTTP/1.1 302 Found
Location: /login?redirect=/dashboard
Cache-Control: no-cache
```text
Resource temporarily at different location. Original URL remains valid.
**304 Not Modified - Cached Content Valid**
```http
HTTP/1.1 304 Not Modified
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Cache-Control: max-age=300
Client’s cached version is still current. No response body needed.
307 Temporary Redirect - Method Preserved
HTTP/1.1 307 Temporary Redirect
Location: /api/v2/users
```text
Like 302 but guarantees HTTP method won't change during redirect.
**308 Permanent Redirect - Method Preserved**
```http
HTTP/1.1 308 Permanent Redirect
Location: https://api.example.com/v2/users
Like 301 but guarantees HTTP method won’t change during redirect.
4xx Client Error Responses
Client error codes indicate that the request contains bad syntax, cannot be fulfilled, or lacks proper authorization. These errors suggest the client needs to modify their request.
Client Error Decision Framework:
Request valid?
├─ No → Malformed syntax → 400 Bad Request
├─ Yes → Authorized?
│ ├─ No → Authentication required → 401 Unauthorized
│ ├─ Forbidden → 403 Forbidden
│ └─ Yes → Resource exists?
│ ├─ No → 404 Not Found
│ ├─ Yes → Method allowed?
│ │ ├─ No → 405 Method Not Allowed
│ │ └─ Yes → Content acceptable?
│ │ ├─ No → 406 Not Acceptable
│ │ └─ Yes → Rate limited?
│ │ ├─ Yes → 429 Too Many Requests
│ │ └─ No → Process request
└─ Validation failed → 422 Unprocessable Entity
Common 4xx Codes:
400 Bad Request - Malformed Request
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Invalid JSON syntax",
"details": "Unexpected token '}' at position 45",
"code": "INVALID_JSON"
}
```text
Request syntax is invalid or cannot be understood.
**401 Unauthorized - Authentication Required**
```http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
Content-Type: application/json
{
"error": "Authentication required",
"message": "Please provide a valid access token"
}
Request lacks valid authentication credentials.
403 Forbidden - Access Denied
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": "Insufficient permissions",
"message": "Admin access required for this operation"
}
```text
Server understood request but refuses to authorize it.
**404 Not Found - Resource Missing**
```http
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": "Resource not found",
"message": "User with ID 999 does not exist"
}
Requested resource could not be found on the server.
422 Unprocessable Entity - Validation Failed
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"error": "Validation failed",
"details": [
{"field": "email", "message": "Invalid email format"},
{"field": "age", "message": "Must be between 18 and 120"}
]
}
```text
Request syntax is correct but contains semantic errors.
**429 Too Many Requests - Rate Limited**
```http
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1642518000
{
"error": "Rate limit exceeded",
"message": "Try again in 60 seconds"
}
Client has sent too many requests in a given time period.
5xx Server Error Responses
Server error codes indicate that the server failed to fulfill a valid request. These errors suggest problems on the server side that the client cannot fix by modifying their request.
Server Error Decision Framework:
Server error occurred?
├─ Generic error → 500 Internal Server Error
├─ Feature not implemented → 501 Not Implemented
├─ Upstream server error → 502 Bad Gateway
├─ Service unavailable → 503 Service Unavailable
├─ Upstream timeout → 504 Gateway Timeout
└─ HTTP version unsupported → 505 HTTP Version Not Supported
Common 5xx Codes:
500 Internal Server Error - Generic Server Error
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": "Internal server error",
"message": "An unexpected error occurred",
"requestId": "req_abc123"
}
```text
Generic server error when specific error type is unknown.
**502 Bad Gateway - Upstream Server Error**
```http
HTTP/1.1 502 Bad Gateway
Content-Type: application/json
{
"error": "Bad gateway",
"message": "Database connection failed"
}
Server acting as gateway received invalid response from upstream server.
503 Service Unavailable - Temporary Unavailability
HTTP/1.1 503 Service Unavailable
Retry-After: 120
Content-Type: application/json
{
"error": "Service unavailable",
"message": "Server is temporarily overloaded"
}
```text
Server temporarily cannot handle request due to maintenance or overload.
**504 Gateway Timeout - Upstream Timeout**
```http
HTTP/1.1 504 Gateway Timeout
Content-Type: application/json
{
"error": "Gateway timeout",
"message": "Upstream server did not respond in time"
}
Server acting as gateway did not receive timely response from upstream.
Status Code Selection Patterns
RESTful API Patterns
Resource Creation:
// POST /api/users
if (validationErrors.length > 0) {
return res.status(422).json({ errors: validationErrors })
}
if (userAlreadyExists) {
return res.status(409).json({ error: 'User already exists' })
}
const user = await createUser(userData)
return res.status(201).json(user)
```javascript
**Resource Retrieval:**
```javascript
// GET /api/users/:id
const user = await findUser(userId)
if (!user) {
return res.status(404).json({ error: 'User not found' })
}
return res.status(200).json(user)
Resource Updates:
// PUT /api/users/:id
const user = await findUser(userId)
if (!user) {
return res.status(404).json({ error: 'User not found' })
}
if (validationErrors.length > 0) {
return res.status(422).json({ errors: validationErrors })
}
const updatedUser = await updateUser(userId, userData)
return res.status(200).json(updatedUser)
```javascript
**Resource Deletion:**
```javascript
// DELETE /api/users/:id
const user = await findUser(userId)
if (!user) {
return res.status(404).json({ error: 'User not found' })
}
await deleteUser(userId)
return res.status(204).send()
Error Handling Patterns
Graceful Degradation:
try {
const result = await processRequest(data)
return res.status(200).json(result)
} catch (error) {
if (error instanceof ValidationError) {
return res.status(422).json({ error: error.message })
}
if (error instanceof NotFoundError) {
return res.status(404).json({ error: error.message })
}
// Log unexpected errors
logger.error('Unexpected error:', error)
return res.status(500).json({
error: 'Internal server error',
requestId: req.id
})
}
```javascript
### Authentication and Authorization Patterns
**Authentication Flow:**
```javascript
// Check if token exists
if (!token) {
return res.status(401).json({
error: 'Authentication required',
message: 'Please provide an access token'
})
}
// Validate token
const user = await validateToken(token)
if (!user) {
return res.status(401).json({
error: 'Invalid token',
message: 'Please log in again'
})
}
// Check permissions
if (!user.hasPermission(requiredPermission)) {
return res.status(403).json({
error: 'Insufficient permissions',
message: 'Admin access required'
})
}
Best Practices
Consistency Guidelines
Use Standard Codes:
- Stick to well-known status codes
- Avoid obscure codes unless specifically needed
- Document any non-standard usage
Provide Helpful Error Messages:
{
"error": "Validation failed",
"message": "The request contains invalid data",
"details": [
{
"field": "email",
"code": "INVALID_FORMAT",
"message": "Email must be a valid email address"
}
],
"requestId": "req_abc123"
}
```javascript
### Client-Side Handling
**Status Code Categories:**
```javascript
function handleResponse(response) {
const status = response.status
if (status >= 200 && status < 300) {
// Success - process response data
return response.json()
}
if (status >= 300 && status < 400) {
// Redirection - follow redirect or update URL
window.location.href = response.headers.get('Location')
}
if (status >= 400 && status < 500) {
// Client error - show user-friendly error message
throw new ClientError('Please check your request and try again')
}
if (status >= 500) {
// Server error - show generic error, maybe retry
throw new ServerError('Something went wrong. Please try again later')
}
}
Monitoring and Debugging
Status Code Metrics:
// Track status code distribution
const statusCodeCounts = {
'2xx': 0, // Success rate
'3xx': 0, // Redirect rate
'4xx': 0, // Client error rate
'5xx': 0 // Server error rate
}
// Alert on high error rates
if (statusCodeCounts['5xx'] / totalRequests > 0.01) {
alert('High server error rate detected')
}
```text
## Common Anti-Patterns
### Incorrect Status Code Usage
**Don't Use 200 for Errors:**
```javascript
// Bad: Error with 200 status
res.status(200).json({
success: false,
error: 'User not found'
})
// Good: Proper error status
res.status(404).json({
error: 'User not found'
})
Don’t Use Generic Codes:
// Bad: Generic 400 for validation errors
res.status(400).json({ error: 'Invalid data' })
// Good: Specific 422 for validation errors
res.status(422).json({
error: 'Validation failed',
details: validationErrors
})
```text
### Missing Error Context
**Provide Actionable Information:**
```javascript
// Bad: Vague error message
res.status(403).json({ error: 'Forbidden' })
// Good: Specific guidance
res.status(403).json({
error: 'Insufficient permissions',
message: 'This operation requires admin privileges',
requiredRole: 'admin',
currentRole: 'user'
})
Related Concepts
HTTP status codes work in conjunction with other HTTP concepts:
- Request Lifecycle: How status codes fit into the complete request flow
- Headers and Caching: How status codes affect caching behavior
- Individual Status Codes: Detailed explanations of specific codes
- HTTP Methods: How different methods relate to expected status codes
- Error Handling: Headers that provide additional error context
Understanding status codes is fundamental to HTTP communication. They provide a standardized way to communicate request outcomes, enable proper error handling, and help create predictable, user-friendly applications. Start with the most common codes (200, 404, 500) and gradually incorporate more specific codes as your application’s needs become more sophisticated.
Frequently Asked Questions
What are HTTP status codes?
Status codes are 3-digit numbers indicating the result of an HTTP request. They are grouped: 1xx informational, 2xx success, 3xx redirect, 4xx client error, 5xx server error.
What are the most common status codes?
200 OK (success), 301/302 (redirect), 400 (bad request), 401 (unauthorized), 403 (forbidden), 404 (not found), 500 (server error), 503 (service unavailable).
What is the difference between 4xx and 5xx errors?
4xx errors are client errors (bad request, not found). 5xx errors are server errors (server crashed, overloaded). 4xx means fix your request; 5xx means wait or contact support.
How do I handle status codes in my application?
Check the status code before processing the response. Handle success (2xx), follow redirects (3xx), show user-friendly errors for 4xx, and retry or alert for 5xx.