HTTP Status Codes: Complete Guide with Examples
All HTTP status codes explained: 2xx, 3xx, 4xx, 5xx. When to use them in your APIs.
Introduction to HTTP Status Codes
HTTP status codes are three-digit numbers returned by servers to indicate the result of a client's request. Understanding these codes is essential for debugging APIs, building robust applications, and creating better user experiences. This guide covers all major status codes with practical examples.
Status Code Categories
Overview
| Range | Category | Description |
|---|---|---|
| 1xx | Informational | Request received, continuing process |
| 2xx | Success | Request successfully received and processed |
| 3xx | Redirection | Further action needed to complete request |
| 4xx | Client Error | Request contains error or cannot be fulfilled |
| 5xx | Server Error | Server failed to fulfill valid request |
1xx Informational
100 Continue
Server acknowledges the request headers. Client should continue with the request body.
// Used with large uploads
// Client sends: Expect: 100-continue header
// Server responds: 100 Continue
// Client then sends body
101 Switching Protocols
Server is switching to a different protocol as requested by client.
// WebSocket upgrade
GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
2xx Success
200 OK
The request succeeded. Response body contains the requested data.
GET /api/users/123
HTTP/1.1 200 OK
{
"id": 123,
"name": "John Doe"
}
201 Created
A new resource was successfully created.
POST /api/users
HTTP/1.1 201 Created
Location: /api/users/124
{
"id": 124,
"name": "Jane Doe"
}
204 No Content
Request succeeded but no content to return.
DELETE /api/users/123
HTTP/1.1 204 No Content
// Empty body
206 Partial Content
Server is delivering only part of the resource (range request).
// Useful for video streaming, resumable downloads
GET /video.mp4
Range: bytes=0-999
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-999/10000
3xx Redirection
301 Moved Permanently
Resource permanently moved to a new URL. Search engines update their index.
GET /old-page
HTTP/1.1 301 Moved Permanently
Location: /new-page
// Use for: domain changes, URL restructuring
302 Found (Temporary Redirect)
Resource temporarily at different URL. Original URL remains valid.
GET /login
HTTP/1.1 302 Found
Location: /dashboard
// Use for: login redirects, A/B testing
304 Not Modified
Resource hasn't changed since last request. Use cached version.
GET /api/data
If-None-Match: "abc123"
HTTP/1.1 304 Not Modified
// No body - use cached response
307 Temporary Redirect
Like 302, but method and body must not change.
POST /api/old-endpoint
HTTP/1.1 307 Temporary Redirect
Location: /api/new-endpoint
// Client must POST to new location
308 Permanent Redirect
Like 301, but method and body must not change.
4xx Client Errors
400 Bad Request
Server cannot process the request due to client error.
POST /api/users
{ "name": } // Invalid JSON
HTTP/1.1 400 Bad Request
{
"error": "Invalid JSON syntax"
}
401 Unauthorized
Authentication required. Client must provide credentials.
GET /api/protected
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
// Solution: Add Authorization header
403 Forbidden
Server understood request but refuses to authorize it.
DELETE /api/users/1
// Logged in but not admin
HTTP/1.1 403 Forbidden
{
"error": "Admin access required"
}
404 Not Found
Requested resource doesn't exist.
GET /api/users/99999
HTTP/1.1 404 Not Found
{
"error": "User not found"
}
405 Method Not Allowed
HTTP method not supported for this resource.
POST /api/users/123 // Should be PUT
HTTP/1.1 405 Method Not Allowed
Allow: GET, PUT, DELETE
409 Conflict
Request conflicts with current state of the server.
POST /api/users
{ "email": "existing@email.com" }
HTTP/1.1 409 Conflict
{
"error": "Email already exists"
}
422 Unprocessable Entity
Request is well-formed but semantically incorrect.
POST /api/users
{ "email": "not-an-email", "age": -5 }
HTTP/1.1 422 Unprocessable Entity
{
"errors": {
"email": "Invalid email format",
"age": "Must be positive"
}
}
429 Too Many Requests
Rate limit exceeded. Client should slow down.
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
"error": "Rate limit exceeded",
"retryAfter": 60
}
5xx Server Errors
500 Internal Server Error
Generic server error. Something went wrong.
GET /api/data
HTTP/1.1 500 Internal Server Error
{
"error": "An unexpected error occurred"
}
502 Bad Gateway
Server acting as gateway received invalid response from upstream.
// Nginx couldn't reach your app server
HTTP/1.1 502 Bad Gateway
503 Service Unavailable
Server temporarily unable to handle requests.
HTTP/1.1 503 Service Unavailable
Retry-After: 300
// Maintenance, overload, etc.
504 Gateway Timeout
Server didn't receive timely response from upstream server.
// Request took too long
HTTP/1.1 504 Gateway Timeout
Handling Status Codes in Code
JavaScript/Fetch
async function fetchData(url) {
const response = await fetch(url);
if (response.ok) { // 200-299
return response.json();
}
switch (response.status) {
case 401:
throw new Error('Please log in');
case 403:
throw new Error('Access denied');
case 404:
throw new Error('Not found');
case 429:
const retryAfter = response.headers.get('Retry-After');
throw new Error(`Rate limited. Retry in ${retryAfter}s`);
default:
throw new Error(`HTTP ${response.status}`);
}
}
Express.js
app.get('/api/users/:id', async (req, res) => {
try {
const user = await User.findById(req.params.id);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
res.status(200).json(user);
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
app.post('/api/users', async (req, res) => {
const user = await User.create(req.body);
res.status(201)
.location(`/api/users/${user.id}`)
.json(user);
});
Best Practices
API Design
- Use 200 for successful GET/PUT/PATCH
- Use 201 for successful POST that creates
- Use 204 for successful DELETE
- Use 400 for validation errors
- Use 401 for missing authentication
- Use 403 for insufficient permissions
- Include helpful error messages in body
Error Handling
- Always check status codes in clients
- Log 5xx errors for investigation
- Implement retry logic for 503/504
- Respect Retry-After headers
Tools and Resources
For debugging HTTP requests:
- JSON Formatter - Format API responses
- Base64 Encoder - Debug Authorization headers
- URL Encoder - Encode query parameters
Conclusion
HTTP status codes are the foundation of web communication. Key takeaways:
- 2xx means success, 4xx means client error, 5xx means server error
- Use specific codes to communicate exact outcomes
- Include helpful error messages in response bodies
- Handle errors gracefully in your applications
For more developer resources, explore our free online tools. For the complete specification, see MDN HTTP Status Codes and HTTP Status Codes Reference.