KAHIBARO
Discord Login Register

2.11. HTTP Status Codes

Why HTTP Status Codes Matter

When a client sends an HTTP request to a server, the server always replies with an HTTP response that starts with a status line. Part of that status line is a status code, such as 200, 404, or 500.

The status code tells the client what happened:

As a backend developer you must always pick the correct status code. It affects:

An HTTP response must have exactly one status code.
Clients rely on accurate status codes to understand the result of a request.


Structure of an HTTP Status Code

A status code has:

Example status line:

http
HTTP/1.1 200 OK

The number is what really matters to machines. The reason phrase is mostly for humans and logging.

Status Code Classes

The first digit groups codes into classes:

ClassRangeMeaningTypical use example
1xx100–199Informational, request still in progressRare in basic APIs
2xx200–299SuccessRequest worked
3xx300–399RedirectionUse another URL or location
4xx400–499Client errorClient sent something invalid
5xx500–599Server errorServer failed while handling a valid request

Rule:

  • If the client did something wrong, use 4xx.
  • If the server failed or crashed, use 5xx.
  • If all is fine, use 2xx.

Common 2xx Success Codes

200 OK

Used when a request is successfully processed and:

Examples:

http
GET /users/123 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 123, "name": "Alice"}
http
PUT /users/123 HTTP/1.1
Content-Type: application/json
{"name": "New Name"}
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 123, "name": "New Name"}

When building APIs, 200 OK is the "default success" for many operations.

201 Created

Use 201 Created when the server created a new resource as a result of the request, typically with POST.

Key points:

Example:

http
POST /users HTTP/1.1
Content-Type: application/json
{"name": "Alice"}
HTTP/1.1 201 Created
Location: /users/123
Content-Type: application/json
{"id": 123, "name": "Alice"}

204 No Content

Use 204 No Content when the request was successful but there is no response body.

Typical for:

Example:

http
DELETE /users/123 HTTP/1.1
HTTP/1.1 204 No Content

If you send a body with 204, most clients will ignore it. Avoid sending a body with this code.


Common 3xx Redirection Codes

3xx responses tell the client that the resource is available somewhere else or has changed location.

Redirection responses usually include a Location header.

301 Moved Permanently

Resource has permanently moved to a new URL.

Use cases:

Example:

http
GET /old-path HTTP/1.1
HTTP/1.1 301 Moved Permanently
Location: /new-path

Browsers may cache this and always go to /new-path next time.

302 Found and 307 Temporary Redirect

Both indicate a temporary redirect, but they differ in method handling.

For modern APIs, prefer 307 when you want to keep the method.

Example with 307:

http
POST /upload HTTP/1.1
HTTP/1.1 307 Temporary Redirect
Location: /upload-server-2

The client should repeat the POST to /upload-server-2 with the same body.

304 Not Modified

Used with caching. It says:

You already have the latest version, you can reuse your cached copy.

There is no response body. The client uses its own cached body.

Example:

http
GET /image.png HTTP/1.1
If-None-Match: "abc123"
HTTP/1.1 304 Not Modified

You will learn more about caching later, but remember that 304 is part of HTTP caching.


Common 4xx Client Error Codes

4xx means the client did something wrong. The request is invalid in some way.

400 Bad Request

The server cannot understand the request. Often used when:

Example:

http
POST /users HTTP/1.1
Content-Type: application/json
{"name": "Alice"  // missing closing brace
HTTP/1.1 400 Bad Request
Content-Type: application/json
{"error": "Invalid JSON body"}

401 Unauthorized

Despite the name, 401 Unauthorized means "not authenticated".

Use 401 when:

Typical for protected APIs:

http
GET /profile HTTP/1.1
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
{"error": "Authentication required"}

Note the WWW-Authenticate header. It tells the client what kind of authentication is needed.

403 Forbidden

The client is authenticated but not allowed to perform this action.

Use 403 when:

Example:

http
DELETE /users/123 HTTP/1.1
Authorization: Bearer valid-but-normal-user-token
HTTP/1.1 403 Forbidden
Content-Type: application/json
{"error": "You do not have permission to delete this user"}

Rule:

  • Not logged in or invalid token β†’ 401 Unauthorized
  • Logged in but not allowed β†’ 403 Forbidden

404 Not Found

The resource does not exist, or you do not want to reveal that it exists.

Typical when:

Example:

http
GET /users/99999 HTTP/1.1
HTTP/1.1 404 Not Found
Content-Type: application/json
{"error": "User not found"}

Many APIs also use 404 for security reasons when the user tries to access someone else's data, even if the resource exists, to avoid information leaks.

405 Method Not Allowed

The URL exists, but the HTTP method is not allowed on it.

Example:

http
POST /users/123 HTTP/1.1
HTTP/1.1 405 Method Not Allowed
Allow: GET, PUT, DELETE

The Allow header lists valid methods for that endpoint.

This often happens by accident when you forget to implement a method route in your backend.

409 Conflict

There is a conflict with the current state of the resource.

Common cases:

Example:

http
POST /users HTTP/1.1
Content-Type: application/json
{"email": "alice@example.com"}
HTTP/1.1 409 Conflict
Content-Type: application/json
{"error": "Email already exists"}

422 Unprocessable Entity

The request is syntactically correct, but the data is semantically invalid.

Often used for:

Example:

http
POST /users HTTP/1.1
Content-Type: application/json
{"name": "", "email": "not-an-email"}
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
  "errors": [
    {"field": "name", "message": "Name cannot be empty"},
    {"field": "email", "message": "Invalid email address"}
  ]
}

