hectoday
DocsCoursesChangelog GitHub
DocsCoursesChangelog GitHub

Access Required

Enter your access code to view courses.

Invalid code

← All courses HTTP from scratch

What is HTTP

  • The request-response model
  • Anatomy of an HTTP request
  • Anatomy of an HTTP response

Methods

  • GET and HEAD
  • POST
  • PUT, PATCH, and DELETE
  • OPTIONS and CORS preflight

Status codes

  • 2xx success
  • 3xx redirection
  • 4xx client errors
  • 5xx server errors

Headers

  • Request headers
  • Response headers
  • Custom headers

The body

  • JSON
  • Form data and multipart
  • No body

Connections

  • TCP, DNS, and TLS
  • HTTP/1.1 vs HTTP/2
  • Cookies and state

Putting it all together

  • Building a server from scratch
  • From scratch to framework

4xx client errors

The client made a mistake

4xx status codes mean the problem is on the client’s side. The server understood the request, but something was wrong with it: bad data, missing credentials, wrong permissions, or asking for something that does not exist. When you build an API, you will use these codes constantly. Returning the right 4xx code tells the client exactly what went wrong and how to fix it.

400 Bad request

The request itself is broken. Maybe the JSON is malformed, a required field is missing, or the data types are wrong.

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

{"error":{"code":"VALIDATION_ERROR","message":"'title' is required"}}

Use 400 for: invalid JSON syntax, missing required fields, wrong data types, malformed query parameters. The client needs to fix the request before trying again.

[!NOTE] The Error Handling course builds a ValidationError class that maps to 400 and a global error handler that returns field-level details so the client knows exactly which fields to fix.

401 Unauthorized

The client is not authenticated. The server is asking: “Who are you? I do not recognize you.”

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer

Use 401 when: the request has no authentication token, the token is invalid or expired, or the credentials are wrong. The WWW-Authenticate header tells the client what authentication scheme to use (in this case, a Bearer token).

403 Forbidden

The client is authenticated (the server knows who they are) but they do not have permission to do this.

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

{"error":{"code":"FORBIDDEN","message":"Admins only"}}

Use 403 for: a regular user trying to access an admin endpoint, or any role-based access control failure.

This is a distinction that confuses a lot of people. 401 means “I do not know who you are.” 403 means “I know who you are, and you are not allowed.” Sending your credentials again will fix a 401. Sending the same credentials again will not fix a 403, because the problem is not identity, it is permissions.

404 Not found

The resource does not exist. This is probably the most well-known HTTP status code.

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

{"error":{"code":"NOT_FOUND","message":"Book not found"}}

Use 404 when: the client requests a specific resource by ID and it does not exist, or the client hits a URL that has no matching route.

409 Conflict

The request conflicts with the current state of the data.

HTTP/1.1 409 Conflict
Content-Type: application/json

{"error":{"code":"CONFLICT","message":"A book with this ISBN already exists"}}

Use 409 for: duplicate entries (like trying to create a book with an ISBN that already exists), version conflicts (two people editing the same resource at the same time), or state conflicts (trying to publish a book that is already published).

422 Unprocessable entity

The request syntax is fine (so it is not a 400), but the data does not make sense.

HTTP/1.1 422 Unprocessable Entity

{"error":{"code":"VALIDATION_ERROR","message":"Rating must be between 1 and 5"}}

What is the difference between 400 and 422? 400 means “I cannot even parse your request.” Maybe the JSON is broken. 422 means “I parsed it, but the values do not make sense.” A rating of 6 is valid JSON, but it is not a valid rating.

In practice, many APIs just use 400 for both. You will see it both ways.

429 Too many requests

The client has been rate limited. They sent too many requests in a given time window.

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

{"error":{"code":"RATE_LIMITED","message":"Too many requests"}}

The Retry-After header tells the client how many seconds to wait before trying again. This is important. A well-behaved client reads this header and backs off. A poorly-behaved client ignores it and keeps hammering the server, which makes the problem worse.

[!NOTE] The Securing Your API course implements rate limiting with 429 and Retry-After. The Error Handling course’s RateLimitError maps to this status code.

We have covered all the major client error codes. But what happens when the server itself breaks? That is a different category entirely: 5xx server errors, coming up next.

Exercises

Exercise 1: Send a request with invalid JSON. Verify you get 400.

Exercise 2: Send a request without an authentication token. Verify 401. Then send with valid credentials but wrong permissions. Verify 403.

Exercise 3: Request a resource that does not exist. Verify 404.

What is the difference between 401 Unauthorized and 403 Forbidden?

← 3xx redirection 5xx server errors →

© 2026 hectoday. All rights reserved.