ToolPal
Server rack with blinking lights in a data center

HTTP Status Codes: The Complete Developer Reference (2026)

πŸ“· Thomas Jensen / Pexels

HTTP Status Codes: The Complete Developer Reference (2026)

A practical guide to all HTTP status codes β€” what they mean, when they occur, and how to handle them in your APIs and web apps.

March 23, 202612 min read

HTTP Status Codes Are Not Just Trivia

Every HTTP response carries a three-digit status code. Most developers have them memorized up to a point β€” 200 means good, 404 means missing, 500 means something broke. But the full picture is more interesting and more useful than that.

Understanding HTTP status codes well means writing better APIs, debugging faster, and making smarter decisions about redirects, caching, and error handling. This guide is a practical reference, not an RFC dump. We'll cover what matters, why it matters, and how to apply it.

If you want an interactive reference while you're working, check out the free HTTP Status Codes tool β€” look up any code instantly with descriptions and usage notes.


The Five Categories: A Mental Model

HTTP status codes are grouped into five classes. The first digit tells you which category you're in:

RangeCategoryThe vibe
1xxInformational"Hold on, still working..."
2xxSuccess"Here you go."
3xxRedirection"It's over there."
4xxClient Error"You messed up."
5xxServer Error"We messed up."

This taxonomy is worth internalizing. When you see an unfamiliar status code, the first digit alone tells you whether to look at your request or the server.


1xx: Informational

These are rarely seen in application code but worth knowing:

100 Continue β€” The server received the request headers and the client should proceed with the body. Used to avoid sending large bodies when the server might reject the request anyway (e.g., based on auth headers).

101 Switching Protocols β€” The server is switching from HTTP to another protocol, typically WebSocket. You'll see this in the browser's network tab when a WebSocket connection is established.

103 Early Hints β€” A newer one, useful for performance. The server sends resource hints (like preload links) before the final response, letting the browser start fetching assets earlier.


2xx: Success Codes

These are what you want. But they're not all the same.

200 OK

The default success. The request worked, here's the response body. Use it for GET requests, and generally for POST/PUT when you're returning the updated resource.

curl -I https://api.example.com/users/42
# HTTP/2 200
# content-type: application/json

201 Created

Used after a resource is successfully created β€” typically in response to a POST. Best practice is to include a Location header pointing to the new resource.

curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@example.com"}'
# HTTP/2 201
# Location: /users/43

A lot of APIs return 200 for everything. That works, but it's lazy. Returning 201 with a Location header gives clients a cleaner contract β€” they know a new thing exists and where to find it.

204 No Content

The request succeeded, but there's nothing to return. Perfect for DELETE operations, or PUT/PATCH when you don't need to send back the updated resource.

curl -X DELETE https://api.example.com/users/42
# HTTP/2 204
# (empty body)

Never return a body with 204 β€” clients don't expect one and some will ignore it. If you need to return data after deletion (like a count of remaining items), use 200 instead.

202 Accepted

The request was accepted for processing, but processing isn't complete yet. This is the right code for async operations β€” you've queued the job, but it might take a while.

{
  "status": "accepted",
  "jobId": "job_abc123",
  "checkUrl": "/jobs/job_abc123"
}

206 Partial Content

Used when serving a range of a resource (video streaming, download resumption). The client requests a range via the Range header, and the server returns the slice with 206.


3xx: Redirects

Redirects are where developers make the most costly mistakes β€” not because they're hard to understand, but because the SEO and caching implications are easy to miss.

301 Moved Permanently

The resource has permanently moved to a new URL. The browser will cache this redirect indefinitely. Search engines transfer link equity (PageRank) to the new URL.

Use 301 when:

  • You're migrating a domain
  • Changing URL structure permanently
  • Consolidating duplicate pages

Be careful: Once a 301 is cached, it's very hard to undo. Browsers may cache it for months. If you're not 100% sure the redirect is permanent, use 302.

