← Back to Blog

HTTP Status Codes Explained: The Complete Developer Reference

March 9, 2026 10 min read By CodeTidy Team

HTTP status codes are three-digit numbers that servers send back with every response. Knowing what they mean is fundamental to building and debugging web applications. This guide covers every status code you're likely to encounter, with practical context about when to use each one.

The Five Categories

RangeCategoryMeaning
1xxInformationalRequest received, continuing process
2xxSuccessRequest successfully received and processed
3xxRedirectionFurther action needed to complete request
4xxClient ErrorThe request contains an error on the client side
5xxServer ErrorThe server failed to process a valid request

2xx Success Codes

200 OK

The request succeeded. The meaning depends on the HTTP method:

  • GET: Resource fetched and sent in the response body
  • POST: Action completed, result in response body
  • PUT/PATCH: Resource updated successfully

201 Created

A new resource was successfully created. Always use this instead of 200 for POST requests that create resources. Include a Location header pointing to the new resource:

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

{"id": 12345, "name": "Alice"}

204 No Content

The request succeeded but there's no response body. Common for DELETE operations and PUT updates where the client doesn't need the updated resource back:

DELETE /api/users/12345
→ 204 No Content

206 Partial Content

The server is delivering only part of the resource due to a Range header. Used for resumable downloads and video streaming.

3xx Redirection Codes

301 Moved Permanently

The resource has permanently moved to a new URL. Search engines transfer ranking to the new URL. Browsers cache this redirect aggressively:

# Old URL permanently redirects to new URL
/old-page → 301 → /new-page

302 Found (Temporary Redirect)

The resource is temporarily at a different URL. Search engines keep the original URL indexed. Use for maintenance pages or A/B testing.

304 Not Modified

The resource hasn't changed since the last request. The server sends no body — the client uses its cached version. This is triggered by If-Modified-Since or If-None-Match headers:

# Client sends:
GET /api/data
If-None-Match: "abc123"

# Server responds (data unchanged):
304 Not Modified

307 Temporary Redirect

Like 302, but guarantees the HTTP method won't change. A POST request redirected with 307 remains a POST. Use 307 instead of 302 for non-GET requests.

308 Permanent Redirect

Like 301, but guarantees the HTTP method won't change. Use 308 instead of 301 when redirecting POST/PUT/DELETE requests permanently.

4xx Client Error Codes

400 Bad Request

The server can't process the request due to a client error — malformed syntax, invalid parameters, or bad JSON formatting. Always include a descriptive error message:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "validation_error",
  "message": "Email address is required",
  "field": "email"
}

401 Unauthorized

Authentication is required but was not provided or is invalid. Despite the name, this is about authentication (who you are), not authorization (what you're allowed to do). The server should include a WWW-Authenticate header indicating the auth scheme. Common when a JWT token is missing or expired.

403 Forbidden

The server understood the request but refuses to authorize it. The client is authenticated but doesn't have permission. Unlike 401, re-authenticating won't help:

  • 401: "I don't know who you are. Please log in."
  • 403: "I know who you are. You're not allowed to do this."

404 Not Found

The requested resource doesn't exist. The most well-known status code. Can also be used intentionally to hide the existence of a resource from unauthorized users (instead of 403).

405 Method Not Allowed

The HTTP method isn't supported for this resource. For example, trying to DELETE a read-only resource. Include an Allow header listing valid methods:

HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS

409 Conflict

The request conflicts with the current state of the resource. Common for duplicate creation attempts or version conflicts:

# Trying to create a user with an existing email
POST /api/users
→ 409 Conflict
{"error": "A user with this email already exists"}

422 Unprocessable Entity

The request syntax is valid (unlike 400) but the content is semantically incorrect. Common in form validation when the JSON structure is correct but the values are invalid:

# Valid JSON, but age can't be negative
{"name": "Alice", "age": -5}
→ 422 Unprocessable Entity

429 Too Many Requests

The client has sent too many requests (rate limiting). Include a Retry-After header telling the client when to retry:

HTTP/1.1 429 Too Many Requests
Retry-After: 60

{"error": "Rate limit exceeded. Try again in 60 seconds."}

5xx Server Error Codes

500 Internal Server Error

The generic server error. Something went wrong on the server side. In production, never expose stack traces or internal details to clients — log them server-side and return a generic message:

// BAD — exposes internals
{"error": "NullPointerException at UserService.java:42"}

// GOOD — safe for clients
{"error": "internal_error", "message": "Something went wrong. Please try again."}

502 Bad Gateway

The server (acting as a proxy or gateway) received an invalid response from an upstream server. Common with reverse proxies (Nginx, Cloudflare) when the backend application crashes or is unreachable.

503 Service Unavailable

The server is temporarily unable to handle the request — usually due to maintenance or overload. Include a Retry-After header:

HTTP/1.1 503 Service Unavailable
Retry-After: 300

{"error": "Server is under maintenance. Back in ~5 minutes."}

504 Gateway Timeout

The proxy/gateway server didn't receive a timely response from the upstream server. Common when backend processing takes too long (slow database queries, external API timeouts).

Choosing the Right Status Code for APIs

OperationSuccess CodeCommon Error Codes
GET /resource200404, 401, 403
POST /resource (create)201400, 409, 422
PUT /resource/:id (update)200 or 204400, 404, 409, 422
PATCH /resource/:id200400, 404, 422
DELETE /resource/:id204404, 403
List with no results200 (empty array)
Authentication failure401
Insufficient permissions403
Rate limited429

Handling Status Codes in JavaScript

async function fetchUser(id) {
  const response = await fetch(`/api/users/${id}`);

  switch (response.status) {
    case 200:
      return await response.json();
    case 404:
      throw new Error('User not found');
    case 401:
      // Redirect to login
      window.location.href = '/login';
      return;
    case 429:
      const retryAfter = response.headers.get('Retry-After');
      throw new Error(`Rate limited. Retry after ${retryAfter}s`);
    default:
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }
  }
}

When testing API responses, use our Curl Converter to translate curl commands into JavaScript fetch calls, or format the JSON response bodies with our JSON Formatter.

Less Common But Useful Codes

CodeNameUse Case
202AcceptedRequest accepted for async processing (not completed yet)
301Moved PermanentlySEO-safe permanent URL redirect
410GoneResource permanently deleted (unlike 404, confirms it existed)
413Payload Too LargeRequest body exceeds server limits
415Unsupported Media TypeServer doesn't support the Content-Type
418I'm a TeapotApril Fools' joke from 1998 — still in the spec
451Unavailable for Legal ReasonsCensorship or legal takedown

Need a quick reference while debugging? Our HTTP Status Code Explorer lets you search any status code and instantly see its meaning, common causes, and how to handle it in your code.

Drop file to load