Test servers
The servers exercised by the latest run come first. The catalog below explains those results and records other useful fixtures, but a catalog entry is not counted as coverage until a published suite or endpoint probe backs it.
Current results
Probed public endpoints
Reachability is recorded separately from assertions so an unavailable third-party server is not mistaken for a client regression.
Why document the wider landscape
OkHttp's own test suite talks to MockWebServer, which shares its framing and its TLS setup with
the client under test. That is the right way to test parsing and state machines, and it is
structurally unable to answer a different class of question: does the ClientHello OkHttp emits
look acceptable to a CDN, does 1.1.1.1 still return the HTTPS record
the ECH code needs, is an expired certificate still refused on Android 14 as it is on JDK 21.
Those are properties of the internet and of the platform, and they are checked by running
against them.
Nearly every serious HTTP or TLS client does some version of this. rustls keeps a
connect-tests crate that opens real connections to a fixed list of top sites and to
badssl.com. curl documents public HTTP/3 endpoints for exactly this reason. The browsers built
badssl.com in the first place, to have somewhere to point their certificate-error UI at. What
follows explains the servers behind current results and identifies candidates for future
results. Only the evidence blocks above say what ran.
The two rules behind these results
Network tests have a bad reputation, and it is deserved when they are written carelessly. Two rules keep them worth having:
- A test asserting a connection succeeds is fragile against the internet; one asserting it is refused is not. Certificates get renewed, CDNs move, resolvers rate-limit. So the strongest network suite available is the one where every assertion is negative — the badssl matrix — and positive assertions belong against something we control.
-
Self-host what we can; reach out for what we cannot. go-httpbin and badssl
both ship containers. Most of the HTTP-semantics and bad-chain coverage can run in
containers, fatal and deterministic, with the public endpoint checking the same property against the real internet. Agreement is the expected result; disagreement is the finding.
Everything that reaches a third party lands in a suite that
reports rather than gates, alongside loomTest. A rate
limit at Cloudflare is not this repository being red.
HTTP semantics and request echo
| Server | Operator | What it is good for | Caveat |
|---|---|---|---|
| httpbin.org | Kenneth Reitz | The original. Redirects, status codes, auth, compression, streaming, cookies, delays — the vocabulary every later service copied. | Rate-limited and intermittently down. Worth one smoke request, not a suite. |
| httpbingo.org | Will McCutchen | A complete Go port of httpbin with no dependencies outside the stdlib. The public instance of go-httpbin. |
Same endpoints, better uptime; still someone else's server. |
| ghcr.io/mccutchen/go-httpbin | Will McCutchen | The container. Published per release for amd64 and arm64. This is where the HTTP-semantics assertions should actually live. | None worth mentioning — pin the tag, as mockserver is pinned. |
| testserver.host | HTTP Toolkit | The one built for hostile cases: malformed chunking, resets mid-body, invalid framing. Endpoints are chainable, so /delay/1/error/reset is one request. Self-hostable as a single container. |
Newer and less widely used than httpbin, so less battle-tested as a reference. |
| pie.dev | HTTPie | A third httpbin instance — a tiebreaker when two disagree. | Undocumented as a public API. |
| postman-echo.com | Postman | Request echo, good for header fidelity specifically. | Commercially operated; terms may change. |
| nghttp2.org/httpbin | Tatsuhiro Tsujikawa | httpbin's endpoints served over HTTP/2 by the reference C implementation — the same assertions, one protocol up. | One person's server. Do not lean on it. |
The endpoint worth singling out is /anything, which echoes the whole request back as
JSON. It is the only honest check of what OkHttp sent — header order, casing,
Accept-Encoding, Connection — rather than what it claims to have sent.
HTTP/2 and HTTP/3
| Server | Protocol | What it is good for |
|---|---|---|
| nghttp2.org | h2, h2c | An independent framing and HPACK implementation. Connection coalescing, GOAWAY, flow control and trailers against something that does not share OkHttp's code. |
| cloudflare-quic.com | h3 | Advertises h3 over Alt-Svc. Since OkHttp has no HTTP/3, the test is that the advertisement is ignored gracefully. |
| quic.nginx.org | h3 | NGINX's QUIC preview — a second h3 implementation to compare fallback behaviour against. |
| quic-interop-runner | QUIC, h3 | Every participating QUIC implementation packaged as a Docker image behind one interface, with a network simulator. The ready-made local matrix if HTTP/3 support ever lands. |
| h2spec | h2 | Listed to rule it out: h2spec is a server conformance tool. It is useful for validating a local h2 fixture before trusting its results, and not for testing a client. |
TLS
| Server | Operator | What it is good for | Caveat |
|---|---|---|---|
| badssl.com | Chrome and Firefox contributors | The canonical broken-configuration matrix: expired, wrong host, self-signed, untrusted root, incomplete chain, revoked, SHA-1, weak DH, RC4, 3DES, null, and the known-compromised keys shipped in real products (Superfish, eDellRoot). Per-version ports — tls-v1-0…:1010, :1011, :1012 — and client-certificate endpoints. Self-hostable from the repository, which generates its own CA. |
Explicitly best-effort: "anything could change without notice". Not an official Google product. |
| howsmyssl.com/a/check | Jeff Hodges | Returns JSON describing the client's own ClientHello: negotiated version, offered cipher suites, session-ticket and ephemeral-key support, and a rating. A machine-readable view of what OkHttp sends. | Offered for testing clients under your control — one request per scheduled run, never in a loop. |
| browserleaks.com/tls | BrowserLeaks | JA3 and JA4 fingerprints, the full extension and supported-group lists. The decoded ClientHello rather than a summary. | Built for browsers; the HTML view needs scraping to be machine-readable. |
| SSL Labs client test | Qualys | The reference analysis of a client's handshake, including suite ordering and known-weakness flags. | Reference material rather than an assertion target. |
| browserscan.net, tlsfingerprint.io | various | JA3/JA4 plus HTTP/2 fingerprints — SETTINGS values, header ordering, priority — which is the other half of how a CDN identifies a client. |
Commercial or research services with no uptime promise. |
| tls-o-matic.com | Simon Josefsson | A port per client-authentication scenario — useful as a second implementation of mutual TLS with different CertificateRequest contents. |
Small, volunteer-operated. |
| tls13.akamai.io | Akamai | A TLS 1.3 endpoint on a stack that is neither OpenSSL-on-Linux nor Cloudflare. | A demo page, not a documented service. |
The JA3/JA4 services deserve more weight than they first appear to. The ClientHello OkHttp produces is mostly the platform's, and if it shifts between releases or between Android API levels, every OkHttp application's treatment by Cloudflare, Akamai and DataDome shifts with it. Users experience that as "the API started returning 403 after we upgraded", and today nobody can point at what changed.
DNS
| Endpoint | Operator | What it is good for |
|---|---|---|
| https://1.1.1.1/dns-query | Cloudflare | Addressed by IP, so resolving the resolver needs no resolver. Returns HTTPS records including the ech parameter. |
| https://dns.google/dns-query | A second implementation, with a JSON API alongside the wire format — so its own answers can be cross-checked. | |
| https://dns.quad9.net/dns-query | Quad9 | Filtering resolver: the case where an answer is deliberately withheld. |
| https://dns.adguard-dns.com/dns-query | AdGuard | A second filtering resolver, filtering different things. |
| www.dnssec-failed.org | Comcast | The long-standing bogus-signature name: SERVFAIL from any validating resolver. |
| sigok / sigfail.ippacket.stream | — | A matched pair that isolates DNSSEC validation from reachability. |
| rootcanary.org | NLnet Labs and partners | Per-algorithm validation, including the newer algorithms where resolvers genuinely differ. |
| test-ipv6.com | Jason Fesler | ipv4., ipv6. and ds. names for Happy Eyeballs — single-stack and dual-stack answers on demand. |
| ipv4only.arpa | IETF (RFC 7050) | A name that is v4-only by definition, and stays that way. |
Encrypted Client Hello
| Endpoint | Operator | What it is good for |
|---|---|---|
| https://crypto.cloudflare.com/cdn-cgi/trace | Cloudflare Research | Answers sni=encrypted or sni=plaintext. A machine-readable ECH result is rare, and it is what makes this the primary public target. |
| defo.ie | DEfO (ECH for OpenSSL) | The interop reference: hosts exercising acceptance, retry-config, GREASE and rejection, against OpenSSL rather than Go. domainechprobe checks any name's HTTPS RR and ECHConfigList server-side. |
| https://tls-ech.dev/ | Cloudflare Research | A second Cloudflare-side configuration. |
ech-fixture (container) |
this repository | What runs today — origin and DoH resolver, three hostnames for accepted, retried and declined. See the ECH page. |
ECH configurations rotate, so a config list must always come from DNS at run time and never be pinned in a test. That is not a workaround; it is the mechanism working as designed.
The roadmap
Tracked in issue #5. Nothing below is implemented yet — this page is the plan on the record before the code is.
| Phase | Issue | Servers involved |
|---|---|---|
| Infrastructure | #6 A network suite that reports rather than gates |
— |
| #7 Reachability preflight, and endpoint availability on this site | all of them | |
| #8 Self-host the fixtures we depend on | go-httpbin, badssl, nghttp2 or Caddy | |
| HTTP | #9 HTTP semantics against the httpbin family | go-httpbin, httpbingo, pie.dev, postman-echo |
| #10 Hostile and malformed responses | testserver.host | |
| #11 HTTP/2 against an independent stack | nghttp2.org, local nghttpd | |
#12 HTTP/3 and Alt-Svc: record what OkHttp does today |
cloudflare-quic, quic.nginx.org, interop runner | |
| TLS | #13 The badssl matrix: chains that must be rejected | badssl.com, local badssl |
#14 Version and cipher policy through ConnectionSpec |
badssl version ports, tls13.akamai.io | |
| #15 Client certificates against a real server | client.badssl.com, tls-o-matic | |
| #16 Revocation, pinning and Certificate Transparency | revoked and pinning-test badssl | |
| #17 Publish the ClientHello OkHttp actually emits | howsmyssl, browserleaks, SSL Labs | |
| DNS | #18 The DoH resolver matrix | Cloudflare, Google, Quad9, AdGuard, NextDNS |
#19 HTTPS and SVCB record consumption |
public names, extended ech-fixture |
|
| #20 Resolver failure modes: SERVFAIL, bogus, NXDOMAIN | dnssec-failed.org, sigok/sigfail, rootcanary | |
| #21 Happy Eyeballs against real names | test-ipv6.com, ipv4only.arpa, local dual-stack | |
| ECH | #22 ECH against public servers | crypto.cloudflare.com, defo.ie, tls-ech.dev |
What was considered and left out
- h2spec and h3spec. Server conformance tools. Useful for validating a local fixture, useless for testing a client.
- Top-site sweeps. rustls connects to a list of large sites and asserts the handshake completes. It is a real smoke test, but a failure names a website rather than a behaviour, so it produces alerts nobody can act on. One or two, not thirteen.
- Load and performance targets. Not against servers other people pay for.
-
Anything needing
okhttp3.internal. The public-API-only rule is what makes-PokhttpVersionmean something, and it is enforced bycheckPublicApiOnly.
Being a good citizen
Every server on this page is operated by someone else, most of them for free, several by one person. The testbed's daily schedule is the whole budget: one request per endpoint per run, no retries in a loop, no network suites on pull requests, and a preflight that skips an endpoint that is throttling rather than hammering it. Where a service asks to be used only for clients under your control — How's My SSL says so explicitly — that is exactly what this is.
The live suite and endpoint blocks at the top of this page are the coverage record. Entries in this catalog without a matching result remain documentation or roadmap candidates.