Measurement Method
Overview
We measure ECH deployment of domains on the latest CrUX top million list once per week from a single vantage point.
We first explain how ECH works and how we use its retry mechanism to measure ECH, then detail the measurement setup:
| Schedule | Weekly |
|---|---|
| Targets | CrUX top million |
| Vantage point | TU Dresden (IPv4 only) |
How ECH Works
ECH is standardized in RFC 9849.
Normally, a client learns how to use ECH from DNS. Before it connects, it queries the
HTTPS resource record (RR) of the name it wants to visit. Its ech
parameter carries the server's ECH configuration: a public key and a public name. The
client then encrypts its real ClientHello under that key, and an observer sees only the
public name.
Common ECH. The configuration comes from the HTTPS RR in DNS (1, 2); the handshake with ECH follows (3, 4). Then the server rotates its key (5), and a client that still caches the old one recovers with the retry configuration (6 to 9).
The client asks its DNS resolver for the HTTPS resource record of example.com, the name it wants to visit.
The resolver answers with the HTTPS RR. Its ech parameter carries the ECH configuration of example.com: a public key and the public name public.com. The client may cache it.
The client sends a ClientHello with two parts that matter here: the SNI, which names only the public name public.com, and the ECH extension, which holds the real encrypted ClientHello for example.com.
The server decrypts the inner ClientHello and completes the handshake for example.com: ECH accepted. Rotate key shows what happens when the server replaces its key.
The server rotates its key: it generates a new key, retires the old one, and publishes the new configuration in its HTTPS RR. The client may still use the cached configuration.
Later, the client connects again with the cached configuration. It does not know that the server has rotated its key.
The server cannot decrypt the inner ClientHello, as it no longer holds the old key. Instead of failing, it completes the handshake with the outer ClientHello, for the public name, and sends its current ECH configuration, with the new key, in retry_configs inside its EncryptedExtensions, as the standard requires. The client will now use this new configuration.
The client opens a new connection and encrypts its inner ClientHello under the new key from retry_configs.
The server decrypts the inner ClientHello: ECH accepted. The client has recovered without a new DNS lookup.
Measurement Idea
Servers rotate their ECH keys, and clients may still hold an outdated configuration, for example from a DNS cache. ECH has a recovery path for this: a server that cannot decrypt the ECH extension answers with its current configuration, the retry configuration, and the client tries again with it.
Our method uses exactly this recovery path, and so does not rely on DNS. In place of an outdated key, we send an ECH extension under a random key, which no server can decrypt. A standard-compliant ECH server answers it as it would answer a client after a key rotation: with its retry configuration. We then use that configuration in a second connection to test whether ECH actually works.
example.com without ECH
Result: No ECH
example.com with ECH
Result: ECH accepted or ECH rejected
We send example.com an ECH extension under a random key, shown for both cases: example.com without ECH, left, and with ECH, right. Only with ECH does it answer with a retry configuration, and a second connection with it tests whether ECH actually works.
We open a TLS connection to example.com. Its ClientHello names the target in the SNI and carries an ECH extension encrypted under a random key of our own, so a server can parse it but not decrypt it, the same as GREASE ECH.
Without ECH, the server ignores the extension and completes an ordinary handshake, without retry_configs. With ECH, it cannot decrypt the inner ClientHello either, so it completes the handshake with the outer one and, as the standard requires, sends its current ECH configuration in retry_configs inside its EncryptedExtensions: a public key and a public name. This works even if the domain announces no ECH in DNS.
Without ECH, the server gave us no retry configuration, so there is nothing to retry with and no second connection: the result is No ECH. With ECH, we open a second connection, now with the configuration the server handed out: the SNI names only the public name, and the ECH extension holds the inner ClientHello for example.com, encrypted under the retry key.
The server decrypts the inner ClientHello and accepts ECH: ECH accepted. If it does not accept the configuration it handed out a moment ago, for example because it rotated its key in between, it sends new retry_configs or the handshake fails: ECH rejected.
How the Measurement Works
1. Capturing DNS entries.
Every name is queried for its HTTPS resource record. A record may carry an
ech parameter holding one or more ECH configurations: the public key and
public name a client needs to encrypt its ClientHello before it ever talks to the
server. Each configuration found is decoded, so the site knows not just that a
name announced ECH but also which key, config id and cipher suites.
Setup of the DNS Measurement
Every name on the list is queried for its HTTPS resource record with
zdns. An HTTPS record can carry
an ech parameter with one or more ECH configurations. Each configuration
holds the public key and the public name a client needs to encrypt its ClientHello. We
decode every configuration with
echtool, so the dataset
records the config id, the public name and the cipher suites, not only that a
configuration was present.
A name counts as ECH in DNS when any answer in its HTTPS record carried an ECH configuration.
2. Measuring web server behavior.
This step consists of two separate measurements: every name is probed once over TCP
with HTTP/2 and once over QUIC with HTTP/3. Each probe offers a generated ECH extension that the server cannot decrypt.
If the server supports ECH, it must return its current ECH configuration in retry_configs.
We then probe again with this ECH configuration.
We group results into:
| Status | Meaning |
|---|---|
| ECH accepted | The handshake completed with the encrypted ClientHello, using the configuration the server provided. The server supports ECH. |
| ECH rejected | The server supports ECH and returned retry configurations, but did not accept the second connection that used them. This can happen, e.g., after a key rotation. |
| No ECH | The connection worked without ECH, or the server ignored the ECH extension. The server does not support ECH. |
| Probe failed | Covers several kinds of errors, e.g., name resolution failures and timeouts. This is a finding about the path, not about ECH. |
Setup of the TCP and QUIC Measurements
Every name is then probed twice with a zgrab2-based scanner: over TCP with HTTP/2 and over
QUIC with HTTP/3. The probe sends a GREASE ECH extension, an ECH request the server cannot decrypt.
A server that implements ECH according to the standard cannot decrypt it, so it completes the handshake with the
outer ClientHello and returns its current ECH configuration in retry_configs inside its EncryptedExtensions. This finds servers that support ECH even when they do not publish a configuration in DNS.
We join the three measurements into one view based on the domains actively probed.
Which Domains Are Probed?
We measure the Chrome UX Report (CrUX) top million list, taken from the crux-top-lists repository. Each measurement uses the most recent list that was published before the measurement started.
CrUX ranks the origins that browsers actually visit. It therefore contains www.example.com far more often than example.com. This is why the site reports both queried names and the registrable domains (second-level domains) behind them.
Aggregation of Public Names
The ranking by ECH public name counts, for each public name, the domains that completed an ECH handshake under it. A domain configured under more than one public name is counted under each, so the bars can add up to more than the total. Some providers give every domain its own random public name below a common domain, for example ab12cd34.example.com. These are combined into one entry, *.example.com, in the ranking. The stored measurements keep the original names.
Discovering Encrypted Client Hello Deployments by Active ECH Probing
Abstract. We present a new measurement method to detect ECH deployments. This method leverages standard-compliant behavior of ECH servers. Prior measurements relied on DNS exposure and reported only one major ECH deployment (Cloudflare). Our measurements reveal yet undiscovered ECH deployments, including a large deployment at Meta. Meta servers support ECH, but ECH configuration is not exposed via the DNS. We also empirically study details such as the level of privacy improvement and latency impact of ECH.
If you use data or tools, please cite our paper:
Jonas Mücke, Konstantin Gasser, Thomas C. Schmidt, and Matthias Wählisch. 2026. Discovering Encrypted Client Hello Deployments by Active ECH Probing. In Proceedings of the 2026 ACM Internet Measurement Conference (IMC '26). ACM, New York, NY, USA, 276–286. https://doi.org/10.1145/3777912.3839832
@inproceedings{10.1145/3777912.3839832,
author = {M{\"u}cke, Jonas and Gasser, Konstantin and Schmidt, Thomas C. and W{\"a}hlisch, Matthias},
title = {Discovering Encrypted Client Hello Deployments by Active ECH Probing},
year = {2026},
isbn = {9798400723278},
publisher = {ACM},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/3777912.3839832},
doi = {10.1145/3777912.3839832},
abstract = {We present a new measurement method to detect ECH deployments. This method leverages standard-compliant behavior of ECH servers. Prior measurements relied on DNS exposure and reported only one major ECH deployment (Cloudflare). Our measurements reveal yet undiscovered ECH deployments, including a large deployment at Meta. Meta servers support ECH, but ECH configuration is not exposed via the DNS. We also empirically study details such as the level of privacy improvement and latency impact of ECH.},
booktitle = {Proceedings of the 2026 ACM Internet Measurement Conference},
pages = {276–286},
numpages = {11},
keywords = {ECH, TLS, HTTPS, DNS, privacy, hypergiant deployment},
location = {Karlsruhe, Germany},
series = {IMC '26}
}