HTTP

Guide

HTTP Status Codes: A Complete Reference Guide

Learn how HTTP status code classes (1xx-5xx) work and when to use each code. Master informational, success, redirect, client error, and server error responses.

10 min read beginner Try in Playground

TL;DR: Status codes indicate request outcomes: 2xx success, 3xx redirect, 4xx client error, 5xx server error. Choose the right code to help browsers, users, and developers understand what happened.

HTTP status codes are three-digit numbers that servers send to communicate the outcome of client requests. They’re the primary mechanism for indicating success, failure, or the need for additional action. Understanding status codes is essential for building robust web applications, debugging issues, and creating intuitive user experiences.

This guide provides a comprehensive overview of all five status code classes, practical decision-making frameworks, and real-world implementation patterns that will help you choose the right status code for every situation.

Introduction

Every HTTP response includes a status code that tells the client exactly what happened with their request. These codes are standardized across the web, ensuring consistent behavior between different servers, browsers, and applications. The three-digit format isn’t arbitrary—it creates a hierarchical system where the first digit indicates the general category of response.

Status codes serve multiple audiences: they help browsers decide how to handle responses, inform developers about API behavior, guide user interface decisions, and enable automated systems to react appropriately to different outcomes. Choosing the correct status code isn’t just about technical accuracy—it directly impacts user experience, SEO performance, and system reliability.

The five classes (1xx through 5xx) each serve distinct purposes in the HTTP communication protocol. Understanding when and how to use each class enables you to build more predictable, debuggable, and user-friendly applications.

The Five Status Code Classes

1xx Informational Responses

Informational status codes indicate that the request has been received and the server is continuing to process it. These are interim responses that don’t complete the request-response cycle.

Key Characteristics:

  • Provisional responses during request processing
  • Client should wait for final response
  • Rarely used in typical web applications
  • More common in streaming and long-running operations

Common 1xx Codes:

100 Continue

HTTP/1.1 100 Continue

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

{"status": "upload complete"}
```text

Used when client sends `Expect: 100-continue` header before sending large request body.

**101 Switching Protocols**

```http
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

Indicates protocol upgrade (HTTP to WebSocket, HTTP/1.1 to HTTP/2).

102 Processing (WebDAV)

HTTP/1.1 102 Processing
```text

Informs client that server is still processing the request (prevents timeout).

### 2xx Success Responses

Success codes indicate that the client's request was received, understood, and successfully processed. The specific 2xx code provides details about what type of success occurred.

**Decision Framework for 2xx Codes:**

```text
Request successful?
├─ Yes → Was resource created?
│  ├─ Yes → 201 Created
│  └─ No → Was content returned?
│     ├─ Yes → 200 OK
│     ├─ No content → 204 No Content
│     └─ Accepted for processing → 202 Accepted
└─ No → Use 4xx or 5xx
```text

**Common 2xx Codes:**

**200 OK - Standard Success**

```http
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 156

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

Most common success response. Request succeeded and response contains requested data.

201 Created - Resource Creation

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

{
  "id": 123,
  "name": "Charlie",
  "createdAt": "2026-01-18T10:30:00Z"
}
```text

New resource was successfully created. Include `Location` header pointing to new resource.

**202 Accepted - Asynchronous Processing**

```http
HTTP/1.1 202 Accepted
Content-Type: application/json

{
  "jobId": "job_abc123",
  "status": "processing",
  "estimatedCompletion": "2026-01-18T10:35:00Z"
}

Request accepted but processing not complete. Common for background jobs.

204 No Content - Successful with No Response Body

HTTP/1.1 204 No Content
Cache-Control: no-cache
```nginx

Request succeeded but no content to return. Common for DELETE operations or updates.

### 3xx Redirection Responses

Redirection codes indicate that additional action is needed to complete the request. They guide clients to the correct resource location or inform them about resource status changes.

**Redirection Decision Tree:**

```text
Resource moved?
├─ Permanently → 301 Moved Permanently
├─ Temporarily → 302 Found or 307 Temporary Redirect
├─ Not modified → 304 Not Modified
└─ Multiple choices → 300 Multiple Choices
```text

**Common 3xx Codes:**

**301 Moved Permanently - Permanent Redirect**

```http
HTTP/1.1 301 Moved Permanently
Location: https://newdomain.com/api/users
Cache-Control: max-age=31536000

<html>
<body>Resource has moved to <a href="https://newdomain.com/api/users">new location</a></body>
</html>

Resource permanently moved. Search engines update their indexes.

302 Found - Temporary Redirect

HTTP/1.1 302 Found
Location: /login?redirect=/dashboard
Cache-Control: no-cache
```text

Resource temporarily at different location. Original URL remains valid.

**304 Not Modified - Cached Content Valid**

```http
HTTP/1.1 304 Not Modified
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Cache-Control: max-age=300

Client’s cached version is still current. No response body needed.

307 Temporary Redirect - Method Preserved

