Clients, Servers and HTTP

Clients, Servers and the HTTP Request-Response Cycle

The web is a client-server system. A client (a browser, a crawler, the curl 3,008 command) sends a request; a server (nginx 75 , Apache, Caddy 7,400 or a Node.js 2,131 process listening on a port) sends back a response. They speak HTTP, the Hypertext Transfer Protocol, one request and one response at a time. HTTP is stateless: the server remembers nothing between requests unless the client presents something that identifies it, such as a cookie or an Authorization header.

A URL tells the client everything it needs to start. In https://shop.example.com:443/cart?id=42#total, https is the scheme, shop.example.com the host, 443 the port (the HTTPS default, normally omitted), /cart the path, ?id=42 the query and #total the fragment, which never leaves the browser.

From Enter to first byte

Loading a page over a fresh connection takes five stages, and each one appears as a colored bar in the Network panel's timing view (Network and Lighthouse):

  1. DNS lookup. The browser asks a resolver to translate the host name into an IPv4 or IPv6 address. Results are cached by the browser, the operating system and the resolver, so repeat visits usually skip this.

  2. Transport connection. For HTTP/1.1 and HTTP/2 the browser opens a TCP connection with a three-way handshake (SYN, SYN-ACK, ACK). HTTP/3 uses QUIC, which runs over UDP.

  3. TLS handshake. The server proves its identity with a certificate and both sides agree on encryption keys. TLS 1.3 (RFC 8446, 2018) does this in one round trip; QUIC folds the transport and TLS 1.3 handshakes into one.

  4. Request and wait. The browser sends the request; the time until the first byte of the reply arrives (TTFB) is mostly the server's work plus distance.

  5. Response download. The HTML streams in, and the browser starts parsing before it has all of it, requesting stylesheets, scripts, fonts and images as it discovers them, usually over the same connection.

Setting up a new connection: QUIC combines the transport and TLS handshakes, saving a round trip
Setting up a new connection: QUIC combines the transport and TLS handshakes, saving a round trip
Reading a real exchange

curl -v prints both halves of the conversation: lines starting with > are sent, < are received and * are curl's own notes.

Watching DNS, connection, request and response with curlShell
curl -sv -o /dev/null https://example.com/
Output
* Host example.com:443 was resolved.
* IPv6: 2606:4700:10::ac42:93f3, 2606:4700:10::6814:179a
* IPv4: 172.66.147.243, 104.20.23.154
*   Trying [2606:4700:10::ac42:93f3]:443...
* ALPN: curl offers http/1.1
* ALPN: server accepted http/1.1
* Established connection to example.com (2606:4700:10::ac42:93f3 port 443)
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/8.19.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html
< Server: cloudflare
< Age: 12608
< cf-cache-status: HIT
<
{ [571 bytes data]

A request is a method and path, a set of headers, a blank line and an optional body. A response is a status line, headers, a blank line and the body. Methods say what you want: GET reads, POST submits, PUT and PATCH replace or modify, DELETE removes, HEAD fetches headers only. Status codes are grouped by their first digit: 1xx informational (103 Early Hints), 2xx success (200 OK, 204 No Content), 3xx redirection (301, 304 Not Modified), 4xx client errors (400, 401, 403, 404) and 5xx server errors (500, 502, 503). Headers carry everything else: content type, caching (Cache-Control, ETag), cookies, compression and security policies. The Age and cf-cache-status: HIT headers above reveal that a Cloudflare 2 CDN edge answered from its cache without contacting the origin server.

Three versions, one set of semantics

Methods, status codes and headers are defined once, in RFC 9110 (HTTP Semantics). The versions differ only in how those messages travel. W3Techs 13,241 reported in September 2026 that 40.7% of websites support HTTP/3.

HTTP versions share the semantics of RFC 9110 but change the wire format
Version Standardized Transport What it changed
HTTP/1.0 RFC 1945, 1996 TCP Headers, status codes, content types
HTTP/1.1 RFC 2068, 1997; now RFC 9112 TCP Persistent connections, Host header, chunked bodies
HTTP/2 RFC 7540, 2015; now RFC 9113 TCP + TLS Binary frames, many streams on one connection, header compression
HTTP/3 RFC 9114, 2022 QUIC over UDP No TCP head-of-line blocking, faster setup, survives network changes

HTTP/2 multiplexes requests over one TCP connection, but TCP delivers bytes strictly in order, so one lost packet stalls every stream. QUIC tracks streams independently, and its connection IDs let a download survive a phone's switch from Wi-Fi to mobile data.