The request
You type http://www.example.com. DNS gave the browser 203.0.113.10, so it opens a TCP connection to port 80: SYN, SYN-ACK, ACK. HTTP messages are just text that rides on this connection.
The browser writes a request. The first line names a method (GET means "send me this"), a path and the version. Header lines follow. Host is required in HTTP/1.1: one server can host many sites. An empty line ends the headers.
The request crosses the connection as plain text. The server reads it top to bottom: GET, so it should send something back; /index.html, which file; Host, which of its websites.
The response
The response starts with a status line: the version, a three-digit code and a short reason. 200 OK means it worked. The first digit gives the family: 2xx success, 3xx look elsewhere, 4xx a problem with the request, 5xx a problem on the server.
Headers describe the body. Content-Type says it is HTML. Content-Length says it is 1256 bytes. Cache-Control lets the browser reuse it for an hour. After an empty line comes the body: the page itself.
Ask for /old-page and the server may answer 301 Moved Permanently, with a Location header. The browser follows it and asks again. A missing page gets 404 Not Found; a crash on the server gets 500.
State and cookies
HTTP is stateless: every request stands alone. The server keeps no memory between them, so your second request looks just like a stranger's. It cannot tell you are the same person who asked a moment ago.
You log in: POST sends the form in the body. The answer carries Set-Cookie. The browser keeps the cookie in its jar and sends it back in a Cookie header on every later request to this site. Now the server knows you.
Faster versions
HTTP/1.1 keeps the connection open after a response, so the next request skips a new handshake. But on one connection the answers come back in order, one after another, so a slow answer holds up the rest.
HTTP/2 sends many requests at once on one connection. Each request and its response form a numbered stream, cut into small binary frames that take turns. Answers can come back in any order. Browsers use HTTP/2 only with HTTPS.
HTTP/3 runs on QUIC, which uses UDP and builds in streams and TLS encryption. Under TCP, one lost packet stalls every stream. Under QUIC it delays only its own stream; the others carry on. Servers announce HTTP/3 with an Alt-Svc header.
The messages, step by step
;; step 1/11 · connect ;; client → server TCP 192.0.2.7:51514 → 203.0.113.10:80 SYN → · ← SYN-ACK · ACK → (the TCP lesson's three-way handshake) port 80 = plain http:// (https:// uses 443 and adds TLS first) TCP delivers the bytes in order; HTTP decides what they say
Illustrative values: the page size (1256 bytes), the paths, the login form and the port 51514. The cookie value SID=31d4d96e407aad42 is the example from RFC 6265. The cards show a shortened message: a real browser sends more headers (User-Agent, Accept-Language, Accept-Encoding …) and the server adds Date, Server and others.