How HTTP works
How the Hypertext Transfer Protocol carries the web, from URLs, requests, methods and status codes to caching, cookies and the three versions in use today, HTTP/1.1, HTTP/2 and HTTP/3.
Every page on the web, every image on it and most of the data that apps exchange travel by the Hypertext Transfer Protocol (HTTP). Its idea is simple: a client sends a request for a resource, and a server sends back a response. Around this exchange, HTTP defines a precise vocabulary of methods, status codes and header fields that lets browsers, servers, caches and proxies made by different people work together.
This article is the last step of a journey. Before an HTTP request can be sent, the client looks up the server’s name with DNS, reaches its IP address, opens a TCP connection and secures it with TLS. Then HTTP begins.
A short history
HTTP has carried the World Wide Web since 1990 (RFC 1945). Its first version, later called
HTTP/0.9, knew a single command: GET, followed by a path, answered with the document and nothing
else. HTTP/1.0, described in RFC 1945 in 1996 by Tim Berners-Lee, Roy Fielding and Henrik Frystyk,
added headers, status codes and other methods. HTTP/1.1 followed in 1997 and was revised
several times; it is still in daily use.
The next two versions changed how messages travel, not what they mean. HTTP/2 (2015), which drew on an earlier experimental protocol called SPDY, replaced the text format with binary frames and carried many requests over one connection at once. HTTP/3 (2022) moved HTTP onto QUIC, a new transport protocol built on UDP. In June 2022, the IETF republished the whole family in a new structure: HTTP Semantics (RFC 9110), which is the same for every version, plus one document each for caching (RFC 9111), HTTP/1.1 (RFC 9112), HTTP/2 (RFC 9113) and HTTP/3 (RFC 9114).
Resources and URLs
HTTP transfers representations of resources: anything that can be named, such as a page, an image, or a record in a database. Resources are named by URLs (RFC 3986):
https://www.example.com:443/articles/?page=2#history
| Part | In the example | Meaning |
|---|---|---|
| Scheme | https |
How to reach the resource: HTTP over TLS |
| Host | www.example.com |
The server, found through DNS |
| Port | 443 |
The TCP or UDP port; 443 is the default for https, 80 for http |
| Path | /articles/ |
The resource on the server |
| Query | page=2 |
Extra parameters for the resource |
| Fragment | history |
A part of the page; stays in the browser |
The default port is usually left out, so the same URL is normally written
https://www.example.com/articles/?page=2#history. The fragment, after #, is never sent to
the server; the browser uses it to scroll to a part of the page.
Requests and responses
In HTTP/1.1, messages are plain text, which makes them easy to read. A request for a page and its response look like this (shortened):
Every message has the same parts:
- A start line. In a request, it holds the method, the target and the protocol version. In a response, it holds the version and a status code with a short reason phrase.
- Header fields, one per line: a case-insensitive name, a colon and a value. They describe the message, the client’s preferences and the content.
- An empty line, which ends the header.
- The content, if there is any, such as the HTML of a page or the data of a form.
The Host field names the site the request is for. It is required in HTTP/1.1, because a single
server, at a single IP address, often hosts many sites. HTTP/2 and HTTP/3 carry the same
information in a field called :authority.
Methods
The method says what the client wants to do with the resource (RFC 9110):
| Method | Meaning | Safe | Idempotent |
|---|---|---|---|
GET |
Retrieve the resource | Yes | Yes |
HEAD |
Like GET, but return only the header | Yes | Yes |
POST |
Process the enclosed data, for example submit a form | No | No |
PUT |
Create or replace the resource with the enclosed data | No | Yes |
DELETE |
Remove the resource | No | Yes |
PATCH |
Apply partial changes (RFC 5789) | No | No |
OPTIONS |
Ask which methods and features the resource supports | Yes | Yes |
Two properties matter for everything that sits between client and server:
- A safe method only reads; it does not change anything on the server. Browsers, search engines and prefetching tools may send safe requests freely.
- An idempotent method has the same effect whether it is sent once or several times. A
client may repeat an idempotent request automatically when a connection fails before the
answer arrives. A client should not repeat a non-idempotent request such as
POSTautomatically (RFC 9110): a repeated order form could place the order twice.
Status codes
Every response carries a three-digit status code. The first digit gives the class:
| Class | Meaning | Common codes |
|---|---|---|
| 1xx | Informational | 101 Switching Protocols, 103 Early Hints (RFC 8297) |
| 2xx | Success | 200 OK, 201 Created, 204 No Content, 206 Partial Content |
| 3xx | Redirection | 301 Moved Permanently, 302 Found, 304 Not Modified, 307 Temporary Redirect, 308 Permanent Redirect |
| 4xx | Client error | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 429 Too Many Requests (RFC 6585) |
| 5xx | Server error | 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout |
Two pairs are easy to confuse:
- Redirects.
301and302were historically allowed to turn aPOSTinto aGETwhen the browser follows them, and browsers do.307(temporary) and308(permanent) forbid changing the method, so a redirected form submission stays a submission. - 401 and 403.
401 Unauthorizedmeans the request lacks valid credentials, so logging in may help.403 Forbiddenmeans the server understood who is asking and refuses anyway.
Header fields at work
Header fields carry most of HTTP’s intelligence. A few groups are worth knowing:
- Describing the content.
Content-Typegives the media type, such astext/html; charset=utf-8orapplication/json.Content-Lengthgives its size in bytes. - Content negotiation. The client states its preferences with
Accept(media types),Accept-LanguageandAccept-Encoding, and the server picks the best representation it has. The response’sVaryfield names the request fields that influenced the choice, so that caches do not hand an English page to someone who asked for German. - Compression. With
Accept-Encoding: gzip, br, zstd, a client says it understands gzip, Brotli (RFC 7932) and Zstandard (RFC 8878). The server compresses text before sending it and names the method inContent-Encoding. Text such as HTML, CSS and JavaScript typically shrinks to a fraction of its size. - Conditions and ranges.
If-None-MatchandIf-Modified-Sincemake a request conditional, which caches use to revalidate a copy.Rangeasks for part of a resource, which lets a download resume where it stopped (answered with206 Partial Content).
Cookies: state on a stateless protocol
HTTP is stateless: every request stands on its own, and the server does not remember earlier ones. To build sessions, such as a login or a shopping cart, servers use cookies (RFC 6265). A response sets a cookie:
Set-Cookie: session=7f3a9c; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=86400
From then on, the browser sends it back with every matching request, in a Cookie field. The
attributes limit where it goes and who can read it:
Securesends the cookie only over HTTPS.HttpOnlyhides it from JavaScript in the page, which limits the damage of injected scripts.SameSitecontrols whether the cookie is sent with requests that other sites trigger, which helps against cross-site request forgery. It is defined in the revised cookie specification, which the IETF has approved for publication as the successor of RFC 6265.Max-AgeorExpiressets its lifetime; without them, it disappears when the browser closes.
Caching
The fastest request is the one that is never sent. HTTP has a detailed caching model (RFC 9111) that lets browsers, proxies and content delivery networks keep copies of responses and reuse them safely.
A cache first asks whether its copy is fresh. The server sets the lifetime with
Cache-Control:
| Directive | Meaning |
|---|---|
max-age=3600 |
Fresh for 3,600 seconds after it was generated |
s-maxage=3600 |
The same, but only for shared caches such as CDNs |
no-cache |
May be stored, but must be revalidated before every use |
no-store |
Must not be stored at all, for example for sensitive data |
private |
Only the user’s own browser may store it, not a shared cache |
immutable |
Will never change during its lifetime, so no need to revalidate (RFC 8246) |
stale-while-revalidate=60 |
May be used stale for 60 more seconds while a fresh copy is fetched (RFC 5861) |
When a copy is stale, the cache does not have to download it again. It revalidates: it asks
the server whether the resource has changed, using a validator from the stored response. The
ETag field holds an identifier of a version, such as a hash of its content, which the cache
sends back in If-None-Match; the Last-Modified date is sent back in If-Modified-Since. If
nothing has changed, the server answers 304 Not Modified with no content, and the cache uses
its copy for another lifetime.
A common pattern for websites combines both ideas. Files whose names contain a hash of their
content, such as app.3f9a2c.js, get a long lifetime and immutable, because a new version gets
a new name. HTML pages, which link to those names, get a short lifetime or no-cache, so that
visitors see changes quickly.
Connections in HTTP/1.1
HTTP/1.0 opened a new TCP connection for every request, paying for a TCP handshake (and later a
TLS handshake) every time. HTTP/1.1 keeps connections open by default, so that several requests
can use one connection, one after another. The end of each response is marked by its
Content-Length, or by chunked transfer coding when the length is not known in advance.
The limit is that a connection carries only one exchange at a time. A slow response blocks the requests behind it, a problem called head-of-line blocking. HTTP/1.1 allowed pipelining, sending several requests without waiting, but responses still had to come back in the order of the requests, so a slow response still held up the ones behind it. Browsers worked around the limit by opening several connections to each site, and websites by combining files and spreading them across domains.
HTTP/2: many streams, one connection
HTTP/2 keeps the meaning of every message and changes how messages travel.
- Binary frames. Each message is split into frames with a 9-byte header that gives the frame’s
length, type and stream.
HEADERSframes carry the header fields;DATAframes carry the content. - Streams. Every request and its response form a stream with its own number. Frames of different streams are interleaved on a single connection, so dozens of requests can be in flight at once without waiting for each other. This is called multiplexing.
- Header compression. Requests repeat many of the same header fields. HPACK (RFC 7541) replaces common fields by references to a static table of 61 entries and to a table of fields already sent on the connection, and compresses the rest with a Huffman code.
- Flow control per stream, so that one large download cannot crowd out everything else.
HTTP/2 also defined server push, which let a server send resources before the client asked for
them. A client can turn it off with a setting (SETTINGS_ENABLE_PUSH). A simpler way to speed up a
page is 103 Early Hints (RFC 8297), a preliminary response that tells the browser which resources
it will need while the real response is still being prepared.
Over TLS, client and server agree on HTTP/2 during the TLS handshake through the ALPN extension,
where HTTP/2 is identified as h2.
HTTP/3: HTTP over QUIC
HTTP/2 solved head-of-line blocking between requests, but not underneath them. All its streams share one TCP connection, and TCP delivers bytes strictly in order. When a single packet is lost, TCP holds back everything that arrived after it until the lost packet is retransmitted, even data that belongs to other streams.
QUIC (RFC 9000) fixes this by moving the transport’s work into a new protocol that runs over UDP:
- Independent streams. QUIC knows about streams, so a lost packet delays only the streams whose data it carried.
- TLS built in. QUIC uses TLS 1.3 for its handshake and encrypts almost all of its own headers. Setting up a connection takes one round trip instead of two, and resumed connections can send their first request with no round trip at all (0-RTT).
- Connection migration. A connection is identified by connection IDs rather than by addresses and ports, so it can survive a change of network, such as a phone moving from Wi-Fi to mobile data.
HTTP/3 (RFC 9114) is HTTP mapped onto QUIC streams, with QPACK (RFC 9204) as its header
compression, a variant of HPACK designed for streams that arrive out of order. A client learns that
a server supports HTTP/3 from an Alt-Svc header field in an earlier response (RFC 7838) or from
the server’s HTTPS record in DNS (RFC 9460), then connects over UDP, to port 443 unless another port
is announced. Because some networks block UDP, clients should fall back to HTTP over TCP when a QUIC
connection fails (RFC 9114).
| Aspect | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| Published | 1997 (current text 2022) | 2015 (current text 2022) | 2022 |
| Format | Text | Binary frames | Binary frames |
| Requests per connection | One at a time | Many, multiplexed | Many, multiplexed |
| Transport | TCP, with or without TLS | TCP with TLS (in browsers) | QUIC over UDP, TLS 1.3 built in |
| Header compression | None | HPACK | QPACK |
| Head-of-line blocking | Per connection | At the TCP level | Only within a stream |
HTTPS everywhere
An http:// URL sends everything in the clear: anyone on the path can read and change it. An
https:// URL sends the same messages through TLS. One weakness remains even for sites that use
HTTPS: if a user types a name without https://, the first request may still go out unencrypted
and be intercepted before a redirect to HTTPS happens.
HTTP Strict Transport Security (HSTS, RFC 6797) closes this gap. A site sends:
Strict-Transport-Security: max-age=31536000; includeSubDomains
and the browser remembers, for the given number of seconds (here, one year), to use only HTTPS for that site and to refuse connections with invalid certificates. Browsers also ship a preload list of sites that are HTTPS-only from the very first visit.
Everything together: loading a page
Loading https://www.example.com/articles/ for the first time brings every layer of this learning
path into play:
- DNS. The browser looks up
www.example.comand receives its IPv4 and IPv6 addresses, and possibly an HTTPS record announcing HTTP/3. - Connection. It opens a QUIC connection, or a TCP connection followed by a TLS handshake.
TLS verifies the certificate for
www.example.comand, through ALPN, settles the HTTP version. - Request. It sends
GET /articles/with its headers: accepted formats, languages and compression methods, and any cookies for the site. - Response. The server answers
200 OKwith compressed HTML and caching instructions. - More requests. While parsing the HTML, the browser finds stylesheets, scripts, fonts and images, and requests them over the same connection, many at once. Anything already fresh in its cache is not requested at all.
On the second visit, most of this is gone: the DNS answer and many files come from caches, and the connection may be resumed with 0-RTT.
To watch HTTP at work, open the network panel of a browser’s developer tools, which lists every
request with its method, status, protocol version and timing. On the command line,
curl -v https://www.example.com/ prints the request and response headers.
Key points
- HTTP is a request–response protocol: a method and a target in, a status code and content out, with header fields describing both.
- Safe and idempotent methods tell clients and intermediaries what they may repeat or prefetch; status codes tell them what happened.
- Caching with
Cache-Control,ETagand304 Not Modifiedavoids sending data that has not changed. Cookies add state to a stateless protocol. - HTTP/1.1 handles one exchange per connection at a time, HTTP/2 multiplexes streams over one TCP connection, and HTTP/3 runs over QUIC, where a lost packet delays only its own stream.
- HTTPS and HSTS make sure all of it travels encrypted and authenticated.
Sources
- HTTP Semantics (RFC 9110)R. Fielding, M. Nottingham, J. Reschke, RFC Editor, 2022Accessed
- HTTP Caching (RFC 9111)R. Fielding, M. Nottingham, J. Reschke, RFC Editor, 2022Accessed
- HTTP/1.1 (RFC 9112)R. Fielding, M. Nottingham, J. Reschke, RFC Editor, 2022Accessed
- HTTP/2 (RFC 9113)M. Thomson, C. Benfield, RFC Editor, 2022Accessed
- HTTP/3 (RFC 9114)M. Bishop, RFC Editor, 2022Accessed
- Hypertext Transfer Protocol — HTTP/1.0 (RFC 1945)T. Berners-Lee, R. Fielding, H. Frystyk, RFC Editor, 1996Accessed
- Hypertext Transfer Protocol Version 2 (HTTP/2) (RFC 7540)M. Belshe, R. Peon, M. Thomson, RFC Editor, 2015Accessed
- Uniform Resource Identifier (URI): Generic Syntax (RFC 3986)T. Berners-Lee, R. Fielding, L. Masinter, RFC Editor, 2005Accessed
- PATCH Method for HTTP (RFC 5789)L. Dusseault, J. Snell, RFC Editor, 2010Accessed
- Additional HTTP Status Codes (RFC 6585)M. Nottingham, R. Fielding, RFC Editor, 2012Accessed
- An HTTP Status Code for Indicating Hints (RFC 8297)K. Oku, RFC Editor, 2017Accessed
- Brotli Compressed Data Format (RFC 7932)J. Alakuijala, Z. Szabadka, RFC Editor, 2016Accessed
- Zstandard Compression and the 'application/zstd' Media Type (RFC 8878)Y. Collet, M. Kucherawy, RFC Editor, 2021Accessed
- HTTP State Management Mechanism (RFC 6265)A. Barth, RFC Editor, 2011Accessed
- Cookies: HTTP State Management Mechanism (draft-ietf-httpbis-rfc6265bis-22)S. Bingler, M. West, J. Wilander, IETF, 2025Accessed
- HTTP Immutable Responses (RFC 8246)P. McManus, RFC Editor, 2017Accessed
- HTTP Cache-Control Extensions for Stale Content (RFC 5861)M. Nottingham, RFC Editor, 2010Accessed
- HPACK: Header Compression for HTTP/2 (RFC 7541)R. Peon, H. Ruellan, RFC Editor, 2015Accessed
- QUIC: A UDP-Based Multiplexed and Secure Transport (RFC 9000)J. Iyengar, M. Thomson, RFC Editor, 2021Accessed
- QPACK: Field Compression for HTTP/3 (RFC 9204)C. Krasic, M. Bishop, A. Frindell, RFC Editor, 2022Accessed
- HTTP Alternative Services (RFC 7838)M. Nottingham, P. McManus, J. Reschke, RFC Editor, 2016Accessed
- Service Binding and Parameter Specification via the DNS (SVCB and HTTPS Resource Records) (RFC 9460)B. Schwartz, M. Bishop, E. Nygren, RFC Editor, 2023Accessed
- HTTP Strict Transport Security (HSTS) (RFC 6797)J. Hodges, C. Jackson, A. Barth, RFC Editor, 2012Accessed