Skip to content
Ameen Abozaid
PublishedBEG-052-L01

Anatomy of an HTTP request

  • Lesson 1 of 7
  • 11 min read
  • Beginner
On This Lesson 11 topics

Lesson Overview

In BEG-003 you learned that a client sends a request and a server sends back a response. This module opens those two messages and looks inside. Think of ordering at a restaurant: you hand over an order slip (the request) and the kitchen sends back a dish with a note (the response). The slip says what you want and how you want it. The note says whether the kitchen could do it.

HTTP, the language browsers and servers use, is just a strict format for those slips and notes. Once you can read the format, you can read any web traffic, and the backend code you will write later is a program that reads request slips and writes response notes.

This lesson names the parts of a request and a response and explains what "stateless" means. The next lessons zoom in on each part: methods, status codes, headers, JSON bodies, and URLs. It builds on BEG-003 (clients, servers, URLs) and on Java strings from the earlier Java modules.

Learning Objectives

By the end of this lesson you will be able to:

  • Name the four parts of an HTTP request: method, URL (target), headers, and optional body.
  • Name the three parts of an HTTP response: status, headers, and optional body.
  • Read a raw HTTP request and response written as text and point to each part.
  • Explain why a blank line separates the headers from the body.
  • Explain what it means that HTTP is stateless, in one example.
  • Say which part of a response tells you whether the request worked.

Written Explanation

Two messages, one conversation

HTTP works in request/response pairs. The client always starts: it sends one request, and the server answers with one response. The server does not speak first in plain HTTP. In the restaurant picture, the kitchen never sends dishes nobody ordered.

Both messages are made of text (in HTTP/1.1, the version we show here; newer versions carry the same ideas in a binary form). Both share the same layout, as MDN describes it:

  1. A start line, one line saying what this message is.
  2. Zero or more headers, one per line, each written Name: value.
  3. An empty line that marks the end of the headers.
  4. An optional body, the actual data being carried.

The request

text
POST /books HTTP/1.1
Host: api.example.com
Content-Type: application/json

{"title":"Dune"}
PartIn the exampleJob
MethodPOSTThe action you want (lesson 2)
Target (path)/booksWhich resource on the server
VersionHTTP/1.1Which version of the rules is spoken
HeadersHost, Content-TypeExtra information about the request (lesson 4)
Body{"title":"Dune"}The data you send; here it is JSON (lesson 5)

The start line of a request is the request line: <method> <target> <version>. The target is usually just the path (and query) of the URL, because the connection already knows which host it is talking to. The Host header names that host, so one server can serve many sites.

Not every request has a body. A request to read a page has none; a request that sends a new book does. Per MDN, normally only POST, PUT, and PATCH requests carry a body.

The response

text
HTTP/1.1 201 Created
Content-Type: application/json
Location: /books/8

{"id":8,"title":"Dune"}
PartIn the exampleJob
VersionHTTP/1.1Which rules the server speaks
Status code201A number saying how it went (lesson 3)
Reason phraseCreatedA human-readable label; the number is what programs use
HeadersContent-Type, LocationInformation about the response
Body{"id":8,...}The result data, if any

The first line is the status line. The status code is the part that tells you whether the request worked. Some responses have no body at all: 201 Created and 204 No Content may arrive with nothing after the headers.

The Location header in this example is not magic: it is a header the server chose to add to tell the client where the new book lives. Headers are open-ended metadata.

Why a blank line?

The receiver needs to know where the headers stop. Headers are plain lines, so a single empty line is the agreed signal: everything before it is the head, everything after it is the body. Forgetting that blank line, or adding one inside the headers, produces a broken message. (A server also needs to know where the body ends. That is done by a Content-Length header giving the byte count, or by sending the body in chunks. You normally never write this by hand.)

Stateless: each request stands alone

MDN describes HTTP as stateless: there is no link between two requests carried out one after the other, even on the same connection. The server treats each slip as if it were the first it ever saw.

Restaurant version: a waiter with no memory. If you say "the same as before", he does not know what that means, so every slip must contain everything he needs. On the web, that is why a request for your basket must carry some proof of who you are on every single request. Cookies, which are headers, are the usual mechanism that lets a site build sessions on top of a stateless protocol. You will see the header side in lesson 4.

