π What Happens Between Typing a URL and Seeing the Page
A deep dive into the journey of a single URL β URL parsing, DNS resolution, TCP/TLS handshakes, HTTP requests, server processing, and browser rendering β with a full timing breakdown.
π― The Question Every Interviewer Loves
βWhat happens when you type
https://example.cominto your browser and press Enter?β
This question endures because it touches every layer of the networking stack β application, transport, network, link, and physical. A complete answer touches on 8 distinct phases. Here they are, from keystroke to pixels.
1οΈβ£ URL Parsing and HSTS Check
Before anything leaves your machine, the browser parses the URL into its components:
| Component | Value |
|---|---|
| Protocol | https |
| Hostname | example.com |
| Port | 443 (implied by HTTPS) |
| Path | / (default) |
| Fragment | none |
The browser then checks its HSTS (HTTP Strict Transport Security) preload list. If the domain is found, the browser refuses to make an insecure HTTP connection β it upgrades directly to HTTPS. This prevents SSL-stripping attacks even on the first request.
If the domain is not preloaded, the browser sends a plain HTTP request first and relies on the serverβs Strict-Transport-Security response header to remember the upgrade for future visits.
2οΈβ£ DNS Resolution
The browser needs the serverβs IP address. It checks a chain of caches:
Browser cache β OS cache β Router cache β ISP DNS β Recursive resolver
If none of the caches have the mapping, the recursive resolver (usually your ISPβs or Cloudflareβs 1.1.1.1) begins the lookup:
- Root nameserver β tells the resolver where the
.comTLD nameservers are - TLD nameserver β tells the resolver where
example.comβs authoritative nameservers are - Authoritative nameserver β returns the actual A (IPv4) or AAAA (IPv6) record
Browser Resolver Root (.com) TLD Authoritative
β β β β
βββ query: βββββββΊ β β β
β example.com βββ where's βββΊ β β
β β .com? β β
β ββββ go ask βββββ β
β β TLD β β β
β βββ where's βββββββββββββββΊ β
β β example? β β
β ββββββββββββ 93.184.216.34 ββ
ββββ 93.184.216.34ββ β β
Typical timing: 20β50ms for a cold cache, <1ms for a warm cache.
π§ Modern DNS Optimizations
- DNS prefetching: Browsers eagerly resolve domain names found in
<a>tags before the user clicks - DNS-over-HTTPS (DoH): Encrypts DNS queries to prevent snooping (used by Firefox, Chrome)
- DNS-over-TLS (DoT): Alternative encrypted DNS, preferred by Android
3οΈβ£ TCP Handshake
With the IP address known, the browser opens a TCP connection to port 443. TCP provides reliable, ordered delivery over an unreliable IP network. The three-way handshake establishes a connection:
Client Server
β β
βββββββ SYN βββββββββββββββΊ β Client: "Hey, let's talk"
β β
βββββββ SYN-ACK ββββββββββ β Server: "OK, I'm ready. You?"
β β
βββββββ ACK βββββββββββββββΊ β Client: "Confirmed."
β β
Each unacknowledged segment triggers a retransmission, and the round-trip time (RTT) determines the minimum latency. On a 30ms RTT connection, the TCP handshake alone takes 60ms (one round trip for SYN β SYN-ACK, then ACK is the second).
TCP Fast Open (TFO) eliminates this on repeat connections by sending data inside the SYN packet, saving one RTT. Adoption is limited (~10% of servers).
4οΈβ£ TLS 1.3 Handshake
Plain TCP gets you a raw pipe, but you need encryption. TLS 1.3 (RFC 8446) reduced the handshake from 2 RTTs (TLS 1.2) to 1 RTT for fresh connections and 0 RTT for resumed ones.
Client Server
β β
βββ ClientHello βββββββββββΊ β Key share, supported ciphers, random nonce
β (public key share) β
β β
ββββ ServerHello βββββββββββ Cipher choice, server cert + signature
β + Cert + Finished β
β β
βββ Finished ββββββββββββββΊβ Client verifies cert, sends Finished
β β
ββββββ Encrypted Data ββββΊ β Application data begins immediately
Certificate Verification
The browser checks:
- Certificate chain β Is the cert signed by a trusted CA?
- Hostname match β Does the certβs Common Name or SAN match
example.com? - Expiry β Is the cert still valid?
- Revocation β Is the cert revoked? (via OCSP stapling, not CRL β OCSP is faster)
Typical timing: 1β2 RTT + certificate validation (~50β200ms total). With TLS 1.3 0-RTT resumption, returning visitors skip the handshake entirely.
5οΈβ£ HTTP Request
With a secure channel established, the browser sends an HTTP request:
GET / HTTP/1.1
Host: example.com
Accept: text/html,application/xhtml+xml,...
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
HTTP/1.1 vs HTTP/2 vs HTTP/3
| Feature | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| Transport | TCP | TCP | QUIC (UDP) |
| Multiplexing | β (6 connections) | β (streams) | β (streams) |
| HOL blocking | Request-level | TCP-level | β None |
| Header compression | β | HPACK | QPACK |
| Server push | β | β | β |
| Connection migration | β | β | β |
| 0-RTT | β | β | β |
HTTP/1.1: One request per connection, limited to ~6 parallel connections per domain. Head-of-line blocking means one slow response blocks everything behind it.
HTTP/2: Multiplexes multiple streams over a single TCP connection. But TCP-level HOL blocking remains β if a single TCP packet is lost, all streams wait for the retransmission.
HTTP/3: Built on QUIC (RFC 9000), which runs over UDP. Each stream is truly independent. A lost packet only blocks its own stream. Connection migration lets you switch from Wi-Fi to cellular without dropping the connection.
Adoption as of mid-2026: HTTP/2 ~65%, HTTP/3 ~35%, HTTP/1.1 ~5% (mostly legacy).
6οΈβ£ Server Processing
The request arrives at the server. In a modern architecture, it passes through multiple layers:
Client
β
βΌ
CDN (Cloudflare / Fastly / Akamai)
β ββ Cached static assets served here
βΌ
Load Balancer (Nginx / HAProxy / AWS ALB)
β ββ TLS termination, routing, health checks
βΌ
Application Server (Nginx + uWSGI / Node.js / FastAPI)
β ββ Session middleware, auth, business logic
βΌ
Application Code
β ββ Template rendering, API calls, auth checks
βΌ
Database (PostgreSQL / Redis / Memcached)
β ββ Query execution, cache lookup
βΌ
Response (the other way back)
CDN Caching
If the CDN has a cached copy of the response (common for static assets like CSS, JS, images), the request never reaches the origin server. CDN cache hits typically take 5β20ms; cache misses add 200β500ms for origin processing.
Server-Side Timing Breakdown
| Phase | Typical Time |
|---|---|
| TLS termination (LB) | 1β5ms |
| Request routing | 0.1β1ms |
| Auth/session lookup | 5β20ms |
| Application logic | 20β200ms |
| Database queries | 5β100ms |
| Response serialization | 1β10ms |
| Total server time | 50β500ms |
7οΈβ£ Parsing HTML, CSS, and JavaScript
The browser receives the response β typically an HTML document. Parsing begins immediately, even before the full response arrives (streaming parser).
Bytes β Characters β Tokens β Nodes β DOM Tree
The Parse Pipeline
- HTML parsing β Converts bytes to DOM nodes. When the parser encounters
<script>tags (withoutasyncordefer), parsing blocks until the script is fetched and executed. - CSS parsing β CSS is render-blocking. The browser wonβt render anything until the CSSOM is built. Inline CSS is free; external stylesheets block the first paint.
- JavaScript execution β JS can modify the DOM (via
document.write) and the CSSOM (viaCSSStyleSheet), so the parser must wait.
Preload Scanner
Modern browsers deploy a preload scanner β a secondary parser that skims the raw bytes for resource URLs (images, scripts, stylesheets, fonts) and kicks off fetches in parallel before the main parser reaches them. This is why putting <link rel="preload"> or <link rel="preconnect"> in the <head> can dramatically improve load times.
8οΈβ£ Rendering: DOM β CSSOM β Render Tree β Layout β Paint β Compositing
This is where the page actually appears on screen. The rendering pipeline runs in the browserβs main thread (the βcritical rendering pathβ):
Input: DOM Tree + CSSOM
β
βΌ
1. Render Tree Construction
β ββ Combine DOM + CSSOM
β ββ Include only visible elements (no display:none)
βΌ
2. Layout (Reflow)
β ββ Calculate geometry: position, width, height
β ββ Every element's box model is computed
βΌ
3. Paint (Rasterization)
β ββ Fill pixels: colors, borders, shadows, text
β ββ Layers are painted independently
βΌ
4. Compositing
β ββ Combine painted layers into final image
β ββ GPU-accelerated via compositor thread
βΌ
Output: Screen pixels
Layout Thrashing
Every time you read a layout property (offsetHeight, getBoundingClientRect()) and then write a style change in the same frame, the browser must recalculate layout synchronously. This is called βlayout thrashingβ and is a common cause of jank.
// Bad β forces synchronous layout twice
const height = element.offsetHeight;
element.style.height = `${height + 10}px`;
element.style.width = `${element.offsetWidth + 10}px`;
// Good β batch reads then writes
const height = element.offsetHeight;
const width = element.offsetWidth;
element.style.height = `${height + 10}px`;
element.style.width = `${width + 10}px`;
Compositor-Only Properties
Modern browsers can animate transform and opacity entirely on the compositor thread, bypassing layout and paint entirely. This is why will-change: transform is the go-to performance hint for animations.
π Full Timing Breakdown
Hereβs where the milliseconds go for a typical page load with a cold cache:
| Phase | Typical Time | % of Total |
|---|---|---|
| DNS resolution | 20β50ms | 2β5% |
| TCP handshake | 30β100ms (1 RTT) | 3β10% |
| TLS 1.3 handshake | 30β100ms (1 RTT) | 3β10% |
| HTTP request (latency) | 30β100ms (1 RTT) | 3β10% |
| Server processing | 100β500ms | 15β50% |
| HTML parsing + CSSOM | 50β200ms | 5β20% |
| Render tree + layout | 30β100ms | 3β10% |
| Paint + composite | 16β50ms | 2β5% |
| Total | 500msβ2s | 100% |
With a warm cache (repeat visit, CDN cache hit, TLS 0-RTT), the same page loads in 100β400ms.
π‘ Key Takeaways
- DNS is the hidden bottleneck β a cold DNS lookup can add 50+ms that most users notice
- TLS 1.3 is a huge win β 1 RTT instead of 2, plus 0-RTT for repeat visitors
- HTTP/3 eliminates HOL blocking β UDP + QUIC means one lost packet doesnβt stall everything
- CDNs matter more than you think β moving content geographically closer to users cuts latency by 50β200ms
- The render pipeline is fragile β layout thrashing from bad JS can undo all the network gains
- Every millisecond counts β Amazon found that every 100ms of latency costs 1% in revenue
The beauty of this question is that thereβs always more depth. You can drill into congestion control, into the V8 parser, into the GPU compositor. The layers keep unfolding.