Methodology v2.0.0
How this benchmark works
What is measured, what is thrown away, how the numbers are summarised — and, at the end, an honest list of what this test cannot tell you.
What is measured
When you start a run, your browser issues real DNS-over-HTTPS queries to each participating resolver and times how long each one takes to return a response that passes validation. The unit being measured is precisely this: the time for your browser to complete an HTTPS request to a resolver’s DoH endpoint and for the answer to be verified. Nothing more is claimed.
What counts as a measurement
This is where the previous version of this tool was wrong, and it is worth being specific about it.
Version 1 issued its requests with mode: 'no-cors'. That produces an opaque
response: the browser completes the request but refuses JavaScript any access to the status code,
the headers or the body. The old engine therefore timed something arriving and called it a
DNS answer. An HTTP 400, a rate-limit page, a captive-portal login screen or a TLS handshake to a
host that then refused the query all looked identical to a fast, correct DNS response — and
the fastest of those errors would rank first.
Version 2 refuses to count anything it cannot read. Every timed request must survive all six of these checks before it contributes a single number:
- Readable. The request is made with
mode: 'cors'. If the provider does not permit a cross-origin read, the fetch fails and we record that, rather than timing something opaque. - HTTP OK. Any non-2xx status is classified as an HTTP error and excluded.
- Correctly typed. The response must carry
application/dns-messagefor RFC 8484 wire-format replies, or a documented DoH JSON content type. - Parseable. The body is decoded as an actual DNS message. A truncated, malformed or wrong-shaped body is a parse error, not a slow answer.
- Question-matched. The response’s question section must echo the exact name and record type we asked for. A reply about a different name is discarded.
- Expected result code. The DNS RCODE must be the one the test case expects. SERVFAIL and REFUSED are recorded as failures. For the negative test, anything other than NXDOMAIN — including a synthesised address for a name that does not exist — is excluded.
A resolver that fails these checks is not converted into a large latency figure and ranked near the bottom. It is removed from the ranking entirely and listed separately with the reason.
Protocol handling
Not every DoH endpoint accepts the same request. Google Public DNS documents a JSON API at
/resolve and a separate RFC 8484 endpoint at /dns-query; they are not
interchangeable, and assuming otherwise was another v1 defect. This version builds a real DNS wire
message, encodes it as unpadded base64url in the dns parameter as
RFC 8484
specifies, and parses the binary reply — including name-compression pointers. Where a
provider documents a JSON API instead, the JSON adapter is used with that provider’s
documented Accept header.
The test cases
Queries use controlled names under a domain we operate, not random subdomains of unrelated third-party sites. Random names beneath somebody else’s domain mix in their wildcard records, their rate limits and their authoritative servers — and put a test identifier into their logs. Two cases are offered:
- Cached lookup. A name that resolvers will already have. This is closest to what you experience most of the time.
- Uncached lookup. A random label that cannot be in any cache, so the resolver must do recursive work and return NXDOMAIN. This is an upper bound, not a typical result.
The expectation for each case is asserted rather than assumed. If the negative probe ever stops returning NXDOMAIN, the engine reports the fixture as broken instead of quietly averaging in meaningless numbers.
Sampling
Resolvers are measured in interleaved rounds, with the order shuffled every round. Testing one resolver repeatedly and then moving to the next would hand whichever went first whatever conditions happened to prevail then — a warm radio, an idle link, a cool device.
Concurrency is deliberately low. The previous version fired twelve resolvers simultaneously, which on an ordinary connection measures the benchmark competing with itself as much as it measures the resolvers. Quick mode runs 5 rounds; thorough mode runs 11 with a longer timeout.
Statistics
- Median, not mean. Network latency is right-skewed; one stall should not decide a ranking.
- Median absolute deviation is reported beside every median as a robust measure of spread.
- Percentiles are withheld until there is enough data. A 95th percentile computed from three samples is arithmetic, not information, so it is only shown from eight samples upward.
- Success rate counts every attempt, including failures, so availability is visible rather than hidden by only counting the successes.
- No sample is silently dropped. The old code claimed to discard the slowest sample but its condition (four or more samples) could never be true, because it only ever collected three. Nothing is discarded now, and the median makes discarding unnecessary.
Ranking and ties
Resolvers are ordered by median. Two resolvers whose medians differ by less than the test can resolve are marked effectively tied and share a rank. The threshold is the larger of 3 ms or 1.5× the greater of the two spread figures.
There is no longer a composite score out of 100. The old one min-max normalised whatever resolvers happened to respond, weighted latency at 70% and jitter at 30%, applied a floor, and then forced the fastest entrant to at least 96. That guaranteed a satisfying-looking winner in every run regardless of whether the field contained one good resolver or twenty, and the number could not be compared between runs. Raw medians with their spread are less dramatic and mean something.
What this benchmark cannot tell you
Before you start
- It is not classic DNS. The figures are for DNS-over-HTTPS endpoints. Configuring a DNS server in Windows, macOS or a router normally uses that provider’s service on UDP/TCP port 53 — a different endpoint, path and cache. The two usually correlate because it is the same anycast network, but they are not the same measurement, and a browser cannot make the port-53 one.
- It cannot measure resolvers that block cross-origin reads. A DoH endpoint that does not send the necessary headers cannot be measured from any web page. Those resolvers are excluded and named, not penalised with an invented number.
- It is one browser, one network, one moment. Results shift with device, browser, congestion, Wi-Fi conditions and time of day. Run it more than once before acting on a small difference.
- Connection reuse flatters repeat requests. Later requests to the same endpoint may reuse an established TLS session. This is realistic — a browser does the same thing — but it means the first measurement and later ones are not measuring identical work.
- It says nothing about answer quality. Filtering behaviour, DNSSEC validation, privacy policy and uptime over time all matter more than a few milliseconds, and none of them are measured here. The resolver comparison covers those.
Which resolvers take part
Every resolver is defined in RESOLVER-REGISTRY.json, which
records for each one its endpoint, protocol, published addresses, filtering behaviour, official
documentation URL, privacy policy and the date the configuration was last checked against a
primary source. Only entries marked active — verified against the
provider’s own documentation — are benchmarked. Entries whose configuration has not
been re-verified are listed on the comparison page but excluded from measurement, and retired
services are kept in the file so their removal is auditable rather than silent.
Nothing on this site hard-codes a provider count. Every visible figure is rendered from that registry, so the site cannot claim to test resolvers it does not test.
Reproducing and checking this
The validation rules above are covered by a deterministic test suite in the repository: fixtures for valid wire-format and JSON answers, NXDOMAIN, SERVFAIL, REFUSED, truncated responses, malformed bodies, wrong-question responses, HTTP errors, timeouts and cross-origin failures. The gates assert that none of the failure cases can ever receive a latency rank. Every result you export carries the methodology version that produced it.
Related
- Run the benchmark
- What DNS latency actually costs you
- Public DNS resolvers compared
- Frequently asked questions
Last reviewed 2026-08-15. Provider configuration comes from RESOLVER-REGISTRY.json, which records the official source and verification date for every entry.