Application-Layer Protocol Negotiation (ALPN)
ALPN (Application-Layer Protocol Negotiation) is a
TLS extension that lets a client and server agree on the
application protocol, such as h2 or http/1.1, while
the TLS handshake is still in progress. The agreement
happens inside the handshake, so no extra round trip is
spent choosing a protocol before data flows.
What ALPN solves
ALPN removes the need for a separate negotiation step after TLS completes. A single port like 443 can serve HTTP/1.1, HTTP/2, and other protocols at the same time, and the client and server have to agree on which one to speak. Without ALPN, that agreement would cost an additional exchange after the encrypted channel is ready, delaying the first request.
ALPN folds the choice into the existing TLS handshake. The
client advertises the protocols it supports as part of the
first message it already sends, and the server picks one in
the message it already returns. Application data then starts
immediately under the agreed protocol. This is what makes
HTTP/2 practical over TLS, since browsers negotiate
h2 through ALPN rather than through an in-band upgrade.
How ALPN works in the handshake
ALPN runs as an extension the client carries in the ClientHello and the server answers in its handshake messages. The negotiation completes before any application data is sent, and it adds no network round trips of its own.
The flow has two steps:
- ClientHello: the client includes an
application_layer_protocol_negotiationextension holding a list of protocol identifiers, ordered by client preference. A typical browser sendsh2followed byhttp/1.1. - Server selection: the server selects a single protocol from that list, usually the one it prefers most, and returns the chosen identifier in its own ALPN extension. TLS 1.3 carries the reply in the EncryptedExtensions message, while TLS 1.2 places it in the ServerHello. Both sides then proceed with the selected protocol.
When the server supports none of the offered protocols, it
ends the handshake with a fatal no_application_protocol
alert rather than guessing. The selected identifier is also
available early enough for the server to choose a
certificate based on the negotiated protocol.
Protocol identifiers
ALPN protocol identifiers are short byte strings registered with IANA, each naming one application protocol. The client offers identifiers it supports and the server returns the single identifier it selected. The common HTTP values:
| Identifier | Selects |
|---|---|
http/1.1 |
HTTP/1.1 |
h2 |
HTTP/2 over TLS |
h3 |
HTTP/3 over QUIC |
A few related details apply to these identifiers. The h2
string always means HTTP/2 over TLS. The cleartext form of
HTTP/2 uses a separate h2c token that is reserved and not
allowed to appear in a TLS ALPN negotiation. The h3
identifier names HTTP/3, which runs over QUIC where TLS 1.3
is built into the transport, so ALPN is part of the QUIC
handshake rather than a separate TLS layer.
The registry reaches beyond HTTP. The acme-tls/1
identifier carries the ACME TLS-ALPN-01 domain
control validation challenge, and the short co
identifier names CoAP over DTLS for constrained
devices.
Historical identifiers such as spdy/1, spdy/2, and
spdy/3 survive from the protocol that preceded
HTTP/2.
Relationship to HTTP/2 and HTTP/3
ALPN is the standard way clients and servers select an HTTP
version over a secure connection. HTTP/2 over TLS is
negotiated almost entirely through ALPN using the h2
identifier, which replaced the cleartext upgrade path the
original HTTP/2 specification once described.
HTTP/3 depends on ALPN for protocol identification
inside the QUIC handshake, using the h3 token. A client
typically learns that a server speaks HTTP/3 through an
Alt-Svc advertisement or an HTTPS DNS record,
then opens a QUIC connection where ALPN confirms h3. This
differs from the HTTP/1.1
protocol upgrade mechanism, which
switches protocols on an already open cleartext connection.
ALPN instead settles the protocol while the secure channel
is being built.
Example
The negotiated protocol is visible with openssl s_client,
which prints the ALPN result after the handshake. The
-alpn flag sends the listed identifiers in the
ClientHello, and the server's choice appears in the output.
A client offering h2 and falling back to http/1.1
against an HTTPS host on port 443:
openssl s_client -connect www.example.re:443 -alpn h2,http/1.1
When the server supports HTTP/2, the handshake output reports the agreed protocol:
ALPN protocol: h2
The h2 result confirms both sides settled on
HTTP/2 during the TLS handshake. A server limited to
HTTP/1.1 would instead report ALPN protocol: http/1.1, and a server offering nothing from the list would
close the connection with a no_application_protocol alert.
See also
- RFC 7301: TLS Application-Layer Protocol Negotiation Extension
- RFC 9952: ALPN ID for CoAP over DTLS
- IANA TLS ALPN Protocol IDs Registry
- HTTPS
- Protocol upgrade
- Alt-Svc
- HTTP/1.1
- HTTP/2
- HTTP/3
- HTTP connection management
- HTTP headers