How Status Codes Work
Every HTTP response includes a three-digit status code that tells the client what happened. The first digit defines the category:
| Range | Category | Meaning |
|---|---|---|
| 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 | Request contains an error on the client side |
| 5xx | Server Error | Server failed to fulfill a valid request |
You can test these codes in real time with the API Tester — send requests to any endpoint and inspect the full response including status codes, headers, and body.
1xx Informational
Informational responses indicate the server received the request and is continuing to process it. You rarely interact with these directly in application code.
100 Continue
The server received the request headers and the client should proceed to send the body. This is used with large uploads: the client sends Expect: 100-continue in headers, and the server responds with 100 before the client uploads the body. If the server rejects the request (e.g., unauthorized), it can respond with 4xx instead, saving the client from uploading a large file unnecessarily.
101 Switching Protocols
The server agrees to switch to a different protocol as requested by the client. The most common example is upgrading from HTTP to WebSocket. The client sends an Upgrade: websocket header, and the server responds with 101 before switching to the WebSocket protocol.
103 Early Hints
A relatively new status code that allows the server to send preliminary headers before the final response. This lets the browser start preloading resources (CSS, fonts, scripts) while the server is still generating the full response. Supported in modern browsers and increasingly used for performance optimization.
2xx Success
These codes mean the request was received, understood, and processed successfully.
200 OK
The standard success response. The meaning varies by HTTP method: for GET, the resource is returned in the body; for POST, the result of the action is in the body; for PUT/PATCH, the updated resource is typically returned. This is the code you see most often.
201 Created
The request succeeded and a new resource was created. Used after POST requests that create a new entity. The response should include a Location header pointing to the URL of the newly created resource.
HTTP/1.1 201 Created
Location: /api/users/42
Content-Type: application/json
{
"id": 42,
"name": "Alice",
"created_at": "2026-02-21T10:00:00Z"
}
204 No Content
The request succeeded but there is no content to return. Typically used for DELETE requests or PUT/PATCH requests where you do not need to return the updated resource. The response body must be empty.
206 Partial Content
The server is delivering only part of the resource. Used when the client sends a Range header to request a specific portion of a file, common in video streaming and resumable downloads.
3xx Redirection
Redirection codes tell the client to take additional action, usually following a different URL.
301 Moved Permanently
The resource has permanently moved to a new URL. Browsers cache this redirect and go directly to the new URL on subsequent requests. Search engines transfer ranking to the new URL. Use this when you permanently rename or restructure URLs.
302 Found (Temporary Redirect)
The resource is temporarily at a different URL. Browsers follow the redirect but do not cache it. Search engines keep indexing the original URL. Use for temporary redirects like A/B tests or maintenance pages.
304 Not Modified
The resource has not changed since the last request. Used with conditional requests (If-Modified-Since or If-None-Match headers). The server tells the client to use its cached version, saving bandwidth and improving performance.
307 Temporary Redirect
Like 302, but guarantees the HTTP method will not change. If the original request was POST, the redirect will also be POST. With 302, some older clients might change POST to GET.
308 Permanent Redirect
Like 301, but guarantees the HTTP method will not change. The permanent equivalent of 307.
For permanent URL changes: use 301 (may change method) or 308 (preserves method). For temporary redirects: use 302 (may change method) or 307 (preserves method). When in doubt for simple page redirects, 301 for permanent and 302 for temporary are the safe defaults.
4xx Client Errors
These codes indicate the client sent a bad request. The problem is on the client side and can usually be fixed by correcting the request.
400 Bad Request
The server cannot process the request due to malformed syntax, invalid parameters, or missing required fields. Return a helpful error message in the body explaining what is wrong.
{
"error": "Bad Request",
"message": "Validation failed",
"details": [
{ "field": "email", "issue": "Invalid email format" },
{ "field": "age", "issue": "Must be a positive integer" }
]
}
401 Unauthorized
The request requires authentication. The client has not provided credentials, or the provided credentials are invalid. The response should include a WWW-Authenticate header indicating the authentication scheme. The client should retry with valid credentials.
403 Forbidden
The server understood the request and the client is authenticated, but the authenticated user does not have permission to access this resource. Unlike 401, re-authenticating will not help — the user simply does not have access.
404 Not Found
The requested resource does not exist. This is the most recognized HTTP error code. In REST APIs, return 404 when a specific resource ID does not exist. Do not use 404 for authorization errors — use 403 instead, unless you want to hide the existence of the resource entirely.
405 Method Not Allowed
The HTTP method is not supported for this URL. For example, sending DELETE to a read-only endpoint. The response must include an Allow header listing which methods are permitted.
409 Conflict
The request conflicts with the current state of the resource. Common in REST APIs when creating a resource that already exists (duplicate email, username, etc.) or when an optimistic concurrency check fails because the resource was modified since the client last fetched it.
422 Unprocessable Entity
The request body is syntactically correct (valid JSON) but semantically invalid. Originally from WebDAV, now widely used in REST APIs for business logic validation errors. Some APIs use 400 for all validation; others use 422 for semantic validation specifically.
429 Too Many Requests
The client has been rate-limited. The response should include a Retry-After header indicating how long to wait. Well-designed APIs also include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers.
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1708520460
5xx Server Errors
Server errors mean the server failed to fulfill a valid request. The problem is on the server side and the client typically cannot fix it.
500 Internal Server Error
A catch-all error for unexpected server failures. Usually caused by unhandled exceptions, null pointer errors, database connection failures, or misconfigured servers. This code means something broke in your code. Check your server logs for the stack trace.
502 Bad Gateway
The server acting as a proxy or gateway received an invalid response from the upstream server. In practice, this often means your application server (Node.js, Python, etc.) crashed or is not running, and the reverse proxy (Nginx, AWS ALB) cannot get a response from it.
503 Service Unavailable
The server is temporarily unable to handle requests, usually due to maintenance or overload. Include a Retry-After header to tell clients when to try again. Unlike 500, this implies the situation is temporary.
504 Gateway Timeout
The proxy server did not receive a response from the upstream server within the configured timeout. This often means a slow database query, an external API call that is hanging, or an application that is processing too long. Increase timeouts or optimize the slow operation.
In production, 5xx error responses should never include stack traces, database queries, or internal file paths. Log the details server-side and return a generic message to the client. Exposing internals is a security risk.
REST API Best Practices
Choosing the right status code makes your API predictable and easier to consume. Here is a quick reference for common REST operations:
| Operation | Success Code | Common Error Codes |
|---|---|---|
| GET /users | 200 | 401, 403 |
| GET /users/42 | 200 | 401, 403, 404 |
| POST /users | 201 | 400, 409, 422 |
| PUT /users/42 | 200 | 400, 404, 409, 422 |
| PATCH /users/42 | 200 | 400, 404, 422 |
| DELETE /users/42 | 204 | 401, 403, 404 |
Error Response Format
Standardize your error responses across your entire API. A good structure includes a machine-readable error code, a human-readable message, and field-level details for validation errors:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request body contains invalid fields.",
"details": [
{
"field": "email",
"message": "Must be a valid email address.",
"value": "not-an-email"
}
]
}
}
Troubleshooting Common Errors
Debugging 502 and 504
- Check if your application process is running:
ps aux | grep node - Check application logs for crashes or exceptions
- Verify the proxy is pointing to the correct port
- Test the application directly, bypassing the proxy:
curl http://localhost:3000/health - For 504, check slow database queries and external API timeouts
Debugging 403
- Verify the user's role and permissions in your authorization system
- Check if CORS headers are missing (browsers show CORS errors as network failures)
- Check file permissions on static assets served by Nginx/Apache
- Verify API key or token has the required scopes
Debugging CORS Errors
CORS failures often appear as network errors in the browser, not as a specific HTTP status code. Check that your server returns Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers for preflight (OPTIONS) requests.
Related Free Tools
Frequently Asked Questions
401 Unauthorized means the request lacks valid authentication credentials. The client has not identified itself at all, or the provided credentials (API key, token, username/password) are invalid. The client should retry with proper authentication. 403 Forbidden means the server understood the request and the client is authenticated, but the authenticated user does not have permission to access the requested resource. Re-authenticating will not help because the identity is known but lacks authorization. In practice: 401 means "who are you," 403 means "I know who you are but you cannot access this."
301 Moved Permanently tells browsers and search engines that a resource has permanently moved to a new URL. Search engines transfer SEO ranking to the new URL and update their index. Use 301 when you rename a page, change your domain, or restructure URLs permanently. 302 Found (temporary redirect) tells clients the resource is temporarily at a different URL but may return to the original URL in the future. Search engines keep the original URL in their index. Use 302 for A/B testing, temporary maintenance pages, or when redirecting users during an active session. Using the wrong redirect type can hurt your SEO because search engines treat them very differently.
Return 400 Bad Request for general validation errors where the request body is malformed or missing required fields. Return 422 Unprocessable Entity (from WebDAV, widely adopted in REST APIs) when the request body is well-formed JSON but contains semantic errors, such as an email field with an invalid email format or a quantity field with a negative number. Many APIs use 400 for all validation errors since it is part of the core HTTP specification. The response body should include a structured error object with field-level details, for example: {"errors": [{"field": "email", "message": "Invalid email format"}]}. This helps API consumers display specific error messages to their users.
429 Too Many Requests means the client has sent too many requests in a given time period, hitting a rate limit set by the server. The response usually includes a Retry-After header that tells you how many seconds to wait before sending the next request. To handle it properly: implement exponential backoff (wait 1 second, then 2, then 4, etc.), respect the Retry-After header value, and consider caching responses to reduce the number of requests. In your API design, include rate limit headers like X-RateLimit-Limit (max requests), X-RateLimit-Remaining (requests left), and X-RateLimit-Reset (when the limit resets) so clients can proactively manage their request rate.
500 Internal Server Error means the server itself encountered an unexpected condition that prevented it from fulfilling the request. This is typically caused by unhandled exceptions, bugs in your application code, or database errors. The fix is in your application code or server configuration. 502 Bad Gateway means the server acting as a gateway or proxy (like Nginx or a load balancer) received an invalid response from an upstream server. This often happens when your application server (Node.js, Python, etc.) crashes, is not running, or takes too long to respond. The fix usually involves checking if the upstream application is running and healthy, not the proxy server itself.