DNS and what happens when you type a URL
45 min · Intermediate
Need help? Ask a tutor on WhatsApp (opens in a new tab)"What happens when you type a URL in the browser?" is one of the most asked placement questions, and it checks whether you can connect DNS, TCP, TLS and HTTP in the right order without freezing.
The DNS hierarchy: resolver, root, TLD and authoritative servers
DNS (Domain Name System) is the internet's phone book: it turns a name like www.example.com into the IP address a computer needs. It is a distributed hierarchy, so no single server knows every name.
The example resolves a name step by step on a cache miss: the resolver asks a root server, then the TLD server, then the authoritative server.
Example 1 · Iterative DNS resolution through the hierarchy
root = {"com": "a.gtld-servers.net", "in": "ns1.registry.in"}tld = {"example.com": "ns1.example-dns.com", "college.in": "ns.college.in"}authoritative = {"www.example.com": "93.184.215.14", "results.college.in": "103.21.4.10"}
def resolve(name): labels = name.split(".") tld_name = labels[-1] domain = ".".join(labels[-2:])
print(f"resolver -> root: where is .{tld_name}? -> {root[tld_name]}") print(f"resolver -> {root[tld_name]}: where is {domain}? -> {tld[domain]}") ip = authoritative[name] print(f"resolver -> {tld[domain]}: A record of {name}? -> {ip}") return ip
print("Answer:", resolve("www.example.com"))print("Answer:", resolve("results.college.in"))resolver -> root: where is .com? -> a.gtld-servers.net resolver -> a.gtld-servers.net: where is example.com? -> ns1.example-dns.com resolver -> ns1.example-dns.com: A record of www.example.com? -> 93.184.215.14 Answer: 93.184.215.14 resolver -> root: where is .in? -> ns1.registry.in resolver -> ns1.registry.in: where is college.in? -> ns.college.in resolver -> ns.college.in: A record of results.college.in? -> 103.21.4.10 Answer: 103.21.4.10
What this code does
- The resolver walks down the tree: root knows the TLD servers, the TLD server knows the domain's name servers, and only the authoritative server knows the final IP.
- The device made one recursive request; the resolver made three iterative ones. The server names and IPs here are examples, not live data.
Your device asks a recursive resolver (usually run by your ISP, your college or a public service), which does the hard work and returns the final answer. On a cache miss, the resolver asks a root server, which points to the TLD server for .com (top-level domain). The TLD server points to the domain's authoritative server, which holds the actual records and returns the IP. This chain of referrals is called iterative resolution; the device-to-resolver request is recursive ("give me the final answer").
Who is who:
- Root servers: 13 named root server identities (a to m), run as hundreds of machines worldwide.
- TLDs: generic such as
.com,.org, and country codes such as.in. - Authoritative server: the source of truth for one domain, set up by its owner or DNS provider.
- DNS queries use UDP port 53 by default; TCP 53 for large answers and zone transfers.
Order of execution
Order a DNS lookup
A laptop looks up www.example.com and nothing is cached. Put the steps in order.
DNS caching and record types
TTL (time to live) in DNS is the number of seconds an answer may be cached. The browser, the operating system and the resolver keep the answer until the TTL runs out, so most lookups never reach the root.
The first example is a DNS cache that expires entries by TTL. The second follows CNAME records until it reaches an A record.
Example 2 · A DNS cache with TTL
from typing import NamedTuple
class Entry(NamedTuple): ip: str expires_at: int
cache = {}upstream_queries = 0
def lookup(name, now): global upstream_queries entry = cache.get(name) if entry and now < entry.expires_at: return f"{entry.ip} (cache, {entry.expires_at - now}s left)" upstream_queries += 1 ip, ttl = "142.250.1.1", 300 # the answer from the resolver cache[name] = Entry(ip, now + ttl) return f"{ip} (asked resolver, TTL {ttl}s)"
for t in [0, 10, 299, 300, 310]: print(f"t={t}s {lookup('www.google.com', t)}")print("Upstream queries:", upstream_queries)t=0s 142.250.1.1 (asked resolver, TTL 300s) t=10s 142.250.1.1 (cache, 290s left) t=299s 142.250.1.1 (cache, 1s left) t=300s 142.250.1.1 (asked resolver, TTL 300s) t=310s 142.250.1.1 (cache, 290s left) Upstream queries: 2
What this code does
- The first lookup goes upstream and stores the answer for 300 seconds. Lookups at 10 s and 299 s are served from the cache.
- At exactly 300 s the entry has expired, so the cache asks again and starts a new TTL. Five lookups cost only two upstream queries; time is passed in as a number to keep the run repeatable.
Example 3 · Following CNAME records to an A record
a_records = {"edge.cdnprovider.net": "151.101.1.10", "mail1.shop.in": "203.0.113.25"}cnames = {"www.shop.in": "shop.cdnprovider.net", "shop.cdnprovider.net": "edge.cdnprovider.net"}mx = {"shop.in": "10 mail1.shop.in"}
def resolve_a(name): hops = 0 while name in cnames: print(f" CNAME {name} -> {cnames[name]}") name = cnames[name] hops += 1 if hops > 5: return "CNAME loop" return a_records.get(name, "NXDOMAIN (no such name)")
print("A for www.shop.in:")print(" =", resolve_a("www.shop.in"))print("MX for shop.in:", mx["shop.in"])print("A for old.shop.in:", resolve_a("old.shop.in"))A for www.shop.in: CNAME www.shop.in -> shop.cdnprovider.net CNAME shop.cdnprovider.net -> edge.cdnprovider.net = 151.101.1.10 MX for shop.in: 10 mail1.shop.in A for old.shop.in: NXDOMAIN (no such name)
What this code does
- A CNAME is an alias: the resolver follows it to the next name until it finds an A record. CDNs use this so a shop can point
wwwat the CDN without knowing its IPs. - MX tells mail servers where to deliver email for
shop.in. A name with no records gives NXDOMAIN, the DNS "not found" answer.
A changed DNS record can take time to be seen everywhere, because cached copies live until their TTL ends. A domain has several kinds of records. You must know four: A (name to IPv4), AAAA (name to IPv6), CNAME (an alias that points to another name) and MX (the mail servers for the domain, with a priority).
Examples:
- A:
example.com → 93.184.215.14. AAAA:example.com → 2606:2800:21f:cb07:6820:80da:af6b:8b2c. - CNAME:
www.shop.in → shop.cdnprovider.net, then that name's A record gives the IP. - MX:
shop.in → 10 mail1.shop.in; the lower number is tried first. - Also useful: NS (which servers are authoritative), TXT (text, e.g. email verification), PTR (IP to name).
The full URL journey
The URL journey is the fixed chain of steps from typing https://www.example.com/results to seeing the page: parse, cache, DNS, TCP, TLS, HTTP request, server work, response and render.
The example parses a URL into scheme, host, port and path, which is the first step of the journey.
Example 4 · Parsing a URL before the journey starts
from urllib.parse import urlsplit
DEFAULT_PORTS = {"http": 80, "https": 443}
urls = [ "https://www.example.com/results?roll=21#marks", "http://localhost:8080/api/v1/products", "https://exam.college.in:8443/hall-ticket",]for text in urls: u = urlsplit(text) port = u.port or DEFAULT_PORTS[u.scheme] # u.port is None when the URL has no port print(text) print(f" scheme={u.scheme} host={u.hostname} port={port} path={u.path} " f"query={u.query or '-'} fragment={u.fragment or '-'}")https://www.example.com/results?roll=21#marks scheme=https host=www.example.com port=443 path=/results query=roll=21 fragment=marks http://localhost:8080/api/v1/products scheme=http host=localhost port=8080 path=/api/v1/products query=- fragment=- https://exam.college.in:8443/hall-ticket scheme=https host=exam.college.in port=8443 path=/hall-ticket query=- fragment=-
What this code does
URI.createonly splits the text; it does no network work. When the URL has no port,getPort()returns -1 and the browser uses the scheme's default: 443 for HTTPS, 80 for HTTP.- The fragment (
#marks) is never sent to the server; the browser uses it to scroll inside the page. The host is what DNS resolves next.
The browser parses the URL, resolves the host with DNS, opens a TCP connection to port 443, does a TLS handshake to agree on encryption and check the certificate, and sends an HTTP request. The server (often behind a load balancer) sends an HTTP response with a status code, headers and HTML. The browser parses the HTML, fetches CSS, JavaScript and images (more requests, often on the same connection), builds the page and renders it on screen.
Extra facts:
- Cache checks come first: browser, OS, then resolver. HSTS can turn
http://intohttps://before any request. - The request leaves through ARP to the gateway and NAT at the router, as in the previous lessons.
- Rendering: HTML → DOM, CSS → CSSOM, then layout and paint; JavaScript can change the page.
Order of execution
Order the URL journey
You type https://www.example.com and press Enter. Put the steps in order.
Model answer to "What happens when you type a URL?"
Structure beats detail. Walk through the layers in order, one or two sentences each, and finish in about two minutes. Then offer to go deeper: "I can go into DNS or the TLS handshake in more detail if you like."
1. Browser parses the URL: scheme https, host www.example.com, port 443, path /results.2. It checks caches; if no IP is cached, the OS asks the DNS resolver.3. The resolver asks root -> .com TLD -> authoritative server, gets the A record, caches it.4. Browser opens a TCP connection to that IP on port 443 (SYN, SYN-ACK, ACK).5. TLS handshake: server sends its certificate, browser verifies it, they agree on keys.6. Browser sends "GET /results" with headers like Host, cookies and Accept.7. Server (via load balancer, app, database) builds the page and replies 200 OK with HTML.8. Browser parses HTML, fetches CSS/JS/images, builds DOM and CSSOM, lays out, paints.Use the same skeleton every time: parse, cache, DNS, TCP, TLS, HTTP request, server work, response, rendering. Interviewers check that you know the order and can explain any step they pick.
Example 5 · The journey as a timeline
steps_ms = { "Parse URL, check caches": 1, "DNS lookup (cache miss)": 40, "TCP handshake (1 RTT)": 30, "TLS 1.3 handshake (1 RTT)": 30, "HTTP request + server work": 120, "Download HTML": 30, "Fetch CSS/JS/images": 150, "Parse, layout, paint": 60,}
clock = 0for step, ms in steps_ms.items(): clock += ms print(f"{step:<28} +{ms:>3} ms (t={clock} ms)")
saved = sum(steps_ms[k] for k in ("DNS lookup (cache miss)", "TCP handshake (1 RTT)", "TLS 1.3 handshake (1 RTT)"))print(f"Second visit with cached DNS and a reused connection saves {saved} ms")Parse URL, check caches + 1 ms (t=1 ms) DNS lookup (cache miss) + 40 ms (t=41 ms) TCP handshake (1 RTT) + 30 ms (t=71 ms) TLS 1.3 handshake (1 RTT) + 30 ms (t=101 ms) HTTP request + server work +120 ms (t=221 ms) Download HTML + 30 ms (t=251 ms) Fetch CSS/JS/images +150 ms (t=401 ms) Parse, layout, paint + 60 ms (t=461 ms) Second visit with cached DNS and a reused connection saves 100 ms
What this code does
- The numbers are illustrative, assuming a 30 ms round trip; real times depend on distance and network. The order of steps is what interviewers check.
- DNS, TCP and TLS are pure setup costs. Caching and connection reuse remove them on later requests, which is why the second page of a site loads faster.
Find the bug
Spot the weak answer line
Each answer to "what happens when you type a URL" has one wrong line. Tap it, then check the fix.
A candidate gives the steps.
Round 1 of 3Follow-up questions interviewers ask
A CDN (content delivery network) keeps copies of a site on servers near users. Its DNS answers with the IP of a nearby server, so a student in Chennai and one in Delhi may get different IPs for the same name.
After the model answer, interviewers dig into one step. Common follow-ups: "What if the DNS record is cached?", "Why TCP and not UDP for HTTP?", "What does the certificate prove?" and "How does a CDN change this?".
Next step
Check your understanding
12 quick questions