HTTP/1.1 307 Temporary Redirect
Location: /api/v2/users
```text

Like 302 but guarantees HTTP method won't change during redirect.

**308 Permanent Redirect - Method Preserved**

```http
HTTP/1.1 308 Permanent Redirect
Location: https://api.example.com/v2/users

Like 301 but guarantees HTTP method won’t change during redirect.

4xx Client Error Responses

Client error codes indicate that the request contains bad syntax, cannot be fulfilled, or lacks proper authorization. These errors suggest the client needs to modify their request.

Client Error Decision Framework:

Request valid?
├─ No → Malformed syntax → 400 Bad Request
├─ Yes → Authorized?
│  ├─ No → Authentication required → 401 Unauthorized
│  ├─ Forbidden → 403 Forbidden
│  └─ Yes → Resource exists?
│     ├─ No → 404 Not Found
│     ├─ Yes → Method allowed?
│     │  ├─ No → 405 Method Not Allowed
│     │  └─ Yes → Content acceptable?
│     │     ├─ No → 406 Not Acceptable
│     │     └─ Yes → Rate limited?
│     │        ├─ Yes → 429 Too Many Requests
│     │        └─ No → Process request
└─ Validation failed → 422 Unprocessable Entity

Common 4xx Codes:

400 Bad Request - Malformed Request

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

{
  "error": "Invalid JSON syntax",
  "details": "Unexpected token '}' at position 45",
  "code": "INVALID_JSON"
}
```text

Request syntax is invalid or cannot be understood.

**401 Unauthorized - Authentication Required**

```http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
Content-Type: application/json

{
  "error": "Authentication required",
  "message": "Please provide a valid access token"
}

Request lacks valid authentication credentials.

403 Forbidden - Access Denied

HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "error": "Insufficient permissions",
  "message": "Admin access required for this operation"
}
```text

Server understood request but refuses to authorize it.

**404 Not Found - Resource Missing**

```http
HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "error": "Resource not found",
  "message": "User with ID 999 does not exist"
}

Requested resource could not be found on the server.

422 Unprocessable Entity - Validation Failed

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "error": "Validation failed",
  "details": [
    {"field": "email", "message": "Invalid email format"},
    {"field": "age", "message": "Must be between 18 and 120"}
  ]
}
```text

Request syntax is correct but contains semantic errors.

**429 Too Many Requests - Rate Limited**

```http
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1642518000

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

Client has sent too many requests in a given time period.

5xx Server Error Responses

Server error codes indicate that the server failed to fulfill a valid request. These errors suggest problems on the server side that the client cannot fix by modifying their request.

Server Error Decision Framework:

Server error occurred?
├─ Generic error → 500 Internal Server Error
├─ Feature not implemented → 501 Not Implemented
├─ Upstream server error → 502 Bad Gateway
├─ Service unavailable → 503 Service Unavailable
├─ Upstream timeout → 504 Gateway Timeout
└─ HTTP version unsupported → 505 HTTP Version Not Supported

Common 5xx Codes:

500 Internal Server Error - Generic Server Error

HTTP/1.1 500 Internal Server Error
Content-Type: application/json

{
  "error": "Internal server error",
  "message": "An unexpected error occurred",
  "requestId": "req_abc123"
}
```text

Generic server error when specific error type is unknown.

**502 Bad Gateway - Upstream Server Error**

```http
HTTP/1.1 502 Bad Gateway
Content-Type: application/json

{
  "error": "Bad gateway",
  "message": "Database connection failed"
}

Server acting as gateway received invalid response from upstream server.

503 Service Unavailable - Temporary Unavailability

HTTP/1.1 503 Service Unavailable
Retry-After: 120
Content-Type: application/json

{
  "error": "Service unavailable",
  "message": "Server is temporarily overloaded"
}
```text

Server temporarily cannot handle request due to maintenance or overload.

**504 Gateway Timeout - Upstream Timeout**

```http
HTTP/1.1 504 Gateway Timeout
Content-Type: application/json

{
  "error": "Gateway timeout",
  "message": "Upstream server did not respond in time"
}

Server acting as gateway did not receive timely response from upstream.

Status Code Selection Patterns

RESTful API Patterns

Resource Creation:

// POST /api/users
if (validationErrors.length > 0) {
  return res.status(422).json({ errors: validationErrors })
}

if (userAlreadyExists) {
  return res.status(409).json({ error: 'User already exists' })
}

const user = await createUser(userData)
return res.status(201).json(user)
```javascript

**Resource Retrieval:**

```javascript
// GET /api/users/:id
const user = await findUser(userId)

if (!user) {
  return res.status(404).json({ error: 'User not found' })
}

return res.status(200).json(user)

Resource Updates:

// PUT /api/users/:id
const user = await findUser(userId)

if (!user) {
  return res.status(404).json({ error: 'User not found' })
}

if (validationErrors.length > 0) {
  return res.status(422).json({ errors: validationErrors })
}

