Lesson 1 of 106 min read

How the Web Works

Share:WhatsAppLinkedIn

What you'll build

By the end of this lesson you will be able to run a tiny local web server, open it in your browser, watch the HTTP request in DevTools, and explain every step that happened, from typing a URL to seeing the page. You will also know how to use curl to inspect raw HTTP responses, which is the fastest debugging tool you will ever learn.

Concepts

The client-server model

A "client" is any program that asks for something. A "server" is any program that answers. Your browser is a client. When you open https://class-central.com, the browser sends a request to a server somewhere on the internet, and the server sends back HTML.

That is it. Every web interaction, loading a page, submitting a login form, streaming a video, is just a client asking and a server answering, repeatedly.

Browser                              Web Server
  |------ GET /index.html --------->|
  |<----- 200 OK + HTML body -------|

DNS: how names become numbers

Computers talk to each other using IP addresses like 142.250.195.46. Humans prefer names like google.com. DNS (Domain Name System) is the phone book that maps one to the other.

When you type google.com and press Enter, your OS asks a DNS resolver (usually your ISP's, or 8.8.8.8) to translate that name into an IP. This takes maybe 1, 50 ms on a first visit. The result is cached so subsequent visits are instant.

You can inspect this yourself:

# Ask Google's public DNS what IP hosts class-central.com
nslookup class-central.com 8.8.8.8

# Or with the dig tool (more detail)
dig class-central.com

HTTP: the language of the web

HTTP (Hypertext Transfer Protocol) is a plain-text protocol. A request looks like this:

GET /courses HTTP/1.1
Host: www.class-central.com
Accept: text/html

And the response looks like:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 12483

<!DOCTYPE html>
<html>...

The first line of a response always has a status code. The ones you will hit every day:

Code Meaning
200 OK, everything worked
301 Moved permanently, follow the redirect
404 Not found, the URL does not exist on the server
500 Internal server error, the server crashed

What the browser does on Enter

This is the full sequence. Understanding it lets you locate bugs at the right layer:

  1. Parse the URL, scheme (https), host (class-central.com), path (/courses).
  2. DNS lookup, resolve the hostname to an IP.
  3. TCP connection, open a reliable connection to port 443 (HTTPS) or 80 (HTTP).
  4. TLS handshake (HTTPS only), verify the server's certificate, establish encryption.
  5. Send the HTTP request, GET /courses HTTP/1.1.
  6. Receive the response, status line, headers, then the body (HTML).
  7. Parse and render, the browser builds the DOM from HTML, fetches CSS and JS referenced in that HTML, runs the JS, and paints pixels.

Steps 1, 6 happen before you see anything. That is why a slow DNS server or a missing TLS certificate can make a page feel broken even before a single byte of HTML arrives.

Using curl to see raw HTTP

curl is a command-line tool that makes HTTP requests and prints the response. It is your best friend for debugging APIs and servers.

# Basic GET, prints the JSON body
curl https://jsonplaceholder.typicode.com/todos/1

# Show headers too
curl -i https://jsonplaceholder.typicode.com/todos/1

# Follow redirects, show timing
curl -L -w "\n\nTotal time: %{time_total}s\n" https://google.com -o /dev/null -s

Hands-on

Let's serve a real web page locally and watch what happens in the browser.

Step 1: Create a tiny HTML file.

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My First Server</title>
</head>
<body>
  <h1>Hello from my server!</h1>
  <p>The browser fetched this from localhost:8000.</p>
</body>
</html>

Step 2: Start Python's built-in HTTP server in the same folder.

python3 -m http.server 8000

You will see: Serving HTTP on 0.0.0.0 port 8000.

Step 3: Open http://localhost:8000 in your browser.

You will see the page. Now switch to the terminal, you will see the log line:

127.0.0.1 - - [10/May/2026 10:22:01] "GET / HTTP/1.1" 200 -

That is the raw HTTP request your browser sent, logged by the server.

Step 4: Open DevTools (F12) → Network tab → reload the page.

Click on the first request (localhost). You will see:

  • Request Headers, what the browser sent, including Host, User-Agent, Accept.
  • Response Headers, what the server replied with, including Content-Type and Content-Length.
  • Status Code, 200.
  • Timing, how long each step took.

Try changing http://localhost:8000/index.html to http://localhost:8000/nope.html. You will see a 404 in the terminal and in DevTools. That is the server saying "I do not have a file called nope.html".

Step 5: Do the same request with curl.

curl -i http://localhost:8000/index.html

Output:

HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.12.0
Date: Sat, 10 May 2026 04:52:01 GMT
Content-type: text/html
Content-Length: 196
Last-Modified: Sat, 10 May 2026 04:50:00 GMT

<!DOCTYPE html>
<html lang="en">
...

Everything above the blank line is the header. Everything after is the body. When you understand this separation you can debug almost any web problem.

Common pitfalls

  • Confusing HTTP and HTTPS. A browser that loads http:// sends your data in plain text. Use HTTPS in production always. Locally, plain HTTP is fine.
  • Thinking 404 means the server is down. It means the server is up but that specific file does not exist. Check your path.
  • DNS cache confusing you. If you change a DNS record and your browser still shows the old site, run ipconfig /flushdns (Windows) or sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder (Mac). Or just open an incognito tab and wait a few minutes.
  • Port conflicts. If python3 -m http.server 8000 says "Address already in use", another process owns port 8000. Use 8080 or 9000 instead.
  • CORS errors in the browser, but curl works fine. CORS is a browser-only restriction. The server response is the same; the browser just refuses to give it to your JavaScript. This is expected behaviour, not a server bug.

What to try next

  1. Modify index.html to link to a style.css file. Watch two separate requests appear in DevTools when you reload, one for HTML, one for CSS.
  2. Use curl -X POST -d '{"name":"test"}' -H "Content-Type: application/json" https://jsonplaceholder.typicode.com/posts and read the JSON response. This is how every form submission and API call works under the hood.
  3. Look up the HTTP status code 418 ("I'm a teapot") and find which RFC defines it. This will teach you that RFCs, the actual specifications behind HTTP, are very readable documents, not just dry bureaucracy.

Test Your Knowledge

Take a quick quiz on this lesson

Start Quiz →

Prefer watching over reading?

Subscribe for free.

Subscribe on YouTube