HTTP Status Codes: Complete Developer Guide 2025
What 2xx, 4xx, and 5xx mean, when to return which code from your API, and how to fix the most common errors.
HTTP status codes are the language servers use to communicate with clients. Understanding these codes is fundamental to web development, API design, and debugging. A 404 Not Found tells you the resource doesn't exist, while a 500 Internal Server Error indicates a server-side problem. But what about 429 Too Many Requests or 503 Service Unavailable? Let's decode the complete HTTP status code system.
Understanding Status Code Categories
HTTP status codes are organized into five categories, each identified by the first digit:
- 1xx (Informational): Request received, continuing process
- 2xx (Success): Request successfully received, understood, and accepted
- 3xx (Redirection): Further action needed to complete the request
- 4xx (Client Error): Request contains bad syntax or cannot be fulfilled
- 5xx (Server Error): Server failed to fulfill a valid request
2xx Success Codes
These codes indicate that the request was successfully received, understood, and accepted:
200 OK
The standard success response. The request succeeded, and the response body contains the requested data. This is the most common success code for GET, PUT, and PATCH requests.
GET /api/users/123
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 123, "name": "John Doe"}
201 Created
The request succeeded and a new resource was created. Typically used 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 201 Created
Location: /api/users/456
Content-Type: application/json
{"id": 456, "name": "Jane Smith"}
204 No Content
The server successfully processed the request but is not returning any content. Commonly used for DELETE requests or PUT/PATCH requests where the response body isn't needed. The response body should be empty.
202 Accepted
The request has been accepted for processing, but processing has not been completed. Used for asynchronous operations where the result will be available later. The response should include information about where to check the status.
3xx Redirection Codes
These codes indicate that further action is needed to complete the request, typically involving a redirect to another location:
301 Moved Permanently
The requested resource has been permanently moved to a new URL. Browsers and search engines should update their links. The new URL should be provided in the Location header.
GET /old-page
HTTP/1.1 301 Moved Permanently
Location: /new-page302 Found (Temporary Redirect)
The requested resource temporarily resides under a different URL. Unlike 301, this redirect is temporary, and the original URL should still be used for future requests. Commonly used for URL shorteners or temporary maintenance pages.
304 Not Modified
The client's cached version is still valid. Used for conditional GET requests with If-Modified-Since or If-None-Match headers. This saves bandwidth by not sending the resource again.
4xx Client Error Codes
These codes indicate that the client made an error in the request. The client should not retry the request without modification:
400 Bad Request
The server cannot process the request due to a client error (malformed syntax, invalid request message framing, or deceptive request routing). This is a catch-all for client errors that don't fit other 4xx codes.
POST /api/users
HTTP/1.1 400 Bad Request
Content-Type: application/json
{"error": "Invalid email format"}
401 Unauthorized
The request requires authentication. The client must authenticate itself to get the requested response. This is different from 403, which means the client is authenticated but not authorized.
GET /api/protected
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"403 Forbidden
The client does not have access rights to the content. Unlike 401, the client is authenticated, but it doesn't have permission to access the resource. This is an authorization issue, not an authentication issue.
404 Not Found
The server cannot find the requested resource. This is the most common error code. It means the URL doesn't exist or the resource has been deleted. In REST APIs, this often means the ID doesn't exist in the database.
405 Method Not Allowed
The request method is not allowed for the requested resource. For example, trying to POST to a resource that only accepts GET. The response should include an Allow header listing allowed methods.
409 Conflict
The request conflicts with the current state of the server. Commonly used when trying to create a resource that already exists (e.g., duplicate email) or when a concurrent modification conflict occurs.
422 Unprocessable Entity
The request was well-formed but contains semantic errors. Often used for validation errors where the syntax is correct but the data doesn't meet business rules. This is more specific than 400.
429 Too Many Requests
The user has sent too many requests in a given time ("rate limiting"). The response should include headers indicating when the client can retry, such as Retry-After.
GET /api/data
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 05xx Server Error Codes
These codes indicate that the server failed to fulfill a valid request. The client can retry the request:
500 Internal Server Error
A generic error message when the server encounters an unexpected condition that prevents it from fulfilling the request. This is a catch-all for server errors. In production, you should never expose detailed error information to clients.
502 Bad Gateway
The server, while acting as a gateway or proxy, received an invalid response from an upstream server. Common when a reverse proxy (like nginx) can't reach the application server.
503 Service Unavailable
The server is temporarily unable to handle the request due to maintenance or overload. The response should include a Retry-After header indicating when the service might be available again.
504 Gateway Timeout
The server, while acting as a gateway or proxy, did not receive a timely response from an upstream server. This indicates the upstream server is too slow or unresponsive.
Best Practices for Using Status Codes
Be Consistent
Use the same status codes for the same situations throughout your API. If 404 means "resource not found" in one endpoint, it should mean the same in all endpoints.
Provide Meaningful Error Messages
While status codes tell you what went wrong, error messages tell you why. Always include helpful error messages in the response body:
{
"error": "Validation failed",
"message": "Email address is required",
"field": "email",
"code": "VALIDATION_ERROR"
}
Use Appropriate Codes
Don't use 200 OK for errors. If something went wrong, use the appropriate 4xx or 5xx code. Don't use 404 for authentication failures—use 401 or 403.
Include Helpful Headers
Use headers to provide additional context:
Locationfor redirects and created resourcesRetry-Afterfor rate limiting and service unavailableAllowfor 405 Method Not AllowedWWW-Authenticatefor 401 Unauthorized
Common Mistakes to Avoid
Using 200 for Errors
Never return 200 OK with an error in the body. This breaks HTTP semantics and makes it impossible for clients to distinguish between success and failure without parsing the response body.
Confusing 401 and 403
401 Unauthorized means "you need to authenticate." 403 Forbidden means "you're authenticated, but you don't have permission." Use them correctly.
Overusing 500
Don't use 500 for client errors. If the client sends invalid data, use 400 or 422. Reserve 500 for actual server failures.
Debugging with Status Codes
When debugging API issues, status codes are your first clue:
- 4xx errors: Check the request—wrong URL, missing headers, invalid data
- 5xx errors: Check the server—database issues, code bugs, resource exhaustion
- 429 errors: Implement rate limiting or reduce request frequency
- 502/504 errors: Check upstream services, network issues, or timeouts
Conclusion
HTTP status codes are a fundamental part of web development. Understanding them helps you build better APIs, debug issues faster, and communicate more effectively with other developers. Use them correctly, provide meaningful error messages, and be consistent across your application.
For testing and debugging HTTP requests, check out our API Tester tool, which helps you inspect status codes, headers, and response bodies in real-time.
Try these tools
Use these tools alongside this guide
Part of the ThenCatch blog. Learn more about us or browse more guides.