API documentation
Free JSON API for HTTP/3 checks – no signup, no key, CORS enabled.
Overview
The API is free, needs no signup and no API key. It answers JSON and sends
Access-Control-Allow-Origin: *, so you can call it straight from a browser.
Rate limit: 15 requests / 60s per IP address.
GET /api/v1/check
Runs a real check: reads the Alt-Svc header, then opens an actual QUIC connection.
Takes a few seconds because it talks to the target server.
curl "https://h3check.de/api/v1/check?domain=example.org"
| Parameter | Values | Meaning |
|---|---|---|
domain | required | Domain to check. https://, paths and ports are stripped automatically. |
host | auto · root · www | Check as given, force without www., or force with it. Default auto. |
share | 0 · 1 | Default 0. With 1 the domain appears in the public list and gets a page under /check/. |
Note on privacy: API calls do not publish anything by default. If you
check customer domains, leave share alone.
Response
{
"domain": "example.org",
"ok": true,
"advertised": {
"alt_svc": "h3=\":443\"; ma=86400",
"advertises_h3": true
},
"connection": {
"tls_version": "TLS 1.3",
"tls_cipher": "TLS_AES_256_GCM_SHA384",
"negotiated_version": "2",
"has_ipv6": true
},
"verified": {
"http3_only": true,
"curl_http_version": "3",
"http_code": 200,
"effective_url": "https://example.org/",
"hint": null,
"response_headers": "HTTP/3 200 ...",
"has_headers": true
},
"self_check": { "detected": false, "hint": null }
}
The two fields that matter: advertised.advertises_h3 says the server
promises HTTP/3, verified.http3_only says it actually
delivered it. Promise without delivery is nearly always a firewall blocking
UDP/443 – see enabling HTTP/3.
verified.response_headers contains the raw headers and can be a couple of
kilobytes. Ignore the field if you do not need it.
GET /api/v1/cached
Returns the stored result of the last public check – no live connection, answers instantly and is not worth rate-limiting yourself over. Ideal for dashboards and badges.
curl "https://h3check.de/api/v1/cached?domain=example.org"
{
"ok": true,
"cached": true,
"domain": "example.org",
"checked_at": 1785421715,
"checked_at_iso": "2026-07-30T14:28:35+00:00",
"http3": { "working": true, "advertised": true, "alt_svc": "h3=\":443\"; ma=86400" },
"connection": { "tls_version": "TLS 1.3", "has_ipv6": true, "http_code": 200 },
"stack": { "server": "cloudflare", "cdn": "Cloudflare" }
}
advertised and has_ipv6 may be null — that means "not measured", not "no".
Errors
| Status | error_code | When |
|---|---|---|
| 400 | invalid_domain | Not a valid domain, or an example domain. |
| 404 | not_cached | /cached only: no stored result yet. |
| 429 | rate_limited | Rate limit hit. Retry-After tells you how long to wait. |
Errors are JSON too, and always carry "ok": false.
Examples
// JavaScript – works from the browser thanks to CORS
const r = await fetch('https://h3check.de/api/v1/check?domain=example.org');
const data = await r.json();
console.log(data.verified.http3_only ? 'HTTP/3 works' : 'no HTTP/3');
<?php // PHP
$d = json_decode(file_get_contents(
'https://h3check.de/api/v1/cached?domain=example.org'
), true);
echo $d['http3']['working'] ? 'yes' : 'no';
Badge
Every domain that was checked publicly has an SVG badge that updates itself:
<img src="https://h3check.de/badge/example.org.svg?lang=en" height="30">
Stability
The /api/v1/ path is versioned: fields may be added, but existing ones will not
change meaning or disappear. The older form /?domain=…&format=json keeps
working and returns the same object as /api/v1/check.