HTTP Status Codes: Complete Reference Guide
· 12 min read
Table of Contents
What Are HTTP Status Codes?
HTTP status codes are three-digit numbers returned by a server in response to a client's request. They indicate whether the request was successful, redirected, or resulted in an error. Every time your browser loads a page, calls an API, or submits a form, the server responds with a status code.
Think of status codes as the server's way of communicating what happened with your request. Just like a traffic light tells you whether to stop or go, status codes tell your application whether to proceed, retry, or handle an error.
Status codes are grouped into five categories based on their first digit:
- 1xx (Informational): Request received, processing continues
- 2xx (Success): Request received, understood, and accepted
- 3xx (Redirection): Further action needed to complete the request
- 4xx (Client Error): The request contains an error from the client side
- 5xx (Server Error): The server failed to fulfill a valid request
Quick reference: Use our HTTP Status Codes Lookup tool to quickly check any status code and see detailed explanations with examples.
How Status Codes Work
When a client (like your browser or an API client) makes an HTTP request, the server processes it and returns a response. This response always includes a status code in the first line, followed by headers and an optional body.
Here's what a typical HTTP response looks like:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1234
{"status": "success", "data": {...}}
The status code appears right after the HTTP version. In this example, 200 OK tells the client that the request succeeded.
Status codes serve multiple purposes:
- Communication: They provide a standardized way for servers to communicate outcomes
- Error handling: Applications can programmatically handle different scenarios based on the code
- Debugging: Developers can quickly identify where problems occur in the request-response cycle
- SEO: Search engines use status codes to understand how to index content
- Caching: Browsers and CDNs use codes to determine caching behavior
1xx Informational
Informational status codes indicate that the server has received the request and is continuing to process it. These are provisional responses and are rarely seen in everyday web browsing, but they're important for certain protocols and optimizations.
100 Continue
The server received the request headers and the client should proceed to send the body. This is used with large uploads where the client sends an Expect: 100-continue header to check if the server will accept the request before sending the full payload.
This optimization prevents wasting bandwidth on requests that will be rejected. For example, if you're uploading a 500MB video file, you don't want to send all that data only to find out the server will reject it due to authentication failure.
POST /upload HTTP/1.1
Host: api.example.com
Content-Length: 524288000
Expect: 100-continue
// Server responds with 100 Continue
// Client then sends the request body
101 Switching Protocols
The server agrees to switch protocols as requested by the client. Most commonly seen when upgrading from HTTP to WebSocket using the Upgrade: websocket header.
WebSockets enable real-time, bidirectional communication between client and server, which is essential for chat applications, live updates, and collaborative tools.
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
// Server responds with 101 Switching Protocols
103 Early Hints
This relatively new status code lets the server send preliminary headers before the final response. It's often used to start preloading resources like CSS, fonts, and JavaScript files while the server is still preparing the main response.
Early Hints can significantly improve page load times by allowing browsers to start downloading critical resources earlier in the page load process.
Pro tip: Most developers will never need to handle 1xx codes directly. They're typically managed by web servers and HTTP libraries automatically. Focus your error handling on 4xx and 5xx codes instead.
2xx Success
Success codes are what you want to see. They indicate that the request was received, understood, and accepted successfully. Different 2xx codes provide nuanced information about exactly how the request was processed.
200 OK
The standard success response. The request succeeded and the response body contains the requested data. This is the most common status code on the web.
Use 200 OK for successful GET requests that return data, successful POST requests that return created resource data, and successful PUT/PATCH requests that return updated resource data.
GET /api/users/123 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 123, "name": "John Doe", "email": "[email protected]"}
201 Created
A new resource was successfully created. This is the appropriate response for POST requests that create new resources. The response should include a Location header pointing to the newly created resource.
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "Jane Smith", "email": "[email protected]"}
HTTP/1.1 201 Created
Location: /api/users/124
Content-Type: application/json
{"id": 124, "name": "Jane Smith", "email": "[email protected]"}
202 Accepted
The request has been accepted for processing, but processing has not been completed. This is useful for asynchronous operations where the server queues the request for later processing.
Common use cases include batch processing, email sending, video encoding, and other long-running operations that shouldn't block the HTTP response.
204 No Content
The request succeeded, but there's no content to return. This is commonly used for DELETE requests or PUT/PATCH requests where the client doesn't need the updated resource returned.
Using 204 No Content instead of 200 OK with an empty body saves bandwidth and clearly communicates intent.
DELETE /api/users/123 HTTP/1.1
HTTP/1.1 204 No Content
206 Partial Content
The server is delivering only part of the resource due to a range header sent by the client. This enables resumable downloads and video streaming where the client requests specific byte ranges.
Video players use this extensively to allow seeking to different parts of a video without downloading the entire file first.
| Status Code | Name | When to Use |
|---|---|---|
200 |
OK | Standard success response with content |
201 |
Created | Resource successfully created |
202 |
Accepted | Request queued for async processing |
204 |
No Content | Success with no response body needed |
206 |
Partial Content | Returning requested byte range |
3xx Redirection
Redirection codes indicate that the client needs to take additional action to complete the request. These are crucial for URL management, SEO, and maintaining backward compatibility when resources move.
301 Moved Permanently
The resource has permanently moved to a new URL specified in the Location header. Browsers and search engines should update their records to use the new URL.
This is the go-to status code for permanent redirects. Search engines will transfer the SEO value from the old URL to the new one, and browsers will cache the redirect.
GET /old-page HTTP/1.1
HTTP/1.1 301 Moved Permanently
Location: https://example.com/new-page
Pro tip: Use 301 redirects when you've permanently moved content. Use 302 for temporary moves. Getting this wrong can hurt your SEO, as search engines treat them very differently.
302 Found (Temporary Redirect)
The resource temporarily resides at a different URL. The client should continue to use the original URL for future requests. Search engines won't transfer SEO value with this redirect.
Common use cases include A/B testing, maintenance pages, and temporary promotional pages.
303 See Other
The response to the request can be found at another URL using GET. This is commonly used after POST requests to redirect to a result page, preventing duplicate form submissions if the user refreshes.
This implements the Post/Redirect/Get pattern, which is a best practice for web forms.
304 Not Modified
The resource hasn't been modified since the version specified in the request headers (If-Modified-Since or If-None-Match). The client can use its cached version.
This dramatically reduces bandwidth usage and improves performance by avoiding unnecessary data transfer when content hasn't changed.
307 Temporary Redirect
Similar to 302, but guarantees that the request method won't change when redirected. If the original request was POST, the redirected request will also be POST.
308 Permanent Redirect
Similar to 301, but guarantees that the request method won't change. This is the modern, more precise version of 301 for APIs and applications that need strict method preservation.
4xx Client Errors
Client error codes indicate that the request contains bad syntax or cannot be fulfilled due to client-side issues. These errors mean the client needs to modify the request before retrying.
400 Bad Request
The server cannot process the request due to malformed syntax, invalid request message framing, or deceptive request routing. This is a generic error for requests that don't fit other 4xx categories.
Common causes include malformed JSON, missing required fields, invalid data types, or requests that violate API constraints.
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "John", "email": "not-an-email"}
HTTP/1.1 400 Bad Request
Content-Type: application/json
{"error": "Invalid email format"}
401 Unauthorized
Authentication is required and has failed or hasn't been provided. Despite the name, this actually means "unauthenticated" – the client needs to provide valid credentials.
The response should include a WWW-Authenticate header indicating the authentication method required.
GET /api/protected-resource HTTP/1.1
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
{"error": "Authentication required"}
403 Forbidden
The server understood the request but refuses to authorize it. Unlike 401, authentication won't help – the client doesn't have permission to access this resource.
Use this when a user is authenticated but doesn't have the necessary permissions, or when access is restricted by IP address, rate limiting, or other policies.
404 Not Found
The most famous status code. The server can't find the requested resource. This could mean the URL is wrong, the resource was deleted, or it never existed.
For APIs, return 404 when a specific resource ID doesn't exist. For websites, show a helpful 404 page with navigation options and search functionality.
Quick tip: Don't return 404 for authorization failures. Use 403 or 404 strategically based on whether you want to reveal that a resource exists. For security-sensitive resources, 404 can prevent information disclosure.
405 Method Not Allowed
The request method is not supported for the requested resource. For example, trying to POST to a read-only endpoint or DELETE on a resource that doesn't support deletion.
The response must include an Allow header listing the valid methods.
DELETE /api/users HTTP/1.1
HTTP/1.1 405 Method Not Allowed
Allow: GET, POST, PUT
{"error": "DELETE method not supported"}
408 Request Timeout
The server timed out waiting for the request. The client took too long to send the complete request.
409 Conflict
The request conflicts with the current state of the server. Common in scenarios like trying to create a resource that already exists, or updating a resource that has been modified by another request.
This is particularly important for APIs that need to handle concurrent updates and maintain data consistency.
410 Gone
The resource is permanently gone and won't be available again. Unlike 404, this indicates intentional removal. Use this when you want to explicitly communicate that a resource was deleted and won't return.
413 Payload Too Large
The request entity is larger than the server is willing or able to process. Common when uploading files that exceed size limits.
415 Unsupported Media Type
The server refuses to accept the request because the payload format is not supported. For example, sending XML when the API only accepts JSON.
422 Unprocessable Entity
The request was well-formed but contains semantic errors. This is commonly used for validation errors where the syntax is correct but the data doesn't meet business rules.
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "", "age": -5}
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"errors": {
"name": "Name cannot be empty",
"age": "Age must be positive"
}
}
429 Too Many Requests
The user has sent too many requests in a given time period. This is used for rate limiting to prevent abuse and ensure fair resource usage.
Include Retry-After header to tell the client when they can retry.
| Status Code | Name | Common Cause | How to Fix |
|---|---|---|---|
400 |
Bad Request | Malformed syntax or invalid data | Check request format and data types |
401 |
Unauthorized | Missing or invalid credentials | Provide valid authentication |
403 |
Forbidden | Insufficient permissions | Request access or use authorized account |
404 |
Not Found | Resource doesn't exist | Verify URL and resource ID |
429 |
Too Many Requests | Rate limit exceeded | Wait and retry with backoff |
5xx Server Errors
Server error codes indicate that the server failed to fulfill a valid request. These errors mean something went wrong on the server side, and the client generally can't fix the issue by modifying the request.
500 Internal Server Error
The generic server error. Something went wrong on the server, but it doesn't fit into a more specific 5xx category. This is often caused by unhandled exceptions, configuration errors, or unexpected conditions.
When you see this error, check server logs for stack traces and error details. Never expose internal error details to clients in production – log them server-side instead.
GET /api/users HTTP/1.1
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{"error": "An unexpected error occurred"}
501 Not Implemented
The server doesn't support the functionality required to fulfill the request. This might be used for HTTP methods that aren't implemented yet or features that are planned but not available.
502 Bad Gateway
The server, while acting as a gateway or proxy, received an invalid response from the upstream server. This commonly occurs when a reverse proxy can't reach the application server, or the application server returns a malformed response.
Common causes include application server crashes, network issues between proxy and application, or application server overload.
503 Service Unavailable
The server is temporarily unable to handle the request. This is often used during maintenance, when the server is overloaded, or when a required service is down.
Include a Retry-After header to indicate when the client should try again.
GET /api/users HTTP/1.1
HTTP/1.1 503 Service Unavailable
Retry-After: 3600
{"error": "Service temporarily unavailable for maintenance"}
504 Gateway Timeout
The server, acting as a gateway or proxy, didn't receive a timely response from the upstream server. This typically means the application server is taking too long to respond.
Common causes include slow database queries, external API timeouts, or resource-intensive operations that exceed timeout limits.
Pro tip: When debugging 5xx errors, always check server logs first. These errors indicate server-side issues that require access to backend systems to diagnose and fix. Use monitoring tools like our Uptime Monitor to catch these errors before users do.
Troubleshooting Common Errors
Understanding status codes is one thing, but knowing how to fix the underlying issues is what matters. Here's a practical guide to troubleshooting the most common HTTP errors.
Debugging 404 Not Found Errors
404 errors are frustrating but usually straightforward to fix:
- Check the URL: Verify spelling, capitalization, and path structure
- Verify routing: Ensure your application's routing configuration includes the path
- Check file existence: For static files, confirm the file exists in the correct directory
- Review redirects: A misconfigured redirect might be sending requests to non-existent URLs
- Clear cache: Browser or CDN caching might serve stale 404 responses
For APIs, implement proper error responses that help developers understand what went wrong:
{
"error": "Resource not found",
"message": "User with ID 12345 does not exist",
"code": "USER_NOT_FOUND"
}
Resolving 401 and 403 Authentication Issues
Authentication and authorization errors require different approaches:
For 401 Unauthorized:
- Verify authentication credentials are being sent correctly
- Check token expiration – refresh tokens if needed
- Ensure authentication headers are properly formatted
- Verify the authentication endpoint is working
- Check for CORS issues that might strip authentication headers
For 403 Forbidden:
- Verify the authenticated user has the required permissions
- Check role-based access control (RBAC) configuration
- Review IP whitelist/blacklist settings
- Ensure the resource isn't restricted by other policies
Fixing 500 Internal Server Errors
Server errors require backend investigation:
- Check server logs: Look for stack traces and error messages
- Review recent changes: Did a recent deployment introduce the bug?
- Test database connectivity: Many 500 errors stem from database issues
- Verify environment variables: Missing or incorrect configuration can cause crashes
- Check resource limits: Memory, disk space, or connection pool exhaustion
- Review third-party services: External API failures might cascade to your server
Handling 502 and 504 Gateway Errors
Gateway errors indicate communication problems between servers:
For 502 Bad Gateway:
- Verify the application server is running
- Check network connectivity between proxy and application
- Review proxy configuration (nginx, Apache, etc.)
- Ensure the application is listening on the correct port
- Check firewall rules that might block connections
For 504 Gateway Timeout:
- Increase timeout settings in your proxy configuration
- Optimize slow database queries
- Add caching to reduce processing time
- Implement request queuing for long-running operations
- Scale application servers to handle load
Dealing with Rate Limiting (429)
When you hit rate limits, implement proper retry logic:
async function fetchWithRetry(url, options = {}, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
const delay = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
Best practices for avoiding rate limits:
- Implement exponential backoff for retries
- Cache responses when possible
- Batch requests instead of making many individual calls
- Monitor your usage against rate limit quotas
- Request higher rate limits if you have legitimate high-volume needs
Best Practices for Developers
Using HTTP status codes correctly improves API design, debugging, and user experience. Here are essential best practices every developer should follow.
Choosing the Right Status Code
Don't default to 200 for everything. Use specific codes that accurately describe what happened:
- Resource created? Use 201, not 200
- No content to return? Use 204, not 200 with empty body
- Validation failed? Use 422, not 400
- Authentication failed?