Stateless is not a flaw. A server that remembers nothing between requests is simpler to reason about and easier to run as many copies, an idea that matters for backends later.

Examples

Example 1: Label a request (simple)

text
GET /books/7 HTTP/1.1
Host: api.example.com
Accept: application/json
  • Method: GET
  • Target: /books/7
  • Headers: Host, Accept
  • Body: none (there is nothing after the headers)

The blank line after the last header is present even though no body follows.

Example 2: Label a response (practical)

text
HTTP/1.1 200 OK
Content-Type: application/json

{"id":7,"title":"Dune"}
  • Status: 200 (reason phrase OK), so the request worked
  • Header: Content-Type: application/json, which says how to read the body
  • Body: the book as JSON

If the first line had read HTTP/1.1 404 Not Found, the headers and body would describe the failure, and your code would check the number first.

Example 3: Take a request apart in Java (realistic)

A server receives text and must split it into its parts. This small program does that for the POST request above. It uses a Java text block ("""), a way to write a multi-line string; treat it as an ordinary string if you have not met it yet.

java
public class L01 {
    public static void main(String[] args) {
        String raw = """
                POST /books HTTP/1.1
                Host: api.example.com
                Content-Type: application/json

                {"title":"Dune"}""";
        String[] parts = raw.split("\n\n", 2);       // head | body
        String[] lines = parts[0].split("\n");
        String[] startLine = lines[0].split(" ");
        System.out.println("method  = " + startLine[0]);
        System.out.println("target  = " + startLine[1]);
        System.out.println("version = " + startLine[2]);
        for (int i = 1; i < lines.length; i++) {
            String[] h = lines[i].split(": ", 2);
            System.out.println("header  " + h[0] + " -> " + h[1]);
        }
        System.out.println("body    = " + parts[1]);
    }
}

Output (compiled and run with JDK 21):

text
method  = POST
target  = /books
version = HTTP/1.1
header  Host -> api.example.com
header  Content-Type -> application/json
body    = {"title":"Dune"}

The program cuts at the blank line first (head and body), then at the first line (start line) and the rest (headers). Real servers do the same job with much more care. Note that real HTTP ends lines with a carriage return plus line feed; we use plain line feeds to keep the demo readable.

Backend Insight

Your future backend code will be a function from request to response. A framework hands you the method, the path, the headers, and the body already split apart, and you return a status, headers, and a body. Knowing the raw layout tells you what the framework is giving you and where to look when something is wrong.

Statelessness has a direct consequence: anything the server must remember between requests (a logged-in user, a basket) has to be either sent again with each request or stored on the server in a database and looked up using an identifier the client sends. A backend that "just remembers" in a variable breaks as soon as a second copy of the server runs or the first one restarts.

Finally, the status code is the first thing a client program reads. If your backend returns 200 with an error message in the body, clients that check the code will think everything is fine.

Common Mistakes

Mistake 1: Mixing up request parts and response parts

  • Incorrect: "The response has a method."
  • Correct: "The request has a method; the response has a status code."

Ask which direction the message travels. The client sends methods; the server sends statuses.

Mistake 2: Thinking every message has a body

  • Incorrect: "A GET request must include the book in its body."
  • Correct: "A GET normally has no body, and a 204 response has none either."

Mistake 3: Thinking the server remembers the last request

  • Incorrect: "I asked for /books/7 a second ago, so I can just ask for 'the next one'."
  • Correct: "Each request must identify exactly what it wants, because the server keeps no memory of the previous one."

Mistake 4: Treating the reason phrase as the result

  • Incorrect: "The response said Created, so my code checks that text."
  • Correct: "Code checks the numeric status; the phrase after it is only a label."

Exercises

Try each exercise before opening the solutions.

Level A: Foundation

A1. List the parts of an HTTP request and the parts of an HTTP response, and mark which are optional.

Show solution A1

A1. Request: method, target (URL path), headers, optional body. Response: status code, headers, optional body. The body is the optional part in both (in HTTP/1.1 a request is also expected to carry a Host header).

A2. Label the method, target, headers, and body in:

text
PUT /members/3 HTTP/1.1
Host: club.example.com
Content-Type: application/json

{"name":"Sara"}
Show solution A2

A2. Method PUT; target /members/3; headers Host and Content-Type; body {"name":"Sara"}. The version HTTP/1.1 is also on the start line.

A3. What does "stateless" mean, in one sentence?

Show solution A3

A3. Each request stands alone; the server keeps no link between one request and the next.

Level B: Application

B1. Label the parts of this response and say whether it worked:

text
HTTP/1.1 404 Not Found
Content-Type: text/plain

No such book
Show solution B1

B1. Status line: version HTTP/1.1, status 404, reason phrase Not Found. Header: Content-Type: text/plain. Body: No such book. It did not work: 404 means the resource was not found.

B2. A student says: "My request has no body, so the blank line after the headers is not needed." Is that right? Explain, using what the blank line separates.

Show solution B2

B2. The blank line is still needed. It ends the header section, so the receiver knows the message head is complete. Without a body the message simply ends after it.

B3. A shop site shows your basket on every page. In terms of statelessness, what must each request include for the server to know whose basket to load?

Show solution B3

B3. Some identifier of the user or basket, usually carried in a header such as a cookie, on every request. The server cannot rely on remembering you from the previous request.

Level C: Challenge

C1. Change the Java program from Example 3 so that, for the raw text of Example 1 (the GET with no body), it prints body = (none) instead of failing. Describe what goes wrong in the original and show your fix.

Show solution C1

C1. With no body, raw.split("\n\n", 2) returns only one element, because the text block ends after the last header and has no blank line followed by text. Then parts[1] throws ArrayIndexOutOfBoundsException. Fix:

java
String body = parts.length > 1 ? parts[1] : "(none)";
System.out.println("body    = " + body);

(Compiled and run on the GET text: it prints body = (none), and without the fix the error is Index 1 out of bounds for length 1.)

C2. Write the full response a server might return after DELETE /books/7 succeeds, using a status line and one header, with no body. Explain why no body is needed.

Show solution C2

C2.

text
HTTP/1.1 204 No Content
Date: Wed, 04 Nov 2026 10:00:00 GMT

A 204 No Content means success with nothing to return. The client only needs to know the delete worked; there is no data to show.

Mini Challenge

Take any small web page you know. Write, from memory and by reasoning, a plausible request for its main page and a plausible response (use GET, a path, a Host header, a status code, a Content-Type of text/html, and the first line of the body). Then mark each part with a label in brackets.

Check your work: the request has a method, target, version, at least one header, and a blank line; the response has a version, status code, reason phrase, header, blank line, and body; no part is in the wrong message.

Summary & Next Lesson

Key takeaways

  • HTTP is request/response: the client asks, the server answers.
  • A request has a method, a target, headers, and sometimes a body. A response has a status code, headers, and often a body.
  • A blank line separates the headers from the body.
  • The status code tells you whether the request worked.
  • HTTP is stateless: every request must carry everything the server needs.

Next lesson

The next lesson, "Methods: GET, POST, PUT, PATCH, DELETE", takes the first word of the request line and shows how to choose the right one.

Self-check

  1. Name the parts of a request.
  2. Name the parts of a response.
  3. Which part tells you if the request worked?
  4. What separates headers from body?
  5. Why must a request for your basket identify you each time?
Show answers
  1. Method, target (URL), headers, optional body.
  2. Status code (in the status line), headers, optional body.
  3. The status code.
  4. An empty line.
  5. HTTP is stateless, so the server does not remember who asked before.

References

  • MDN: HTTP messages. Supports the layout of start line, headers, empty line, and optional body; the request-line and status-line formats; that reason phrases carry no protocol meaning; and that only POST, PUT, and PATCH normally have request bodies.
  • MDN: An overview of HTTP. Supports client-initiated request/response exchange and the statement that HTTP is stateless while cookies enable sessions.

Practice

Apply this lesson with the module's lab, exercises and quiz.

Lab and exercises Quiz

Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.

Continue to next lesson

Type to search levels, phases, modules and lessons.