Development2024-03-30

HTTP Status Codes Explained: What Every 404, 301, and 500 Really Means

From 200 OK to 503 Service Unavailable, HTTP status codes tell the story of every web request. This guide decodes every important status code with real-world examples and debugging tips.

#http#status-codes#web-development#api#debugging

HTTP Status Codes Explained: What Every 404, 301, and 500 Really Means

Every time you load a webpage, your browser makes dozens of HTTP requests. Each response includes a three-digit status code that tells you what happened. Most people only know 404 — but understanding all the codes makes you a better developer, debugger, and API designer.

This guide covers every status code you'll encounter in practice, with real-world examples, debugging tips, and how they impact SEO.

The Five Categories

Range Category Meaning
1xx Informational Request received, continuing
2xx Success Request succeeded
3xx Redirection Further action needed
4xx Client Error You made a mistake
5xx Server Error The server made a mistake

2xx Success — All Good

200 OK

The standard success response.

GET /api/users → 200 OK

201 Created

A new resource was successfully created.

POST /api/users → 201 Created

204 No Content

Success, but there's nothing to return.

DELETE /api/users/123 → 204 No Content

Quick Reference

Code Meaning When Used
200 OK GET, PUT success
201 Created POST success
202 Accepted Async processing started
204 No Content DELETE success

3xx Redirection — Go Somewhere Else

301 Moved Permanently

The resource has a new permanent URL. Search engines transfer SEO value to the new URL.

GET /old-page → 301 Moved Permanently
Location: /new-page

SEO impact: Link equity passes to the new URL. Use this when permanently moving content.

302 Found (Temporary Redirect)

The resource is temporarily at a different URL.

GET /dashboard → 302 Found
Location: /login

SEO impact: Link equity does NOT pass. Use for temporary redirects.

304 Not Modified

The cached version is still valid. No data transferred — saves bandwidth.

GET /styles.css
If-None-Match: "abc123"
→ 304 Not Modified

307 vs 308

Code Method Preserved? Permanent?
307 ✅ Yes ❌ No (temporary)
308 ✅ Yes ✅ Yes (permanent)

Note: 301 and 302 may change POST to GET. Use 307/308 if you need to preserve the HTTP method.

4xx Client Error — Your Fault

400 Bad Request

The server can't understand your request.

Common causes:

  • Malformed JSON body
  • Missing required parameters
  • Invalid data types
// POST /api/users
{"name": 123}  // name should be a string
→ 400 Bad Request

401 Unauthorized

You need to authenticate first.

GET /api/profile
→ 401 Unauthorized
WWW-Authenticate: Bearer realm="api"

Note: Despite the name, it means "unauthenticated" — you haven't proven who you are.

403 Forbidden

You're authenticated, but you don't have permission.

GET /api/admin/users
Authorization: Bearer user-token
→ 403 Forbidden

401 vs 403:

  • 401 = "I don't know who you are" (login first)
  • 403 = "I know who you are, but you can't access this"

404 Not Found

The resource doesn't exist.

GET /api/users/999
→ 404 Not Found

SEO tip: Don't redirect all 404s to the homepage. Google treats this as a soft 404. Either return a real 404 with helpful content, or redirect only if there's a relevant replacement page.

405 Method Not Allowed

The URL exists, but this HTTP method isn't supported.

DELETE /api/users/123
→ 405 Method Not Allowed
Allow: GET, POST

429 Too Many Requests

You've hit the rate limit.

GET /api/data
→ 429 Too Many Requests
Retry-After: 60

4xx Quick Reference

Code Meaning Fix
400 Bad Request Check request format
401 Unauthorized Add authentication
403 Forbidden Check permissions
404 Not Found Check the URL
405 Method Not Allowed Use correct HTTP method
408 Request Timeout Retry with backoff
413 Payload Too Large Reduce request size
429 Too Many Requests Slow down, respect rate limits

5xx Server Error — Server's Fault

500 Internal Server Error

Something went wrong on the server, but the server can't be more specific.

Common causes:

  • Unhandled exceptions
  • Database connection failures
  • Configuration errors

502 Bad Gateway

The server acting as a gateway received an invalid response from upstream.

