HTTP and HTTPS
When you type an address and press Enter, the browser starts a conversation with a computer that may be on the other side of the world. That conversation follows a protocol, HTTP, and it is nearly always protected by another, TLS. Together they make up HTTPS, the letters at the start of almost every address on the web. Choose a page of the site of an imaginary bakery and follow the whole conversation:
Before asking for anything, the browser opens a connection with the
server, over TCP. With https://, the two also agree on a secret key,
and the server proves who it is. Only then does the request go, a
small text message that says what the browser wants, and the
response come back, with a code that says whether it worked and,
after it, the page. Switch to http:// and the page arrives a round
trip sooner, without the encryption, but anyone on the way can read the
whole conversation.
HTTP was born in 1991 as a protocol of a single line, and today it carries almost everything that crosses the internet: pages, photos, videos, the conversations of apps with their servers. In this guide, we will start with the format of the messages and of the addresses, see how a page with dozens of files is loaded and how cookies and the cache give memory to a protocol that forgets everything. Then we will build up from the beginning the cryptography that protects the conversation: secret keys, the key exchange of Diffie and Hellman, certificates and the TLS handshake. At the end, the newest versions, HTTP/2 and HTTP/3.
A conversation in text
HTTP is a protocol of request and response. The browser, the client, sends a request; the server sends a response; and each request gets a single final response. In the version that is still the basis of the others, HTTP/1.1, both messages are plain text, which can be read and even typed by hand. Tap the lines to see what each one says:
Both messages have the same shape: a first line, a series of
headers, in the format Name: value, an empty line and, sometimes,
a body. In the request, the first line says what is wanted; in the
response, how it went. The headers carry all the rest: the type of the
content, its length, the preferred language, the rules of the cache, the
cookies. More than two hundred headers are registered, and anyone can
invent others, as long as both sides understand them.
Two headers of the response deserve attention. Content-Type says what
the body is, with the media types inherited from email: text/html
for a page, image/jpeg for a photo, application/json for the data
that apps exchange with servers. Without it, the browser would not know
whether to show the bytes as text, as an image or offer a download. And
Content-Length says where the response ends. When the server does not
know the length beforehand, as with a page put together bit by bit, it
sends the body in pieces, each after its own length, and says so with
Transfer-Encoding: chunked.
Often the body is not even readable text. If the browser announces in
Accept-Encoding that it knows how to decompress, the server can send
the page compressed, with gzip, with Brotli, released by Google in 2015,
or with Zstandard, which Chrome began to accept in 2024. A page of HTML
usually shrinks to a quarter of its size, or less.
Addresses
It all starts with an address, what the standards call a URL. It brings together, in a single line, the information the browser needs to reach the resource: the protocol, the server, the port and the path. Type an address, or choose one of the examples:
Each part goes to a different place. The name of the site goes to the
DNS, which gives back the IP address of the server, as we saw in the
guide to the DNS. The port goes to TCP: when it does not
appear, it is 80 for http and 443 for https. The path and the query
go in the first line of the request, and the name of the site goes
again, in the Host header. The fragment, after the #, never leaves
the browser: it only says where in the page to scroll to.
An address may only use letters without accents, digits and a few
symbols. In the path and in the query, everything else, spaces included,
becomes a sequence of bytes written in hexadecimal, each after a %:
café au lait becomes caf%C3%A9%20au%20lait. The bytes are those of UTF-8,
which we saw in the guide to Unicode, and
the space is byte 20, in hexadecimal. Browsers show the pretty form in
the address bar and send the encoded one over the network. In the name
of the site, the rule is different: accented letters turn into the form
with xn-- that we saw in the guide to the DNS.
From CERN to HTTP/1.1
In March 1989, Tim Berners-Lee, a physicist who worked with computing at
CERN, the European laboratory for particle physics, proposed a system to
organize the laboratory's information in documents linked to one
another. By the end of 1990, he already had the first server and the
first browser working, on a NeXT computer, and the first site,
info.cern.ch. In August 1991, he announced the World Wide Web
publicly, and in April 1993 CERN put the software in the public domain.
The protocol between browser and server was HTTP, the Hypertext
Transfer Protocol.
The first version, which was later numbered 0.9, was extremely simple. Compare the first three versions:
HTTP/1.0 was documented in May 1996, when the web had already exploded,
and it recorded what browsers and servers were already doing: headers,
status codes, types of content. It never became a formal standard.
HTTP/1.1 came in January 1997, with two changes that still matter: the
Host header, which let a single server, at a single IP address, host
thousands of sites, and persistent connections, which avoid opening a
TCP connection for each file. The specification was revised in 1999, in
2014 and, last, in 2022, when it was split into three documents: one
with the meaning of the messages, common to all the versions, one on the
cache and one with the text format of HTTP/1.1.
Methods and forms
The first word of the request is the method, the verb of the
request. The most common is GET, which asks for a copy of a resource.
HEAD asks only for the headers of the response, without the body, and
serves to learn the size or the date of a file without downloading it.
POST sends data for the server to process, such as a form or a
purchase. And there are others, used mostly by the apps that talk to
servers: PUT to create or replace a resource, PATCH to change a
piece of it and DELETE to remove it.
The difference between them is not just a name. GET and HEAD are
safe: they must not change anything on the server, and so the
browser, search engines and caches can repeat them at will. PUT and
DELETE are not safe, but they are idempotent: making the request
again comes to the same as making it once. POST promises nothing, and
repeating one may mean paying twice. That is why the browser asks before
sending a form again when you reload the page. See how a form becomes a
request with each method:
In both cases, the fields are encoded the same way, as pairs
name=value separated by &, with the spaces replaced by + and the
other special characters by %XX. Apps often send their data in another
format, JSON, with Content-Type: application/json, but the idea is the
same: the method says what to do, and the body carries the data.
Status codes
The response begins with a number of three digits, the status code.
The first digit gives the category: 2 is success, 3 is redirection, 4 is
an error of whoever asked and 5 is an error of the server. Programs
decide what to do by looking only at the number; the phrase beside it,
such as Not Found, is for humans, and HTTP/2 no longer even sends it.
Tap the codes to see when each one appears:
Redirections come with a Location header, and the browser goes on to
the new address by itself. That is how a site that changed its name
keeps working, and how an address with http:// leads to the version
with https://. Code 304, which carries no body at all, is the basis of
revalidation in the cache, which we will see further on. And 418 has a
story of its own: it was born in a specification of 1 April 1998, about
a protocol for controlling coffee pots over the network, and it meant
“I'm a teapot”. So many people used it as a joke that it ended up
reserved, never to be used in earnest.
One page, many files
A page is rarely a single file. The HTML refers to style sheets, scripts, fonts and images, and the browser needs a request for each of them. In 2025, the typical home page of a site asked for 75 files on a phone and 80 on a computer, adding up to between 2.5 and 3 megabytes. The challenge is to fetch all this quickly, and the worst enemy is not the speed of the connection, but the round trip time: each new connection costs round trips before the first byte. Compare the versions of HTTP loading a page of the bakery, with 13 files, and use the slider below the figure to change the round trip time:
In HTTP/1.0, each file had its own connection, and each connection cost round trips just to open: one for TCP and, with encryption, another for TLS. HTTP/1.1 kept the connections open, but a connection holds only one request at a time: the next one must wait for the previous response to arrive in full. So as not to stand in a single queue, browsers open up to six connections with the same site, a number that is in no standard and that Chrome and Firefox adopted on their own. HTTP/1.1 did foresee an alternative, sending several requests in a row without waiting for the responses, but the responses had to come back in the same order, and one slow file held up all the others. In practice, hardly anyone used it.
HTTP/2, from 2015, solved this another way: on a single connection, it cuts the responses into frames and interleaves the frames of all of them, like several streams running side by side. All the requests can go out at once, and a slow response does not hold up the others. But turn on the loss of a packet and see what happens to it: TCP delivers the bytes in order, and, until the lost packet is sent again, all the streams of the connection stand still, even those that had nothing to do with it. This is head-of-line blocking. HTTP/3 exists largely to solve this problem, as we will see at the end.
The figure simplifies a lot: there is no congestion control, which makes new connections slow at first, and in it the browser discovers the files only after receiving the whole HTML, while a real browser starts asking for them as soon as it finds them in the middle of the HTML. But the proportions are real: with a long round trip, like that of a phone with a poor signal, what counts is how many times the browser has to wait.
Cookies
HTTP has no memory. Each request stands alone, and the server has no way
of knowing whether two of them came from the same person. For a news
page, that does not matter; for a shop, with a login and a shopping
cart, it is a problem. The solution, invented in 1994 by Lou Montulli,
at Netscape, is the cookie: the server sends a small piece of text
in the Set-Cookie header, the browser keeps it and sends it back in the
Cookie header in every following request to the same site. Go into the
bakery's shop and watch the messages:
The session cookie does not keep Alice's name nor the cart: it keeps only
a number drawn at random, and the server keeps a table that ties each
number to a session. Whoever has the number passes for Alice, and so it
must be treated like a password. The attributes of the cookie help to
protect it: Secure makes it travel only over HTTPS, HttpOnly hides it
from the scripts of the page and SameSite=Lax makes it go, from another
site, only when you yourself follow a link, and not with the requests
that the other site fires off on its own, such as a form sent behind
your back. Since 2020, Chrome treats every cookie without this attribute
as Lax.
Cookies also serve to follow people around the web. If dozens of sites load an image or a script from the same advertising service, that service receives its cookie on each of them, and knows where you have been. These are third-party cookies. Safari and Firefox began to block them or to isolate them by site. Chrome announced for years that it would do the same, but gave up in 2024 and, in 2025, also dropped the idea of asking each user: in it, third-party cookies are still allowed, and whoever wants to block them must change the settings.
Cache
The best request is the one that need not be made. The browser keeps the responses in a cache and reuses them, following the instructions that the server itself gives in the headers. See what happens to the photo of the bread over three visits:
Cache-Control: max-age says for how many seconds the copy can be used
without asking anything. Once that time is up, the browser asks again,
but sends the tag of the version it has, in the If-None-Match header.
If nothing changed, the response is a 304 of a few dozen bytes, instead
of the whole photo. It is the same idea as the lifetime of the DNS, with
one detail more: once the lifetime is over, the old copy can still be
confirmed, instead of downloaded again.
Many sites combine the two things cleverly: they give their files a
lifetime of a year and change the name of a file whenever its content
changes, as in style.3f9a2c.css. The browser never needs to ask, and,
when the site changes, the HTML points to a new name. Between the
browser and the server there can also be shared caches, such as content
delivery networks, the CDNs, with copies of the site spread around the
world, like the copies of the root servers of the DNS.
The trouble with plain text
So far, everything has travelled in the clear. Between you and the server there are your Wi-Fi network, your provider and several routers of other companies, and each of them sees every byte that goes by, and can change it. On an open Wi-Fi network, it is enough to be nearby: the radio reaches everyone. See what an intruder in a café can capture when Alice goes into the bakery's shop:
With HTTP, the intruder reads the password. And even if the password had travelled protected, he would read the session cookie, and with the cookie he would get into Alice's account with no password at all. In October 2010, an extension for Firefox called Firesheep made this trivial: on an open Wi-Fi network, it showed the accounts of the people around, and a click was enough to get into them. The scare helped to convince the big sites to adopt HTTPS on all their pages, and not only on the login ones.
With HTTPS, the content becomes a sequence of bytes that makes no sense to whoever lacks the key, and any change on the way is detected. To get there, the browser and the server must solve three problems: agree on a secret key, do so in front of everyone and be sure they are talking to each other, and not to an intruder. Let us take them one at a time.
Ciphers and keys
A cipher turns a message into something unreadable, in a way that only whoever has the key can undo. The ciphers that protect content on the web are symmetric: the same key serves to encrypt and to decrypt. One of the simplest ideas, and one that is at the heart of real ciphers, is to make from the key a sequence of bytes that looks random and to combine it with the message, byte by byte, through the operation exclusive or (⊕), which gives 1 where the bits differ and 0 where they are equal. Try a toy cipher:
The trick of exclusive or is that it undoes itself: applying the same sequence twice gives back the original bytes. With the right key, the message comes back; change a single letter of the receiver's key and out comes rubbish. The sequence in the figure comes from a weak generator, which an expert would break in seconds. Real ciphers, such as AES, adopted as a standard in 2001, and ChaCha20, use keys of 128 or 256 bits, and trying all the possible keys would take longer than the age of the universe. The versions used in TLS also add to each message a tag of authentication, which gives away any bit changed on the way.
One problem remains: the key. The browser has never talked to the bakery's server, and the two share no secret at all. Sending the key over the network is no use, because the intruder would see it too.
Agreeing on a secret in public
In 1976, Whitfield Diffie and Martin Hellman published a solution that seems like magic: two strangers can agree on a secret by exchanging messages in public, even with someone listening to everything. The idea is often explained with paints. Mixing paints is easy, but separating a mixture into the colours it came from is practically impossible. Change the secret colours and follow along:
Alice and Bob end up with the same colour, made of the public colour and of the two secrets, and neither secret went over the network. Eve saw the public colour and the two mixtures, but, unable to separate the paints, the best she can do is mix what she saw, and then the public colour goes in twice. Choose “With numbers” to see the real version: instead of mixing paints, raising a number to a power and keeping only the remainder of the division by a prime number. Working out the power is fast; finding the exponent from the result, the so-called discrete logarithm, is very hard when the numbers have hundreds of digits.
Today, the web uses a variation with elliptic curves, X25519, which reaches the same security with much smaller numbers. And, since the end of 2024, Chrome and Firefox combine this exchange with a second one, ML-KEM, which also resists quantum computers, able, in theory, to solve the discrete logarithm. The combination was standardized in August 2026 with the name X25519MLKEM768, and in April Cloudflare already counted more than 65% of the human traffic to its servers protected by it. The haste has a reason: someone can record an encrypted conversation today and wait for a quantum computer to decrypt it years from now.
The historical curiosity is that the discovery had been made before, in secret. At GCHQ, the British signals intelligence service, James Ellis, Clifford Cocks and Malcolm Williamson reached the same ideas from 1970 onwards. Williamson only put down on paper the equivalent of the exchange of Diffie and Hellman in 1976, but, according to Ellis, he had thought of it well before. The work stayed secret until December 1997.
But the key exchange has a weak point. Choose “With an intruder in the middle”: if Eve, instead of only listening, manages to intercept the messages and swap the mixtures for her own, she agrees on one key with Alice and another with Bob. Each thinks they are talking to the other, and Eve decrypts, reads and encrypts again everything that goes by. The mathematics has no way to prevent this. What is missing is for the browser to be sure of who is at the other end.
Certificates
The answer comes from another invention of the same time, the digital signature. With it, each server has a pair of keys: a private one, which it keeps under lock and key, and a public one, which it shows to everyone. With the private key, the server signs a message; with the public key, anyone can check that the signature can only have been made by whoever has the private key. In the TLS handshake, the server signs the conversation so far, and the browser checks it with the server's public key. If Eve changes anything, the signature does not match.
But this only pushes the question one step back: how to know that this
public key really belongs to the bakery? That is what the
certificate is for, a document that says, in short, “the public key
of bakery.example is this one”, signed by a certificate authority,
a company or organization that checked that whoever asked for the
certificate controls the site. The authority's signature is checked with
its key, which comes in a certificate signed by an authority above,
until it reaches a root: an authority whose key already comes
installed in the operating system or in the browser. Choose a
certificate and watch the browser check it:
The authorities in the figure are made up, but the structure is the real one. In practice, the certificates of sites are signed by intermediate authorities, and the roots, whose keys are the most valuable, are kept far from the network. Since 2015, a non-profit authority, Let's Encrypt, issues certificates for free and automatically, and it was decisive in making HTTPS the rule: at the end of September 2026, it had nearly 692 million active certificates.
A certificate is good for a short time, and that time is shrinking. Since 15 March 2026, the maximum is 200 days, and the rules agreed between the authorities and the browsers bring it down to 100 days in 2027 and to 47 in 2029. Short certificates limit the damage of a stolen key and force sites to renew everything automatically. Besides, the main browsers accept only certificates recorded in public lists, the certificate transparency logs, and anyone can look up there the certificates issued for their domain. An authority that issues a certificate it should not cannot hide it.
The TLS handshake
The protocol that brings all these pieces together is TLS, Transport Layer Security. It descends from SSL, released by Netscape in 1995 and still the name that many people use. Before the first request, the browser and the server go through a handshake: they agree on the ciphers, exchange the parts of the key and the server presents its certificate. Compare the versions and change the round trip time; tap the arrows to see what goes in each message:
In TLS 1.2, from 2008, the handshake cost two round trips, besides that of TCP. TLS 1.3, from 2018, cut one: the browser already sends its part of the key exchange in its first message, betting on the form of exchange that the server will choose. With that, all the rest, certificate included, already goes encrypted, and an intruder does not even see which certificate the server presented. TLS 1.3 also threw out the old and insecure options that the earlier versions had piled up, and today it protects most pages; versions 1.0 and 1.1 were officially retired in 2021.
Two messages of the handshake deserve attention. The ClientHello,
which still travels in the clear, carries the name of the site the
browser wants, in the SNI field, so that a server that hosts several
sites knows which certificate to present. And, at the end, the two sides
exchange a Finished message, already encrypted, with a digest of
everything that was said: if an intruder has changed anything, for
example to force a weaker cipher, the digests do not match and the
connection is dropped.
HTTP/2 and HTTP/3
In 2009, Google announced an experimental protocol called SPDY, which was the basis of HTTP/2, published in 2015. HTTP/2 keeps everything the messages mean, the methods, the codes and the headers, and changes only the way they are sent. Instead of text, it uses binary frames, each with a header of 9 bytes that gives the length, the type and the stream it belongs to. And the headers are compressed, with a scheme called HPACK. Compare two requests in a row on the same connection:
HPACK uses two tables. The static one, the same everywhere, has 61
common headers, such as :method: GET, which become a single byte. The
dynamic one is built during the connection: the headers sent in full are
usually kept on both sides, in a table of limited size, and the second
time it is enough to send their position. The names that begin with a
colon, such as :path and :authority, are the pseudo-headers, which
replace the first line of HTTP/1.1 and the Host. On a page with dozens
of requests, nearly always with the same long headers, the saving is
large.
HTTP/2 still runs over TCP, and it inherits the head-of-line blocking that we saw in the waterfall. HTTP/3, published in 2022, replaces TCP with QUIC, a transport protocol created at Google and standardized in 2021, which runs over UDP. QUIC itself does what TCP did, such as confirming delivery, sending again what was lost and controlling congestion, but it keeps the streams apart: a lost packet delays only the stream it belonged to. QUIC also has TLS 1.3 built in, which joins the two handshakes in a single round trip, and it identifies the connection by a number of its own, not by the addresses, so that a phone that moves from Wi-Fi to the mobile network can keep its connection.
The three versions live side by side. In 2025, half of the requests
that reached Cloudflare used HTTP/2, 29% HTTP/1.x and 21% HTTP/3.
Browsers find out whether a site speaks HTTP/3 from a header of the
response, Alt-Svc, and start using it on the following connections,
or from a record of the type HTTPS in the DNS, which lets them use it
from the first.
What HTTPS does not hide
HTTPS protects the content of the conversation, but not the fact that it took place. Whoever is on the way still sees the IP addresses, the sizes of the messages and the times, and from them it is sometimes possible to guess a lot: which video someone watches, for example, from the pattern of the sizes. The name of the site goes in the clear in the SNI and, usually, in the queries to the DNS too, unless they are encrypted, as we saw in the guide to the DNS. To close the first gap, there is ECH, Encrypted ClientHello, published as a standard in March 2026: the browser encrypts the whole ClientHello with a key that the site publishes in the DNS, and the intruder sees only the generic name of the company that hosts the site. Chrome and Firefox have used it since 2023; Safari does not yet.
And the padlock says nothing about the intentions of whoever is at the
other end. It guarantees that you are talking to the owner of
bakery.example, not that bakery.example is an honest bakery: a scam
site gets a certificate just as easily, as long as it controls its own
domain. That is why browsers stopped highlighting the padlock as a sign
of trust (since 2023, Chrome does not even show it, and puts a neutral
icon of settings in its place) and began to highlight the opposite, the
sites without encryption. Since 2018, Chrome has marked every page over
HTTP as “Not secure”.
Today, the web is nearly all encrypted: according to Google, 99% of the
pages opened in Chrome for Android arrive over HTTPS, and 95% in Chrome
for Windows. To close the door that remains, access through http://,
in which an intruder can still intercept the redirection, sites can
send the Strict-Transport-Security header, which tells the browser to
use only HTTPS with them for a while. Since the browser learns this only
after the first visit, sites can also get onto a list that comes built
into the browsers, the HSTS preload list, which protects even the first
visit. And, since version 154, released on 22 September 2026, Chrome for
computers has asked the user to confirm before opening a public site
without HTTPS.
In practice
Every browser has tools to watch these conversations. In the developer
tools, opened with F12, the Network tab shows each request of the page,
with its headers, the times in a waterfall like that of the figure and
the version of the protocol used. In a terminal, curl makes a request
and, with the option -v, shows the handshake and the messages. For the
bakery's site, the output would be something like this:
$ curl -v https://bakery.example/menu
* Trying 203.0.113.10:443...
* ALPN: curl offers h2,http/1.1
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519MLKEM768
* ALPN: server accepted h2
* Server certificate:
* subject: CN=bakery.example
* expire date: Jan 16 23:59:59 2027 GMT
* issuer: O=Example CA; CN=Example CA R7
> GET /menu HTTP/2
> Host: bakery.example
> Accept: */*
>
< HTTP/2 200
< content-type: text/html; charset=utf-8
< content-length: 147
The lines with * describe the connection: the version of TLS, the
cipher, the post-quantum key exchange and the certificate. Those with
> are the request, and those with <, the response. Notice that, in
HTTP/2, the phrase of the status is gone and the names of the headers
are in small letters: curl shows the messages in the format of HTTP/1.1,
but what travelled were binary frames. And if you want to see the
conversation in plain text, you can do as in the 1990s and type a
request by hand, with telnet or nc, to a server that still accepts
HTTP without encryption.
Final words
HTTP is a rare example of a protocol that grew without losing its
original idea. The request of 1991, a method and a path, is still there
at the bottom of every page you open, with the same GET, now
surrounded by headers, cut into binary frames, compressed and
encrypted. Each layer added solved a concrete problem: Host to share
servers, persistent connections and then streams to save time, cookies
to remember who is who, the cache so as not to repeat the work.
And HTTPS is a rare example of cryptography that became invisible. A key exchange invented in 1976, digital signatures, a chain of authorities and, now, algorithms designed for the computers of the future, all happening in a round trip, before the first letter of the page appears, billions of times a day. The next time you see the padlock, or do not see it, you know exactly what it guarantees, and what it does not.
Further reading
- RFC 9110: HTTP Semantics (2022), the meaning of the messages, common to all the versions, and RFC 9111: HTTP Caching.
- RFC 9113: HTTP/2, RFC 9114: HTTP/3 and RFC 9000: QUIC.
- RFC 9846: TLS 1.3 (2026), the revision of the specification of 2018, and Michael Driscoll, “The Illustrated TLS 1.3 Connection”, which explains a real connection byte by byte.
- Tim Berners-Lee, “Information Management: A Proposal” (1989), and “The Original HTTP as defined in 1991”.
- Whitfield Diffie and Martin Hellman, “New Directions in Cryptography” (1976).
- The HTTP documentation of MDN, and the chapter on the weight of pages of the Web Almanac 2025.
- The Internet Protocol, The Domain Name System and The Unicode Standard, other guides of this site.
The bakery's site, the IP addresses of the figures and the certificate authorities are made up, from names and ranges reserved for examples. The waterfall uses a simplified model, without congestion control, and the cipher of the figure is a toy: it serves to show the idea, not to protect anything. The statistics were looked up in September 2026.