HTTP Status Codes: A Complete Reference Guide
Every HTTP status code explained with examples. Learn when to use each code in your APIs, handle errors properly, and follow REST best practices.
Every time your browser loads a page or your app calls an API, the server responds with an HTTP status code. Understanding these codes is essential for debugging, building APIs, and handling errors gracefully.
What Are HTTP Status Codes?
HTTP status codes are three-digit numbers returned by servers to indicate the result of a request. They're grouped into five classes based on their first digit:
| Range | Category | Meaning |
|---|---|---|
| 1xx | Informational | Request received, processing continues |
| 2xx | Success | Request successfully received and accepted |
| 3xx | Redirection | Further action needed to complete request |
| 4xx | Client Error | Request contains bad syntax or cannot be fulfilled |
| 5xx | Server Error | Server failed to fulfill a valid request |
1xx Informational
These codes indicate the server received the request and is continuing to process it. You rarely see these in practice.
100 Continue
The server received the request headers and the client should proceed to send the body.
When it's used: Large file uploads. The client sends headers first, and if the server approves (correct auth, enough space), it sends 100 to signal "go ahead."
101 Switching Protocols
The server is switching protocols as requested by the client.
When it's used: WebSocket connections. The client requests an upgrade from HTTP to WebSocket:
GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Server responds with 101, then the WebSocket connection begins.
102 Processing
The server is still processing a long request.
When it's used: WebDAV operations that take a long time.
2xx Success
The request was successfully received, understood, and accepted.
200 OK
The standard success response. The meaning depends on the HTTP method:
| Method | 200 Means |
|---|---|
| GET | Resource returned in response body |
| POST | Action completed, result in body |
| PUT | Resource updated, result in body |
| DELETE | Deletion completed (some APIs) |
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 123, "name": "John"}
201 Created
A new resource was successfully created. Should include a Location header with the new resource's URL.
Use for: POST requests that create resources.
HTTP/1.1 201 Created
Location: /api/users/123
Content-Type: application/json
{"id": 123, "name": "John"}
202 Accepted
The request was accepted but hasn't been processed yet. Used for asynchronous operations.
Use for: Background jobs, batch processing, long-running tasks.
HTTP/1.1 202 Accepted
Content-Type: application/json
{"jobId": "abc123", "status": "pending", "checkUrl": "/jobs/abc123"}
204 No Content
Success, but there's no content to return.
Use for: DELETE requests, PUT requests when you don't need to return the updated resource.
HTTP/1.1 204 No Content
Note: 204 responses must not have a body.
206 Partial Content
Returning part of a resource (used with range requests).
Use for: Video streaming, resumable downloads.
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/10240
Content-Length: 1024
3xx Redirection
The client must take additional action to complete the request.
301 Moved Permanently
The resource has permanently moved to a new URL. Clients should update bookmarks and search engines should update their index.
HTTP/1.1 301 Moved Permanently
Location: https://new-site.com/page
Use for: Domain changes, URL restructuring, HTTP to HTTPS redirects.
302 Found (Temporary Redirect)
The resource is temporarily at a different URL. The client should continue using the original URL for future requests.
HTTP/1.1 302 Found
Location: /temporary-page
Historical note: Browsers incorrectly changed POST to GET on 302. Use 307 if you need to preserve the method.
303 See Other
The response can be found at another URL using GET. Typically used after a POST to redirect to a result page.
Use for: POST/Redirect/GET pattern to prevent form resubmission.
304 Not Modified
The resource hasn't changed since the version in the client's cache. No body is returned.
Use for: Caching. Client sends If-Modified-Since or If-None-Match, server responds with 304 if unchanged.
GET /api/data HTTP/1.1
If-None-Match: "abc123"
HTTP/1.1 304 Not Modified
307 Temporary Redirect
Like 302, but guarantees the request method won't change.
Use for: Temporary redirects where you need to preserve POST, PUT, etc.
308 Permanent Redirect
Like 301, but guarantees the request method won't change.
Use for: Permanent redirects for non-GET requests.
4xx Client Errors
The request was invalid or cannot be fulfilled. This is the client's fault.
400 Bad Request
The request is malformed and cannot be understood.
Use for:
- Malformed JSON
- Invalid syntax
- Missing required fields
- Invalid query parameters
HTTP/1.1 400 Bad Request
Content-Type: application/json
{"error": "Invalid JSON: unexpected token at position 42"}
401 Unauthorized
Authentication is required but missing or invalid.
Use for: Missing auth token, expired token, invalid credentials.
Should include a WWW-Authenticate header:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
{"error": "Invalid or expired token"}
403 Forbidden
The server understood the request but refuses to authorize it. Unlike 401, authenticating won't help.
Use for: User is authenticated but lacks permission.
HTTP/1.1 403 Forbidden
{"error": "You don't have permission to delete this resource"}
401 vs 403:
- 401: "Who are you?" (authentication)
- 403: "I know who you are, but you can't do this" (authorization)
404 Not Found
The requested resource doesn't exist.
HTTP/1.1 404 Not Found
{"error": "User not found"}
Security tip: Sometimes you should use 404 even when the issue is permission-based, to avoid revealing that a resource exists.
405 Method Not Allowed
The HTTP method is not supported for this endpoint.
HTTP/1.1 405 Method Not Allowed
Allow: GET, POST
406 Not Acceptable
The server can't produce a response matching the client's Accept headers.
408 Request Timeout
The client took too long to send the request.
409 Conflict
The request conflicts with the current state of the resource.
Use for:
- Duplicate entries (email already exists)
- Version conflicts (optimistic locking)
- State conflicts (can't delete active subscription)
HTTP/1.1 409 Conflict
{"error": "A user with this email already exists"}
410 Gone
The resource existed but has been permanently deleted. Unlike 404, this is definitive - it won't come back.
Use for: Deleted content where you want clients to stop retrying.
413 Payload Too Large
The request body exceeds the server's limits.
HTTP/1.1 413 Payload Too Large
{"error": "File size exceeds 10MB limit"}
415 Unsupported Media Type
The request's Content-Type is not supported.
HTTP/1.1 415 Unsupported Media Type
{"error": "Content-Type must be application/json"}
422 Unprocessable Entity
The request is syntactically correct but semantically invalid.
Use for: Validation errors, business logic violations.
HTTP/1.1 422 Unprocessable Entity
{
"error": "Validation failed",
"details": {
"email": "Invalid email format",
"age": "Must be at least 18"
}
}
400 vs 422:
- 400: "I can't parse this" (syntax error)
- 422: "I understand it, but it's invalid" (semantic error)
429 Too Many Requests
The client has sent too many requests (rate limiting).
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{"error": "Rate limit exceeded. Try again in 60 seconds."}
Include Retry-After header to tell clients when to retry.
5xx Server Errors
The server failed to fulfill a valid request. This is the server's fault.
500 Internal Server Error
A generic server error when something unexpected happened.
HTTP/1.1 500 Internal Server Error
{"error": "An unexpected error occurred"}
Never expose internal details (stack traces, database errors) in production.
501 Not Implemented
The server doesn't support the functionality required.
Use for: Features that are planned but not yet implemented.
502 Bad Gateway
The server, acting as a gateway, received an invalid response from upstream.
Common causes: Upstream server crashed, misconfigured proxy, network issues.
503 Service Unavailable
The server is temporarily unavailable (overloaded, maintenance).
HTTP/1.1 503 Service Unavailable
Retry-After: 3600
{"error": "Server is under maintenance. Back in 1 hour."}
504 Gateway Timeout
The server, acting as a gateway, didn't receive a timely response from upstream.
Common causes: Slow database queries, upstream service timeout, network latency.
API Design Best Practices
Choosing the Right Status Code
Request successful?
├─ Yes: 2xx
│ ├─ Created something? → 201
│ ├─ No content to return? → 204
│ ├─ Async processing? → 202
│ └─ Default → 200
├─ Client's fault?
│ ├─ Not authenticated? → 401
│ ├─ Not authorized? → 403
│ ├─ Resource not found? → 404
│ ├─ Validation failed? → 422
│ ├─ Rate limited? → 429
│ ├─ Malformed request? → 400
│ └─ Conflict? → 409
└─ Server's fault? → 500
Consistent Error Response Format
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{"field": "email", "message": "Invalid email format"},
{"field": "age", "message": "Must be a positive number"}
]
}
}
Common Patterns
| Operation | Success | Error |
|---|---|---|
| GET resource | 200 | 404 |
| GET collection | 200 (empty array is fine) | - |
| POST create | 201 + Location header | 400/422 |
| PUT update | 200 or 204 | 404 |
| DELETE | 204 | 404 |
| Invalid auth | - | 401 |
| No permission | - | 403 |
| Validation | - | 422 |
Security Considerations
- Don't leak information: Return 404 instead of 403 when you don't want to confirm a resource exists.
- Generic 500 errors: Never expose stack traces or internal errors to clients.
- Consistent timing: Avoid timing attacks by taking the same time for "user not found" and "wrong password."
Handling Status Codes in Code
JavaScript/Fetch
const response = await fetch('/api/users');
if (response.ok) { // 200-299
const data = await response.json();
} else if (response.status === 401) {
// Redirect to login
} else if (response.status === 404) {
// Show "not found" message
} else if (response.status >= 500) {
// Show "server error" message
}
Axios
try {
const { data } = await axios.get('/api/users');
} catch (error) {
if (error.response) {
// Server responded with error
const { status, data } = error.response;
if (status === 401) {
// Handle auth error
}
} else if (error.request) {
// No response received
} else {
// Request setup error
}
}
Quick Reference
| Code | Name | When to Use |
|---|---|---|
| 200 | OK | Standard success |
| 201 | Created | Resource created (POST) |
| 204 | No Content | Success, no body (DELETE) |
| 301 | Moved Permanently | URL changed forever |
| 304 | Not Modified | Use cache |
| 400 | Bad Request | Malformed request |
| 401 | Unauthorized | Auth required |
| 403 | Forbidden | Permission denied |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | State conflict |
| 422 | Unprocessable | Validation failed |
| 429 | Too Many Requests | Rate limited |
| 500 | Internal Server Error | Server error |
| 502 | Bad Gateway | Upstream error |
| 503 | Service Unavailable | Maintenance/overload |
Use our HTTP Status Codes reference tool for quick lookups and examples.
Related Tools
Related Articles
Try Our Free Tools
200+ browser-based tools for developers and creators. No uploads, complete privacy.
Explore All Tools