302 Found

Temporary redirect. The browser follows it but doesn't cache it permanently. SEO value stays with the original URL.

Use 302 for:

  • A/B testing (temporarily showing a variant)
  • Maintenance pages
  • Login redirects (redirect to login, then back)

307 Temporary Redirect

Functionally similar to 302, but with a stricter guarantee: the method and body must not change. A POST redirected via 307 must be re-sent as POST to the new URL. Useful in REST APIs where method preservation matters.

308 Permanent Redirect

Like 301, but method-preserving. The permanent version of 307. Less common but useful for APIs that need to maintain request semantics across URL changes.

304 Not Modified

The client sent a conditional GET (with If-None-Match or If-Modified-Since), and the cached version is still valid. The server sends no body β€” just the status. This is how HTTP caching works efficiently.


4xx: Client Errors

The client sent something wrong. Here's where most API debugging happens.

400 Bad Request

A catch-all for malformed requests β€” missing required fields, invalid JSON, type mismatches. Be as specific as possible in the response body.

{
  "error": "validation_failed",
  "details": [
    { "field": "email", "message": "must be a valid email address" },
    { "field": "age", "message": "must be a positive integer" }
  ]
}

401 Unauthorized

The request requires authentication and the client hasn't provided it (or provided invalid credentials). The response should include a WWW-Authenticate header indicating how to authenticate.

Despite the name "Unauthorized," this code is really about authentication, not authorization.

403 Forbidden

The client is authenticated but doesn't have permission to access the resource. The server knows who you are; it just won't let you in.

This distinction matters:

  • Getting someone else's private data β†’ 403
  • Accessing the API without a token β†’ 401
  • Accessing an endpoint your subscription doesn't cover β†’ 403

404 Not Found