const updatedUser = await updateUser(userId, userData)
return res.status(200).json(updatedUser)
```javascript

**Resource Deletion:**

```javascript
// DELETE /api/users/:id
const user = await findUser(userId)

if (!user) {
  return res.status(404).json({ error: 'User not found' })
}

await deleteUser(userId)
return res.status(204).send()

Error Handling Patterns

Graceful Degradation:

try {
  const result = await processRequest(data)
  return res.status(200).json(result)
} catch (error) {
  if (error instanceof ValidationError) {
    return res.status(422).json({ error: error.message })
  }

  if (error instanceof NotFoundError) {
    return res.status(404).json({ error: error.message })
  }

  // Log unexpected errors
  logger.error('Unexpected error:', error)
  return res.status(500).json({
    error: 'Internal server error',
    requestId: req.id
  })
}
```javascript

### Authentication and Authorization Patterns

**Authentication Flow:**

```javascript
// Check if token exists
if (!token) {
  return res.status(401).json({
    error: 'Authentication required',
    message: 'Please provide an access token'
  })
}

// Validate token
const user = await validateToken(token)
if (!user) {
  return res.status(401).json({
    error: 'Invalid token',
    message: 'Please log in again'
  })
}

// Check permissions
if (!user.hasPermission(requiredPermission)) {
  return res.status(403).json({
    error: 'Insufficient permissions',
    message: 'Admin access required'
  })
}

Best Practices

Consistency Guidelines

Use Standard Codes:

  • Stick to well-known status codes
  • Avoid obscure codes unless specifically needed
  • Document any non-standard usage

Provide Helpful Error Messages:

{
  "error": "Validation failed",
  "message": "The request contains invalid data",
  "details": [
    {
      "field": "email",
      "code": "INVALID_FORMAT",
      "message": "Email must be a valid email address"
    }
  ],
  "requestId": "req_abc123"
}
```javascript

### Client-Side Handling

**Status Code Categories:**

```javascript
function handleResponse(response) {
  const status = response.status

  if (status >= 200 && status < 300) {
    // Success - process response data
    return response.json()
  }

  if (status >= 300 && status < 400) {
    // Redirection - follow redirect or update URL
    window.location.href = response.headers.get('Location')
  }

  if (status >= 400 && status < 500) {
    // Client error - show user-friendly error message
    throw new ClientError('Please check your request and try again')
  }

  if (status >= 500) {
    // Server error - show generic error, maybe retry
    throw new ServerError('Something went wrong. Please try again later')
  }
}

Monitoring and Debugging

Status Code Metrics:

// Track status code distribution
const statusCodeCounts = {
  '2xx': 0, // Success rate
  '3xx': 0, // Redirect rate
  '4xx': 0, // Client error rate
  '5xx': 0 // Server error rate
}

// Alert on high error rates
if (statusCodeCounts['5xx'] / totalRequests > 0.01) {
  alert('High server error rate detected')
}
```text

## Common Anti-Patterns

### Incorrect Status Code Usage

**Don't Use 200 for Errors:**

```javascript
// Bad: Error with 200 status
res.status(200).json({
  success: false,
  error: 'User not found'
})

// Good: Proper error status
res.status(404).json({
  error: 'User not found'
})

Don’t Use Generic Codes:

// Bad: Generic 400 for validation errors
res.status(400).json({ error: 'Invalid data' })

// Good: Specific 422 for validation errors
res.status(422).json({
  error: 'Validation failed',
  details: validationErrors
})
```text

### Missing Error Context

**Provide Actionable Information:**

```javascript
// Bad: Vague error message
res.status(403).json({ error: 'Forbidden' })

// Good: Specific guidance
res.status(403).json({
  error: 'Insufficient permissions',
  message: 'This operation requires admin privileges',
  requiredRole: 'admin',
  currentRole: 'user'
})

HTTP status codes work in conjunction with other HTTP concepts:

Understanding status codes is fundamental to HTTP communication. They provide a standardized way to communicate request outcomes, enable proper error handling, and help create predictable, user-friendly applications. Start with the most common codes (200, 404, 500) and gradually incorporate more specific codes as your application’s needs become more sophisticated.

Frequently Asked Questions

What are HTTP status codes?

Status codes are 3-digit numbers indicating the result of an HTTP request. They are grouped: 1xx informational, 2xx success, 3xx redirect, 4xx client error, 5xx server error.

What are the most common status codes?

200 OK (success), 301/302 (redirect), 400 (bad request), 401 (unauthorized), 403 (forbidden), 404 (not found), 500 (server error), 503 (service unavailable).

What is the difference between 4xx and 5xx errors?

4xx errors are client errors (bad request, not found). 5xx errors are server errors (server crashed, overloaded). 4xx means fix your request; 5xx means wait or contact support.

How do I handle status codes in my application?

Check the status code before processing the response. Handle success (2xx), follow redirects (3xx), show user-friendly errors for 4xx, and retry or alert for 5xx.

Keep Learning