Le Quang Lam
← All writing

The journey of a web request

September 6, 2026·10 min read·software

You type https://example.com into the address bar and hit Enter. Less than a second later, a page appears. Behind that instant, dozens of systems pass the work along a complex relay. We'll follow that request on its journey — parsing the URL, resolving the name, opening a connection, securing it, sending the request, waiting on the server, and rendering the page — to see the machinery behind that one second.

Step 1 — Parsing the URL

Before anything leaves your machine, the browser breaks the URL into the pieces it needs:

https://example.com:443/products?sort=price#reviews
└─┬─┘   └────┬────┘ └┬┘ └──┬───┘ └───┬────┘ └──┬──┘
scheme      host    port  path     query    fragment

From here, the browser works through these pieces in order — starting with host, over in DNS.

Step 2 — DNS (Domain Name System): turning a name into an address

Computers route packets to IP addresses, not to example.com. So the very first thing that has to happen is a DNS lookup — and it's layered, checked in this order, stopping at the first hit:

  1. Browser cache — did this browser already resolve this host recently?
  2. Hosts file — a static, manually-edited list of local overrides (/etc/hosts on macOS, C:\Windows\System32\drivers\etc\hosts on Windows). If a name matches here, it wins outright — no cache, no network round trip, nothing to expire:
    127.0.0.1        localhost
    255.255.255.255  broadcasthost
    ::1              localhost
    
    This is also how developers point a domain at 127.0.0.1 for local testing, or how some ad/malware blockers work — by redirecting known-bad hostnames to 0.0.0.0.
  3. OS cache — did any process locally resolve it before?
  4. Recursive resolver — usually your ISP's (Internet Service Provider) resolver or a public one like 1.1.1.1 (Cloudflare), 8.8.8.8 (Google),... If it doesn't have the answer cached either, it does the actual walk:
    • ask a root server (represented by the trailing . on every hostname, the dot is just always hidden: example.com is really example.com.) → "who handles .com?" → "ask this TLD server."
    • ask that TLD server → "who is authoritative for example.com?" → "ask this authoritative server."
    • ask the authoritative server → "what's the IP for example.com?" → "it's 93.184.216.34."

The result is an IP address, say 93.184.216.34 — that every step from here on actually uses, not the hostname.

Step 3 — Opening a connection: the TCP (Transmission Control Protocol) handshake

With an IP in hand, the browser opens a TCP connection to that server on port 443, since our example uses HTTPS. TCP is the transport-layer protocol under HTTP — it guarantees bytes arrive in order and complete, unlike UDP. Opening one always costs the same fixed exchange, the three-way handshake:

  1. Client → Server: SYN — "I'd like to start a connection, my starting sequence number is x."
  2. Server → Client: SYN-ACK — "Got it, here's my own sequence number y, and I acknowledge yours."
  3. Client → Server: ACK — "Acknowledged."

Step 4 — Securing the data: the TLS (Transport Layer Security) handshake

If the scheme is https (it almost always is today), the browser doesn't send the HTTP request yet. First it negotiates encryption on top of the now-open TCP connection — the TLS handshake. In modern TLS 1.3, this is compressed into essentially one round trip:

  • ClientHello — the browser lists cipher suites it supports (the algorithms for encrypting data later), and separately, guesses which key-exchange group the server prefers, generates a throwaway key pair for it, and sends only the public half as its key share.
  • ServerHello + certificate + key share — the server picks a cipher suite, generates its own throwaway key pair for that same group, sends back its public key share, and attaches its certificate.
  • The browser checks the certificate against a trusted certificate authority. Separately, each side combines its own private key with the other's public key share to land on the same symmetric session key — without that key ever crossing the wire.

From here on, everything, including the HTTP request itself, is run through the cipher suite agreed on above — encrypted with the symmetric session key — before being wrapped in a TLS record, so anyone sniffing the connection just sees opaque bytes.

Step 5 — Sending the HTTP request

Only now does the actual HTTP request go out, over the connection that steps 3 and 4 just built:

GET /products?sort=price HTTP/1.1
Host: example.com
Accept: text/html
Cookie: session=abc123

A request line (method, path, version) plus headers — no body for a GET. This is the cheapest step of the whole journey: one small packet, no round trip of its own, because it just rides the connection that's already open and encrypted.

Step 6 — What the server does with it

The request arrives at a machine, but rarely hits application code directly. A typical path:

  • A reverse proxy / load balancer (nginx, an ALB, Cloudflare) terminates the connection and picks which backend instance handles it.
  • The application server finally puts path and query to work. It routes path to a handler, reads query to shape the response, runs the business logic, and — most of the time — talks to a database or cache to gather what it needs.
  • A response gets assembled: a status code, headers, and a body.

This is usually the slowest single step in the whole journey, and the one most within your control as a developer — everything before it is protocol overhead you can only minimize, not skip.

Step 7 — The response comes back

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 8241
Cache-Control: max-age=300

<!doctype html>...

A status code tells the browser how to treat what follows: 2xx render it, 3xx follow the Location header somewhere else, 4xx/5xx show an error. Headers like Cache-Control decide whether the next visit can skip several of the steps above entirely.

Putting the whole trip on one timeline

Laid end to end, here's roughly where the time actually goes for a cold connection to a server on the other side of the world — before your framework, your bundle size, or your database query even enter the picture:

Notice how much of it — DNS, TCP, TLS — is spent before the request you actually care about is even sent. None of that is negotiable per request; it's the fixed cost of talking to a server you don't already have an open, secure connection to.

The response landing doesn't mean the TCP connection tears down — that happens at one of a few distinct points:

  • Connection: close — either side asks to shut it down right after this response (the HTTP/1.0 default).
  • Idle timeout — nothing else comes through within a window the server configures (commonly 5–60 seconds), so it closes the connection itself.
  • Client pool eviction — the browser caps how many idle connections it keeps per host and overall, and closes the oldest ones to make room.

Step 8 — The browser renders the page

The bytes that came back are just text and markup until the browser does something with them:

  1. Parse HTML into a DOM tree as it streams in.
  2. Parse CSS into a CSSOM tree.
  3. Combine both into a render tree — the DOM nodes that are actually visible, with their computed styles.
  4. Layout — compute the exact size and position of every box.
  5. Paint — turn those boxes into actual pixels on screen.

Why the second visit feels instant

Almost every step above is something a second request can skip:

StepFirst visitRepeat visit (same session)
DNS lookupFull or partial recursive walkServed from browser/OS cache
TCP handshakeNew connection, one round tripSkipped — connection reused (keep-alive)
TLS handshakeNew handshake, ~one round tripSkipped — same reused connection
HTTP requestSent in fullSent in full, but may return 304 Not Modified
Server processingFull workPossibly served from a cache layer
RenderingFull parse + layout + paintSame, unless the page itself is cached

That's the real reason a warm connection to a site you're already browsing feels instant while the very first link you click from a search result takes a beat: the first one is paying almost every cost on this list at once.

References


  • Configuring DNS records — the other side of step 2: what the records are made of, and how to read dig when one looks wrong.
  • What TCP does after the handshake — step 3 in depth: sequence numbers, backpressure, why a new connection starts slow, and what TIME_WAIT means.
  • HTTP caching, layer by layer — the Cache-Control line in step 7, opened up: freshness, 304 revalidation, browser vs CDN, and why invalidation is the hard part.