AlgoPlusAlgoPlus
Learn/Web
Lesson

From URL to Pixels

The page-load waterfall: DNS, TCP, TLS, HTTP request, TTFB, download, parse, render — each phase waiting on the last.

9 min read Watch it move Build it

Pressing Enter doesn't fetch a page in one go. The browser runs a fixed line of phases — find the server, connect, secure it, ask, wait, download, draw — and each one only starts *after* the previous finishes. That serial dependency is why the delays stack up, and why making a page feel fast is mostly about shrinking this waterfall.

The waterfall, phase by phase

  1. 1DNS — resolve the human name (example.com) into a numeric IP address the network can route to. (The full mechanics live in the Networking module.)
  2. 2TCP connect — open a reliable connection with the three-way handshake (SYN, SYN-ACK, ACK): one round trip of setup before any page data can move.
  3. 3TLS handshake — on https, agree on encryption keys and verify the server's certificate, securing the channel. Adds one or two more round trips.
  4. 4HTTP request — send the tiny GET / message. Cheap to send; the cost is the wait for the reply.
  5. 5TTFB — Time To First Byte: the gap from sending the request to the first byte of the response. Usually the biggest slice, and where a slow server shows up.
  6. 6Download — stream the HTML over the connection. Bigger pages and slower links stretch this out.
  7. 7Parse + render — hand the HTML to the rendering pipeline (DOM → CSSOM → render tree → layout → paint) to draw the first pixels.
Round trips are the hidden tax
DNS, TCP, and TLS are each round-trip bound, not bandwidth-bound — a fatter internet connection doesn't speed them up, only shorter physical distance and fewer handshakes do. This is why reusing a connection (keep-alive) and terminating TLS close to the user (a CDN) help so much: they cut round trips out of the front of the waterfall.

A worked walk — loading a page

Say each network round trip to the server takes 50ms. DNS costs one (~50ms), TCP one (~50ms), TLS two (~100ms), and then the request goes out. The server thinks for 80ms before the first byte returns — that 80ms is the TTFB. The 40KB of HTML then downloads in ~30ms, and parsing plus first paint takes another ~40ms. Total to first paint: roughly 350ms, of which nearly *two-thirds is setup and waiting* before a single byte of content arrives. Trim a redirect or a redundant handshake and you shave a whole round trip off the front.

Render-blocking resources restart the clock
The first paint doesn't happen the instant the HTML lands. While parsing, the browser hits <link rel="stylesheet"> and <script> tags that are render-blocking — it must fetch and process them before painting. Each one can add its own mini-waterfall, so a page with a slow stylesheet in the <head> stays blank long after the HTML is downloaded.

Measuring it — Navigation Timing

The browser records the timestamp of every phase in the Navigation Timing API, so you can see the waterfall for a real visit rather than guessing.

const nav = performance.getEntriesByType('navigation')[0];
console.log('DNS   ', nav.domainLookupEnd - nav.domainLookupStart);
console.log('TCP   ', nav.connectEnd - nav.connectStart);
console.log('TTFB  ', nav.responseStart - nav.requestStart);
console.log('Download', nav.responseEnd - nav.responseStart);
OperationTimeSpace
DNS + TCP + TLS · latency-bound: distance, not bandwidth~1–4 round trips
TTFB · often the largest single sliceserver-dependent
Download + render · where page weight and blocking assets bitebytes ÷ bandwidth + parse
Check yourself
The HTML finished downloading but the screen is still blank. What is the most likely cause?