How an HTTP Request Travels
From fetch() in your code to bits on the wire — the full encapsulation journey
You call fetch() and, moments later, data comes back. This chapter opens the black box and walks the request from your code all the way down to signals leaving your network card. It is a high-level tour — every step here becomes its own deep-dive chapter later — but by the end you will see the shape of the whole journey.
We use one running example throughout: a React frontend on your laptop (127.0.0.1:3000) calling a Node backend deployed on an AWS EC2 machine (10.0.0.1:443) at the domain https://api.example.com/profile. (For simplicity we treat the loopback and the private 10.x address as if they were public.)
The key idea to hold on to is encapsulation: the data gets wrapped in layer after layer — like putting a letter in an envelope, the envelope in a box, the box in a shipping crate — each layer adding the addressing the next hop needs.
Interactive — the whole journey at a glance
animated figureWatch the request get resolved, wrapped, and raced across the internet. Every phase below is a section of this chapter.
Your code calls fetch() — one line, and the whole journey below begins.
The setup
Our frontend runs in the browser at 127.0.0.1:3000 (localhost). It needs to call the backend, a Node server running on an EC2 instance at 10.0.0.1, listening on port 443 because we are using HTTPS.
In code this is nothing more than: const response = await fetch("https://api.example.com/profile"). One line — but underneath it kicks off everything in this chapter.
- Frontend
- React app at 127.0.0.1:3000 (the client making the request).
- Backend
- Node server at 10.0.0.1:443 on an EC2 instance (the destination).
- Why 443?
- The URL is HTTPS, and browsers assume port 443 for HTTPS by default.
The connection is a 4-tuple
A network connection is uniquely identified by four values — source IP, source port, destination IP, destination port. Together they are called the 4-tuple. Any two machines can hold many simultaneous connections precisely because each one has a different combination of these four.
- Source IP
- 127.0.0.1 — where the request comes from.
- Source port
- 3000 — the client-side port.
- Destination IP
- 10.0.0.1 — the backend machine.
- Destination port
- 443 — the HTTPS service on the backend.
Note: The browser knows its own IP and port, and the destination port (443 from HTTPS). The one thing it still has to find is the destination IP — that is the next step.
Step 1 — DNS turns the name into an IP
Machines route by IP address, not by human names. So before anything can be sent, the hostname api.example.com must be resolved to an IP — here, 10.0.0.1. That resolution is done by DNS (the Domain Name System).
Under the hood this walks a chain of servers — a recursive resolver asks the root servers, then the TLD servers (.com), then the authoritative server for example.com — until it gets the answer. We will dedicate a whole chapter to how DNS resolution works.
Analogy: DNS is the internet’s phone book: you know the name, DNS gives you the number.
Step 2 — Build the HTTP request
With the destination known, the browser assembles the actual HTTP request. This is just structured text: a method, a path, and a set of headers.
- Method
- GET, POST, PUT, etc. — what you want to do.
- Path
- /profile — the resource on the server.
- Headers
- Metadata: content type, host, user agent, and more.
- Auth & cookies
- An Authorization: Bearer <token> header and cookies often travel with the request.
Step 3 — HTTP rides on TCP
HTTP does not move data by itself — it is carried by TCP (Transmission Control Protocol). TCP is connection-oriented: before any data flows, the client and server establish a reliable "pipe" between them.
TCP is what makes the delivery reliable and ordered, using mechanisms like the three-way handshake, flow control, and congestion control — each a future deep-dive. For now: HTTP text is handed down to TCP to actually transport.
Mental model: HTTP = what you want to say. TCP = the reliable courier that guarantees it arrives.
Step 4 — Text becomes bytes
The network does not move text — it moves bytes. The HTTP request text is run through an encoder that turns each character into its byte value, which we often view in hexadecimal (e.g. FE 12 00 AA …).
Why it matters: Everything below this point is just bytes. The "meaning" (it was a GET request) is only reconstructed when the server decodes them at the other end.
Step 5 — The browser hands off to the OS
The browser prepares the request (DNS, IP, ports) but it does not transmit anything itself. It hands the bytes to the operating system’s TCP/IP stack, which is the part of the OS (macOS, Windows, Linux) that actually implements TCP, UDP, ICMP and IP and talks to the hardware.
The OS stack then drives the NIC (Network Interface Card) — the physical hardware that puts signals on the wire or the air.
Key split: App/browser = prepares the message. OS network stack = transmits it. Different responsibilities, different layers.
Step 6 — Break the data into chunks
Data cannot travel as one giant blob. A 500-byte request or a 1 GB file is broken into many smaller chunks that are sent independently and reassembled at the destination.
- MTU
- Maximum Transmission Unit — the largest frame size the link can carry.
- MSS
- Maximum Segment Size — the largest chunk of data a single TCP segment can hold.
Later: MTU, MSS, PMTUD and IP fragmentation get a dedicated chapter. For now: chunk sizes are capped by these limits.
Wrap 1 — The TCP segment
Each chunk is wrapped by TCP into a TCP segment. TCP adds the source port (3000), the destination port (443), and — crucially — a sequence number.
The sequence number lets the receiver put chunks back in the right order even if they arrive out of order, and detect if any are missing. This is the heart of TCP’s reliability.
First envelope: Chunk + ports + sequence number = TCP segment. It knows which programs to connect, but not yet which machines.
Wrap 2 — The IP packet
The TCP segment is then wrapped by the IP layer into an IP packet, which adds the source IP (127.0.0.1) and destination IP (10.0.0.1).
Routers along the way read the destination IP to decide where to forward the packet next, hop by hop. The source IP is what lets the backend know where to send the response.
Second envelope: TCP segment + source/dest IP = IP packet. Now it knows which machines — this is what the internet routes on.
Wrap 3 — The frame (MAC addresses)
The final wrap adds physical (MAC) addresses, producing a frame. The source MAC is your laptop’s NIC. But what is the destination MAC?
The backend is not on your local network, so you do not know (and cannot use) its MAC directly. Instead, the destination MAC is set to your default gateway (the router) — the device that will forward the frame onward toward the destination.
Third envelope: IP packet + source/dest MAC = frame. MAC gets it to the next physical device — here, the router.
Step 7 — ARP, then onto the wire
But how do we learn the router’s MAC address? With ARP (Address Resolution Protocol). Your laptop broadcasts to the whole local network — "who has 192.168.1.1?" — and only the router replies with its MAC. ARP is like DNS, but it maps an IP to a MAC.
Finally the completed frame is handed to the NIC, which transmits it as physical signals: radio waves (WiFi), electrical pulses (Ethernet), or light (fiber).
Reality check: After all this, the data still has not reached the backend — we have only covered roughly the first quarter of the journey. Everything above gets unpacked, routed, and repeated at every hop. That is what the rest of the course explores.