Common causes:

  • Backend server crashed
  • Load balancer misconfiguration
  • DNS issues

503 Service Unavailable

The server is temporarily down (overloaded or maintenance).

→ 503 Service Unavailable
Retry-After: 3600

504 Gateway Timeout

The upstream server didn't respond in time.

Common causes:

  • Slow database queries
  • External API timeouts
  • Network issues between servers

5xx Quick Reference

Code Meaning Who to Blame
500 Internal Server Error Backend code
502 Bad Gateway Upstream server
503 Service Unavailable Overloaded/maintenance
504 Gateway Timeout Slow upstream

Handling Status Codes in JavaScript

When working with the Fetch API, status codes aren't thrown as errors — you must check them manually:

// Basic error handling
async function fetchData(url) {
  const response = await fetch(url);

  if (!response.ok) {
    // response.ok is true for 200-299
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }

  return response.json();
}

// Detailed error handling by status
async function apiCall(url, options = {}) {
  const response = await fetch(url, options);

  switch (response.status) {
    case 200:
    case 201:
      return await response.json();
    case 400:
      throw new Error('Invalid request — check your input');
    case 401:
      throw new Error('Please log in');
    case 403:
      throw new Error('You don\'t have permission');
    case 404:
      throw new Error('Resource not found');
    case 429:
      const retryAfter = response.headers.get('Retry-After');
      throw new Error(`Rate limited. Retry after ${retryAfter}s`);
    case 500:
      throw new Error('Server error — try again later');
    case 503:
      throw new Error('Service unavailable — try again later');
    default:
      throw new Error(`Unexpected status: ${response.status}`);
  }
}

// Retry with exponential backoff for 5xx errors
async function fetchWithRetry(url, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url);
      if (response.status >= 500 && i < maxRetries - 1) {
        await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
        continue;
      }
      return response;
    } catch (err) {
      if (i === maxRetries - 1) throw err;
      await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
    }
  }
}

API Design: Choosing the Right Status Code

When building APIs, choosing correct status codes matters for client experience:

For successful operations:

  • 200 for GET/PUT that returns data
  • 201 for POST that creates a resource
  • 204 for DELETE or operations with no response body

For errors, be specific:

  • 400 for validation errors (include field-level details)
  • 401 when no authentication is provided
  • 403 when authenticated but lacking permission
  • 404 when the resource doesn't exist
  • 409 for conflicts (e.g., duplicate email)
  • 422 for semantically invalid data
  • 429 for rate limiting (include Retry-After header)
  • 500 only for truly unexpected errors

Response body for errors:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input data",
    "details": [
      { "field": "email", "message": "Must be a valid email address" },
      { "field": "age", "message": "Must be a positive number" }
    ]
  }
}

Status Codes and SEO

Code SEO Impact
200 ✅ Indexed normally
301 ✅ Link equity transferred
302 ⚠️ Temporary, no equity transfer
404 ❌ Removed from index eventually
410 ❌ Removed from index faster
5xx ❌ Crawling paused if persistent

Debugging Status Codes

Browser DevTools

  1. Open DevTools (F12)
  2. Go to Network tab
  3. Reload the page
  4. Click any request to see its status code and response

cURL

# See status code only
curl -s -o /dev/null -w "%{http_code}" https://example.com

# See headers
curl -I https://example.com

Try It Yourself

Need to check what status code a URL returns? Our HTTP Status Code Checker lets you test any URL and see its response code, headers, and redirect chain.

Summary

  • 2xx = success, everything worked
  • 3xx = redirect, go somewhere else
  • 4xx = client error, fix your request
  • 5xx = server error, not your fault
  • 301 for permanent moves (SEO-friendly)
  • 404 for truly missing pages
  • Always check the Network tab when debugging
  • Handle errors gracefully in your JavaScript — check response.ok
  • Be specific in API error responses — help clients fix their requests

HTTP status codes are the universal language of the web. Understanding them makes you a better developer, debugger, and SEO practitioner.

Need to check what status code a URL returns? Our HTTP Status Code Checker lets you test any URL and see its response code, headers, and redirect chain.

🛠

Try It Yourself

Put what you've learned into practice with our free online tools.