All Articles

HTTP Status Codes Explained: The Complete Reference

·16 min read

How HTTP Communication Works

Every time you click a link, submit a form, or fetch data from an API, your browser (or client) sends an HTTP request to a server. The server processes the request and sends back an HTTP response. Every response includes a three-digit status code that tells the client what happened — did the request succeed, was the resource moved, did the client make a mistake, or did the server crash?

Understanding status codes is essential for web developers, API designers, DevOps engineers, and anyone who works with the web. They are the primary communication channel between servers and clients, and interpreting them correctly is the first step in debugging any HTTP issue.

GET /api/users HTTP/1.1
Host: api.example.com
Accept: application/json

---

HTTP/1.1 200 OK
Content-Type: application/json

[{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]

In the example above, 200 OK is the status code — the request was successful and the server returned the requested data.

The Five Categories of Status Codes

HTTP status codes are organized into five classes, identified by the first digit:

Bookmark our HTTP Status Codes Cheatsheet for a quick-reference table you can consult while debugging.

1xx Informational Responses

Informational responses indicate that the server has received the request and the client should continue or wait. You rarely encounter these directly in web development, but they play important roles behind the scenes.

100 Continue

Tells the client that the initial part of the request was received and the client should continue sending the request body. This is used with the Expect: 100-continue header when sending large payloads — the client asks "is it okay to send this big body?" and the server responds with 100 before the client commits to uploading.

101 Switching Protocols

The server is switching to the protocol requested in the Upgrade header. The most common use case is upgrading an HTTP connection to a WebSocket connection.

103 Early Hints

A relatively new status code that lets the server send preload hints before the final response, allowing the browser to start loading resources (stylesheets, scripts) while the server is still preparing the full response.

2xx Success Responses

These are the status codes you want to see. They indicate that the request was received, understood, and processed successfully.

200 OK

The standard success response. The meaning depends on the HTTP method:

201 Created

The request succeeded and a new resource was created. This is the proper response for a successful POST that creates something (a new user, a new order, a new record). The response should include a Location header pointing to the new resource.

POST /api/users HTTP/1.1
Content-Type: application/json

{"name": "Charlie", "email": "charlie@example.com"}

---

HTTP/1.1 201 Created
Location: /api/users/3
Content-Type: application/json

{"id": 3, "name": "Charlie", "email": "charlie@example.com"}

204 No Content

The request succeeded but there is no content to return. Commonly used for DELETE requests — the resource was deleted successfully, and there's nothing meaningful to send back in the body. Also useful for PUT updates where the client doesn't need the updated resource echoed back.

206 Partial Content

The server is delivering only part of the resource, in response to a range request from the client. This powers features like resumable downloads and video streaming, where the client requests specific byte ranges.

3xx Redirection Responses

Redirection responses tell the client that the requested resource is available at a different location. Getting redirects right is crucial for SEO and user experience.

301 Moved Permanently

The resource has permanently moved to a new URL. The client (and search engines) should use the new URL for all future requests. This is the go-to redirect for URL restructuring, domain migrations, and enforcing canonical URLs.

HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/new-page

In terms of SEO, a 301 redirect passes link equity (ranking power) from the old URL to the new one. Always use 301 when a page has permanently moved.

302 Found (Temporary Redirect)

The resource is temporarily available at a different URL. Unlike 301, search engines will continue to index the original URL. Use this for temporary maintenance pages, A/B tests, or geolocation-based routing.

304 Not Modified

The resource hasn't changed since the client last requested it (based on If-Modified-Since or If-None-Match headers). The server returns no body — the client should use its cached version. This is a key part of HTTP caching that reduces bandwidth and improves load times.

307 Temporary Redirect

Similar to 302, but guarantees that the HTTP method will not change. If the original request was a POST, the redirected request will also be a POST. Use this when redirecting form submissions or API calls.

308 Permanent Redirect

Similar to 301, but guarantees that the HTTP method will not change. This is the strict equivalent of 307 for permanent redirects.

4xx Client Error Responses

Client errors indicate that the problem is with the request itself. The client sent something the server cannot or will not process. These are the status codes you'll encounter most while developing and debugging.

400 Bad Request

The server cannot process the request due to malformed syntax, invalid parameters, or missing required fields. This is the generic "you sent something wrong" response.

// Common causes of 400 errors:
// - Invalid JSON in the request body
// - Missing required fields
// - Wrong data types (sending a string where a number is expected)
// - Exceeding size limits

POST /api/users
Content-Type: application/json

{"name": 123}  // name should be a string

---

HTTP/1.1 400 Bad Request
{"error": "Validation failed", "details": ["name must be a string"]}

401 Unauthorized

The request requires authentication, but none was provided or the credentials are invalid. Despite the name, this is about authentication (who are you?), not authorization (what are you allowed to do?). The response should include a WWW-Authenticate header describing the expected authentication scheme.

403 Forbidden

The server understood the request but refuses to fulfill it. Unlike 401, authentication won't help — the client is identified but doesn't have permission. This is about authorization — the server knows who you are, but you're not allowed to access this resource.

404 Not Found

The most famous status code. The server cannot find the requested resource. This can mean the URL is wrong, the resource was deleted, or it never existed. In APIs, a 404 is also appropriate when a specific record is not found (e.g., GET /api/users/9999 when user 9999 doesn't exist).

A well-designed 404 page is a UX opportunity. Include a search bar, navigation links, and a friendly message. Don't just show a bare "Not Found" text.

405 Method Not Allowed

The HTTP method used is not supported for this resource. For example, trying to DELETE a resource that only supports GET and POST. The response should include an Allow header listing the permitted methods.

409 Conflict

The request conflicts with the current state of the resource. Common in APIs when trying to create a duplicate resource (e.g., a user with an email that already exists) or when there are concurrent modification conflicts.

422 Unprocessable Entity

The server understands the content type and the syntax is correct, but the data is semantically invalid. This is popular in APIs for validation errors — the JSON is valid JSON, but the values don't pass business logic validation.

429 Too Many Requests

Rate limiting in action. The client has sent too many requests in a given time window. The response should include a Retry-After header indicating how long the client should wait before trying again. When building API clients, always handle 429 by implementing exponential backoff.

HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json

{"error": "Rate limit exceeded", "retryAfter": 60}

5xx Server Error Responses

Server errors indicate that the request was valid, but the server failed to process it. These point to bugs, infrastructure issues, or temporary outages on the server side.

500 Internal Server Error

The generic server-side error. Something went wrong, and the server doesn't have a more specific error code. In production, never expose detailed error messages or stack traces in 500 responses — log them server-side and return a generic message to the client.

// ❌ Bad: exposing internals
{"error": "TypeError: Cannot read property 'id' of null at /app/src/users.js:42"}

// ✅ Good: generic message with a tracking ID
{"error": "Internal server error", "requestId": "abc-123-def"}

502 Bad Gateway

The server acting as a gateway or proxy received an invalid response from the upstream server. Common when a reverse proxy (Nginx, AWS ALB) cannot reach the application server. Check if your backend process is running and healthy.

503 Service Unavailable

The server is temporarily unable to handle the request, usually due to maintenance or overloading. Unlike 500, this implies the issue is temporary. The response should include a Retry-After header when possible.

504 Gateway Timeout

The gateway or proxy server didn't receive a timely response from the upstream server. This often indicates a long-running database query, an unresponsive external API, or misconfigured timeout settings. Check your upstream service's health and consider increasing timeout thresholds or optimizing slow operations.

Status Codes in REST API Design

Choosing the right status codes is a fundamental part of API design. Here are best practices:

// A well-designed API error response
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "error": "Validation failed",
  "details": [
    {"field": "email", "message": "must be a valid email address"},
    {"field": "age", "message": "must be between 0 and 150"}
  ]
}

Debugging HTTP Status Codes

When you encounter unexpected status codes, here's a systematic debugging approach:

  1. Read the response body — most APIs include error details in the body. Don't just look at the status code.
  2. Check the request — verify the URL, HTTP method, headers (especially Content-Type and Authorization), and request body.
  3. Use browser DevTools — the Network tab shows the full request/response cycle with headers, timing, and body content.
  4. Check server logs — for 5xx errors, the server logs will contain the actual error message and stack trace.
  5. Test with curl — isolate the request from your application code to rule out client-side issues.
# Debug a failing request with curl
curl -v -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-token" \
  -d '{"name": "Alice", "email": "alice@example.com"}'

The -v (verbose) flag shows the full request and response headers, which is invaluable for debugging authentication, redirect, and CORS issues.

Quick Reference Table

Here are the status codes you'll encounter most often, grouped by scenario:

Wrapping Up

HTTP status codes are the language of the web. Every developer should know the common codes by heart and understand the five categories. When designing APIs, choose status codes carefully — they are part of your API's contract with its consumers. When debugging, always read the full response (not just the status code) and use tools like browser DevTools and curl to inspect the complete request/response cycle. For a printable reference, check out our HTTP Status Codes Cheatsheet.

Try These Tools

Related Articles

Enjoy this article? Buy us a coffee to support free tools and guides.