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

Anatomy of an HTTP response

The other half of the conversation

We have seen what the client sends. Now let’s look at what comes back. When a server finishes processing a request, it puts together a response and sends it to the client. That response tells the client whether things worked, what format the data is in, and (usually) includes the actual data. Understanding the structure of a response matters just as much as understanding the request, because when you are building a server, you are the one constructing these responses.

The three parts of every response

Every HTTP response has three parts:

HTTP/1.1 200 OK                    <- Status line (version, code, reason)
Content-Type: application/json     <- Headers (metadata)
Content-Length: 52

[{"id":"book-1","title":"Kindred"}]  <- Body (data)

The status line is the first line. The headers follow, one per line. A blank line separates the headers from the body. This structure should look familiar. It mirrors the request, just with a status line instead of a request line.

The status line

HTTP/1.1 200 OK

Three pieces of information here:

The version matches the request version. Usually HTTP/1.1.

The status code is a three-digit number, and it is the most important part of the response. It tells the client what happened. 200 means success. 404 means the resource was not found. 500 means the server broke. Your code decides which status code to send, and getting it right is a big part of building a good API.

The reason phrase is a short, human-readable label: “OK”, “Not Found”, “Internal Server Error.” It is there for humans reading raw HTTP. Your code should always rely on the number, not the phrase.

Status code ranges at a glance

Status codes are grouped by their first digit, and each group means something different:

1xx codes are informational. The request is still being processed. You will rarely see these in APIs.

2xx codes mean success. 200 OK, 201 Created, 204 No Content.

3xx codes mean redirection. 301 Moved Permanently, 304 Not Modified. The resource is somewhere else.

4xx codes mean the client made a mistake. 400 Bad Request, 401 Unauthorized, 404 Not Found.

5xx codes mean the server made a mistake. 500 Internal Server Error, 503 Service Unavailable.

Section 3 of this course covers each range in detail. For now, just know the pattern: 2xx is good, 4xx is the client’s fault, 5xx is the server’s fault.

Response headers

Just like requests have headers, responses do too. They tell the client how to handle the response:

Content-Type: application/json
Content-Length: 52
Cache-Control: public, max-age=60
Set-Cookie: session=abc123; HttpOnly

Content-Type tells the client what format the body is in. application/json means JSON. text/html means HTML. Without this header, the client has to guess, and it will often guess wrong.

Content-Length tells the client how many bytes the body is. The client uses this to know when the response is complete.

Cache-Control tells the client how long it can cache this response before asking the server again. Covered in the Caching course.

Set-Cookie tells the browser to store a cookie and send it back on future requests. This is how sessions work. We will cover cookies later in this course, and the Authentication course goes much deeper.

Section 4 covers headers in full.

The response body

The body contains the actual data. What format is it in? Whatever Content-Type says:

If Content-Type is application/json, the body is JSON: {"id":"book-1","title":"Kindred"}

If Content-Type is text/html, the body is HTML: <html><body><h1>Kindred</h1></body></html>

Sometimes there is no body at all. A 204 No Content response (like after a successful deletion) has no body. A 304 Not Modified response (use your cached copy) has no body. The status code tells the client there is nothing to read.

Reading a response in code

Here is what it looks like to receive and read an HTTP response using JavaScript’s fetch:

const response = await fetch("https://api.example.com/books/book-1");

console.log(response.status); // 200
console.log(response.headers.get("content-type")); // "application/json"

const data = await response.json(); // Parse JSON body
console.log(data.title); // "Kindred"

response.status gives you the status code (the number). response.headers.get("content-type") reads a specific header. response.json() reads the raw text body and parses it as JSON, turning it into a JavaScript object you can work with.

Building a response on the server

When you are on the server side, you are the one creating these responses:

route.get("/books/:id", {
  resolve: (c) => {
    const id = new URL(c.request.url).pathname.split("/").pop();
    const book = getBook(id);
    if (!book) return Response.json({ error: "Not found" }, { status: 404 });
    return Response.json(book); // Status 200 by default
  },
});

Response.json(data) does several things for you at once: it serializes the data to a JSON string, sets Content-Type: application/json, and creates a response with status 200. If you need a different status code, you pass it as an option.

We now know what goes into a request and what goes into a response. The next section takes a closer look at the first piece of the request line: HTTP methods. Starting with the most common one, GET.

Exercises

Exercise 1: Use curl -v to make a request. In the output, lines starting with < are the response. Identify the status line, headers, and body.

Exercise 2: Use curl -I (a HEAD request) to get only the headers with no body. Compare what you see to a full GET response.

Exercise 3: Use fetch in Node.js to make a request. Log response.status, response.headers, and the result of response.json().

What does the Content-Type response header tell the client?

← Anatomy of an HTTP request GET and HEAD →

© 2026 hectoday. All rights reserved.