"What happens when you type a URL and press Enter?" is the most famous systems interview question there is, precisely because a single web request quietly touches every layer of the stack — naming, routing, transport, encryption, application protocol, and rendering. Most people can name two or three steps. This guide walks the whole path for one request to https://example.com, from keystroke to rendered pixels, so you can see how the pieces fit — and know exactly where to look when something is slow or broken.

The journey at a glance

Parse URL → DNS lookup → Route packets → TCP handshake → TLS handshake → HTTP request/response → Render

Each phase hands off to the next. We'll take them in order, then put the timeline back together at the end.

Step 1 — Parse the URL

Before any network activity, the browser breaks the URL into parts:

https :// example.com : 443 / path ? query # fragment
scheme     host        port   path   query  fragment
  • scheme (https) decides the protocol and the default port (443 for HTTPS, 80 for HTTP).
  • host (example.com) is the name we must turn into an address.
  • path/query describe what on that host we want; the fragment (#...) never leaves the browser.

The browser also applies HSTS: if the site previously said "always use HTTPS," an http:// link is upgraded to https:// before anything is sent.

Step 2 — Do we even need the network?

The fastest request is the one you don't make. The browser checks, in order:

  • Its own cache — a still-fresh copy (per HTTP caching headers) is used with zero network.
  • An already-open connection to that host it can reuse.
  • The OS, which checks the local hosts file (/etc/hosts) before DNS — a stray entry here is a classic "works on my machine" trap.

Assume nothing is cached. We need the network — starting with a name-to-address lookup.

Step 3 — DNS: turn the name into an address

The browser can't route to example.com; it needs an IP. It asks a recursive resolver (your ISP's, or 1.1.1.1 / 8.8.8.8), which walks the DNS hierarchy — root → .com → example.com's authoritative servers — and returns something like 93.184.216.34. In practice most of this is cached, so it's usually a millisecond or two.

dig +short example.com A     # 93.184.216.34

DNS is a deep topic of its own (caching, TTLs, records, DNSSEC) — our free DNS course covers it end to end. For now: name in, IP out.

Step 4 — Routing: getting packets to that IP

Your device now has a destination IP, but it isn't directly connected to it. It makes one decision: is this IP on my local network, or remote? — computed from your IP and subnet mask.

  • Local → it uses ARP (Address Resolution Protocol) to find the target's hardware (MAC) address and sends the frame directly.
  • Remote (our case) → it sends the packet to its default gateway (your router), after ARPing for the gateway's MAC.

From there the packet is forwarded hop by hop. Each router consults its routing table and passes the packet toward the destination; between networks, BGP (Border Gateway Protocol) is what stitches the world's independent networks (Autonomous Systems) into routes. Every hop decrements the packet's TTL (hop limit); hit zero and it's dropped (this is what traceroute exploits to map the path):

traceroute example.com    # each line is one router hop toward the server

So a request to a server across the world might traverse 12–20 routers, each an independent decision. None of them see your data yet — just addresses on the envelope.

Step 5 — The layered model (TCP/IP) and encapsulation

How is that "envelope" built? Through encapsulation — each layer wraps the one above with its own header:

Layer Wraps your data in
Application the HTTP request (GET / ...)
Transport a TCP segment (ports, sequence numbers)
Internet an IP packet (source & destination IP)
Link an Ethernet / Wi-Fi frame (MAC addresses)

Your HTTP data is wrapped in a TCP segment, wrapped in an IP packet, wrapped in a link-layer frame. Routers rewrite the frame at each hop but leave the IP packet's destination intact; the server unwraps the layers in reverse. Ports live in the TCP header: the server listens on 443, your device picks a random ephemeral source port, and the four-tuple (source IP:port, dest IP:port) uniquely identifies this connection.

Step 6 — TCP: the three-way handshake

Before any HTTP flows, TCP establishes a reliable, ordered connection with a three-way handshake:

Client: SYN → Server: SYN-ACK → Client: ACK → connection established

  • SYN — client proposes a starting sequence number.
  • SYN-ACK — server acknowledges and sends its own.
  • ACK — client acknowledges; the connection is open.

Why bother? TCP turns unreliable packets into a dependable byte stream: it detects loss and retransmits, reorders packets, and paces sending with flow and congestion control. The cost is one round-trip before your request even starts — which is why latency to the server matters so much, and why HTTP/3 uses QUIC over UDP to fold this into the encryption step and shave a round-trip.

Step 7 — TLS: turning HTTP into HTTPS

Because we used https, the client and server now negotiate an encrypted channel with a TLS handshake:

  1. ClientHello — supported ciphers, and SNI (the hostname, so servers hosting many sites know which certificate to send).
  2. ServerHello + certificate — the server sends its TLS certificate.
  3. Validation — the browser checks the certificate chains up to a trusted Certificate Authority, matches the hostname, and isn't expired or revoked.
  4. Key exchange — an ECDHE exchange derives a shared symmetric key that an eavesdropper can't reconstruct, giving forward secrecy.