Some frameworks use 400 for validation errors, others prefer 422. Be consistent inside one API.


Common 5xx Server Error Codes

5xx codes mean the server failed to handle a valid request. The problem is on the server side.

500 Internal Server Error

A general error for unexpected failures.

Use 500 when:

Example:

http
GET /users HTTP/1.1
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{"error": "Something went wrong"}

In production, you should log full details on the server, but send a simple message to the client.

502 Bad Gateway

This appears when there is a reverse proxy or gateway (like Nginx) in front of your app and the proxy gets an invalid response from the upstream server.

Example scenario:

As a backend developer you often see 502 in logs when your application container is down.

503 Service Unavailable

The server is temporarily unavailable.

Use for:

Example:

http
GET /api HTTP/1.1
HTTP/1.1 503 Service Unavailable
Retry-After: 120
Content-Type: application/json
{"error": "Service temporarily unavailable"}

Retry-After tells the client how long to wait before retrying, in seconds or as a date.

504 Gateway Timeout

The gateway or proxy timed out waiting for a response from the upstream server.

Example scenario:

Typical Status Codes for CRUD APIs

In backend development, you often build REST style APIs with CRUD operations:

Here is a typical mapping:

OperationHTTP MethodUsual Status Code(s)
List resourcesGET200 OK
Get single resourceGET200 OK, 404 Not Found
Create resourcePOST201 Created, sometimes 400, 422
Replace resourcePUT200 OK or 204 No Content, 404
Partial updatePATCH200 OK or 204 No Content, 404
Delete resourceDELETE204 No Content, 404 Not Found

Example mini API:

  1. Create:
http
POST /tasks HTTP/1.1
Content-Type: application/json
{"title": "Write chapter"}
HTTP/1.1 201 Created
Location: /tasks/1
Content-Type: application/json
{"id": 1, "title": "Write chapter", "completed": false}
  1. Get:
http
GET /tasks/1 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 1, "title": "Write chapter", "completed": false}
  1. Update:
http
PATCH /tasks/1 HTTP/1.1
Content-Type: application/json
{"completed": true}
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 1, "title": "Write chapter", "completed": true}
  1. Delete:
http
DELETE /tasks/1 HTTP/1.1
HTTP/1.1 204 No Content
  1. Get deleted resource:
http
GET /tasks/1 HTTP/1.1
HTTP/1.1 404 Not Found
Content-Type: application/json
{"error": "Task not found"}

Choosing the Right Status Code

A simple way to decide on a code:

  1. Did the request succeed?
    • Yes β†’ 2xx
    • No β†’ continue
  2. Should the client use another URL?
    • Yes β†’ 3xx
  3. Was the request itself invalid or not allowed?
    • Yes β†’ 4xx
  4. Did something unexpected go wrong on the server?
    • Yes β†’ 5xx

Some practical examples:

SituationGood code
JSON body missing required field400 or 422
User not logged in, trying to access /me401
Logged in user without admin rights tries to delete another user403 or 404
Resource with given ID does not exist404
Duplicate email on registration409
Unhandled exception in your code500
Your database is down500 or 503

Rule:
Use the most specific code that matches what happened.
Avoid returning 200 OK for failures.


Summary

You will use these codes constantly when you implement real backend endpoints in later chapters.

Views: 9

Comments

Please login to add a comment.

Don't have an account? Register now!