The resource doesn't exist. One nuance: some APIs return 404 when the user doesn't have permission to see a resource, to avoid revealing its existence. This is legitimate for security-sensitive resources (like user accounts that shouldn't be enumerated).

405 Method Not Allowed

The endpoint exists, but not for the method you used. A GET on an endpoint that only accepts POST, for example. Always include the Allow header listing valid methods.

409 Conflict

The request conflicts with the current state of the resource. Classic use cases: trying to create a user with an email that already exists, or updating a resource with a stale version (optimistic locking failure).

410 Gone

Like 404, but definitively β€” the resource existed once and is permanently deleted. Search engines will deindex 410 pages faster than 404s. Useful for content that you've intentionally removed.

422 Unprocessable Entity

The request is syntactically valid (parseable JSON, correct content type) but semantically invalid β€” it violates business rules. Many modern APIs prefer 422 over 400 for validation errors because it's more precise.

The difference between 400 and 422 is subtle but real:

  • 400: "I can't even parse what you sent me"
  • 422: "I parsed it fine, but this doesn't make sense"

429 Too Many Requests

You've been rate-limited. The response should include Retry-After (seconds to wait) and ideally X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers.

curl https://api.example.com/data
# HTTP/2 429
# retry-after: 30
# x-ratelimit-limit: 100
# x-ratelimit-remaining: 0
# x-ratelimit-reset: 1711180800

418 I'm a Teapot

Defined in RFC 2324 as an April Fools' joke (the Hyper Text Coffee Pot Control Protocol). The server refuses to brew coffee because it is a teapot. Somehow it made it into real browser implementations and became a beloved easter egg. Google returns it for certain requests. It's the internet's most beloved useless standard.


5xx: Server Errors

Something went wrong on the server side. The client didn't do anything wrong.

500 Internal Server Error

The generic "something broke" code. Usually means an unhandled exception. Log everything, never expose raw stack traces in responses, and alert on these in production.

502 Bad Gateway

The server was acting as a gateway or proxy and received an invalid response from an upstream server. Common with nginx + Node.js setups when the Node process crashes or times out.

503 Service Unavailable

The server is temporarily unable to handle the request β€” overloaded, or down for maintenance. Should include a Retry-After header. Your load balancer typically returns this when all backend instances are unhealthy.

504 Gateway Timeout

The gateway didn't get a timely response from the upstream server. Classic symptom of a slow database query, an external API that's timing out, or a Lambda function that's hitting its execution limit.

507 Insufficient Storage

The server can't store the representation needed to complete the request. Mostly relevant for WebDAV (file storage APIs) or upload endpoints with quota limits.


HTTP Status Codes in REST API Design

Here's a practical cheat sheet for REST API design decisions:

GET /users β†’ 200 (list), 404 (collection doesn't exist β€” rarely used for lists)

GET /users/ β†’ 200 (found), 404 (not found), 403 (forbidden)

POST /users β†’ 201 (created), 400/422 (validation error), 409 (conflict)

PUT /users/ β†’ 200 (updated with body), 204 (updated no body), 404, 409

PATCH /users/ β†’ 200 or 204, 400/422, 404

DELETE /users/ β†’ 204 (deleted), 404 (not found), 409 (can't delete β€” has dependencies)

Be consistent

The worst APIs are inconsistent ones. Pick a convention for validation errors (400 or 422), pick whether to return the resource after updates (200 or 204), and stick to it everywhere. Document it clearly.

Don't return 200 for everything

Some APIs return HTTP 200 with a body like {"success": false, "error": "not found"}. This breaks client libraries, makes monitoring harder, and ignores a perfectly good standard. Use the right status codes.

Provide useful error bodies

A 400 response with no body is useless. At minimum, return an error code and message:

{
  "error": "INVALID_EMAIL",
  "message": "The email address provided is not valid.",
  "field": "email"
}

Consistent error shapes let client developers write generic error handlers instead of parsing error strings.

Use 404 vs 403 carefully

For sensitive resources, it's sometimes better to return 404 even when the resource exists but the user can't access it. This prevents information leakage β€” an attacker can't determine whether a private account exists by getting a 403 instead of a 404.


Debugging with Status Codes

When you're debugging an API issue, start with the status code:

Got a 4xx? The problem is in the request. Check headers, body, authentication, content type.

Got a 5xx? The problem is on the server. Check logs, upstream dependencies, resource limits.

Got a 200 but wrong data? Now you're in application-logic territory β€” the transport layer is fine.

A quick curl with -I (head only) or -v (verbose) tells you exactly what's happening:

# Just check the status code and headers
curl -I https://api.example.com/endpoint

# Full request/response including headers
curl -v https://api.example.com/endpoint

# With auth header
curl -v -H "Authorization: Bearer your-token" https://api.example.com/users/me

Quick Reference

Looking up a specific code while you're working? The HTTP Status Codes tool at ToolPal gives you instant descriptions, common causes, and usage guidance for every standard code. It's faster than opening an RFC.

CodeNameWhen to use
200OKStandard success
201CreatedResource created (POST)
204No ContentSuccess, no body (DELETE)
301Moved PermanentlyPermanent redirect
302FoundTemporary redirect
400Bad RequestMalformed request
401UnauthorizedNot authenticated
403ForbiddenAuthenticated but not allowed
404Not FoundResource doesn't exist
409ConflictState conflict
422Unprocessable EntitySemantic validation error
429Too Many RequestsRate limited
500Internal Server ErrorUnhandled exception
503Service UnavailableServer overloaded/down

Final Thoughts

HTTP status codes are a communication protocol between client and server developers. Using them correctly is a form of professional courtesy β€” it makes everyone's job easier, from the frontend developer consuming your API to the on-call engineer debugging a production incident at 2am.

The codes aren't complicated once you internalize the five categories. Memorize the common ones, look up the rest, and most importantly: be consistent and be specific. An API that uses status codes well is significantly easier to build on top of than one that returns 200 for everything with error details buried in the body.

Frequently Asked Questions

Share this article

XLinkedIn

Related Posts