After this, everything is encrypted and integrity-protected. TLS 1.3 completes in a single round-trip. This is why HTTPS is both private (nobody on the path can read it) and authentic (you're really talking to example.com, not an impostor).

Step 8 — The HTTP request

Now, over the encrypted TCP connection, the browser sends a small text request:

GET / HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 ...
Accept: text/html,application/xhtml+xml
Accept-Encoding: gzip, br
Cookie: session=abc123
  • The method (GET, POST, PUT, DELETE…) says what to do.
  • The Host header lets one server (one IP) serve many sites — virtual hosting.
  • Headers carry content negotiation, cookies, caching validators, and more.

Protocol version matters: HTTP/1.1 does one request at a time per connection; HTTP/2 multiplexes many requests over one connection (no more head-of-line blocking at the app layer); HTTP/3 runs that multiplexing over QUIC/UDP for resilience on lossy networks.

Step 9 — What the server actually does

The request rarely hits "the server" directly. A typical path:

Load balancer / reverse proxy → App server → Database & caches → Response built

  • A load balancer / reverse proxy (often nginx) accepts the connection — frequently where TLS terminates — and forwards to one of many app servers, using health checks to avoid dead ones.
  • The application server runs your code: checks the session cookie, queries a database and caches (Redis), calls other internal services, and assembles a response.
  • The result — an HTML page, or JSON for an API — is handed back up the chain.

All the reliability patterns you read about (multiple replicas, health checks, failover) live in this step.

Step 10 — The HTTP response

The server replies with a status line, headers, and a body:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 1256
Cache-Control: max-age=3600
Set-Cookie: session=abc123; Secure; HttpOnly

<!doctype html><html>...</html>
  • The status code summarises the outcome: 2xx success, 3xx redirect, 4xx your request was wrong (404 not found, 401 unauthorised), 5xx the server broke.
  • Content-Type tells the browser how to interpret the body; Cache-Control tells it how long it may reuse this response (skipping Steps 3–9 next time); Set-Cookie carries state back.

Step 11 — The browser turns bytes into pixels

Receiving HTML is only half the job. The browser now runs the critical rendering path:

  1. Parse HTML → DOM — the document becomes a tree of nodes.
  2. Parse CSS → CSSOM — stylesheets become a tree of style rules.
  3. Render tree — DOM + CSSOM combine into the visible elements and their computed styles.
  4. Layout (reflow) — the browser computes the exact geometry: where every box sits and how big it is.
  5. Paint — each element is drawn into layers of pixels.
  6. Composite — layers are combined (often on the GPU) and shown on screen.

Meanwhile, JavaScript is parsed and executed; by default a <script> blocks parsing (hence async and defer), and JS can mutate the DOM, triggering more layout and paint. Crucially, every subresource the HTML references — CSS files, JS, images, fonts — is another request, each potentially repeating DNS → TCP → TLS → HTTP (or reusing the open connection and HTTP/2 multiplexing). A "single" page load is often dozens of these journeys in parallel.

Putting it together — the timeline

Phase Typically What's happening
DNS ~0–20 ms name → IP (usually cached)
TCP handshake 1 round-trip reliable connection established
TLS handshake 1 round-trip (TLS 1.3) encrypted, authenticated channel
HTTP request/response 1 round-trip + server time the actual page
Render tens of ms parse, layout, paint, run JS
Subresources overlapping CSS/JS/images/fonts, each a mini-journey

Notice how much of the "wait" is round-trips, not bandwidth. That's why the big performance wins are about removing round-trips and moving the server closer: CDNs cut physical distance, HTTP/2 and /3 avoid repeated setup, caching skips whole phases, and TLS 1.3 trims a handshake.

Why this matters

Every layer is a place things go wrong — and a place to optimise:

  • DNS slow or wrong → the page hangs before it starts (check with dig).
  • Routing → a bad path or MTU issue shows up in traceroute/ping.
  • TLS → an expired or mis-chained certificate blocks the whole connection.
  • HTTP → a 5xx is the server; a 4xx is the request; a 3xx loop is a redirect misconfig.
  • Render → a render-blocking script or huge image is why the page is visually slow even when the server was fast.

Understanding the full path turns "the site is slow/down" from a shrug into a systematic diagnosis — you know which layer to interrogate and with which tool.

The same path powers everything

This isn't only about browsers. When a mobile app calls an API, when one microservice calls another, or when you run curl in a terminal, Steps 1–10 are identical — parse, DNS, route, TCP, TLS, HTTP. Only Step 11 (rendering) is browser-specific; an API client just parses the JSON body instead of painting pixels. Master this one path and you understand how all networked software talks.

curl -v is the fastest way to watch the journey happen — it narrates the resolved IP, the TLS handshake and certificate, the request headers it sent, and the response headers it received:

curl -v https://example.com
# * Trying 93.184.216.34:443...        <- routing + TCP
# * TLS 1.3 connection using ...        <- TLS handshake
# * Server certificate: CN=example.com  <- certificate validation
# > GET / HTTP/2                         <- the HTTP request
# < HTTP/2 200                           <- the response

Run it against a site you know and match each line to a step above; the whole abstract chain becomes concrete in one command.

Where to go next

DNS is the first hop in this whole journey and the one most people understand least — our free DNS: How the Internet Finds Things course takes that single step and expands it into the full picture (caching, records, DNSSEC, anycast). From there, the Linux and cloud tracks go deeper on the networking, TLS, and server-side pieces you just met. Now that you can narrate the whole path, each layer is something you can actually reason about.