Paste a URL. We fetch it once and report what the served HTML actually says about Turnstile — whether the widget is there, its sitekey, how it is rendered, its configuration, whether the key is one of Cloudflare's test keys, and whether you are looking at a WAF challenge page instead of a widget.
// free · no account · we fetch the page once from our own address and read the HTML it returns
It reads the HTML the server returns — the same bytes a crawler, a CI job or any non-browser client receives. Everything below is either in that response or it is not, and nothing is inferred beyond it.
challenges.cloudflare.com/turnstile/v0/api.js, a container with class="cf-turnstile", or a turnstile.render() call.data-sitekey or from the sitekey option passed to turnstile.render(). Sitekeys are public by design — they are in the page for every visitor to read.turnstile.render() itself, which is what single-page apps do.data-action, data-cdata, data-size, data-theme, data-appearance, and the response field name if it has been renamed from cf-turnstile-response.The widget mode. Managed, non-interactive and invisible are set per widget in the Cloudflare dashboard and stored against the sitekey inside the account that owns it. The page carries the key and nothing else, so the mode is genuinely not in the source — not for us, and not for any other checker that claims otherwise. What you can do is observe: a container that renders at zero height and never appears is invisible, and a checkbox that appears at any point means managed, because interaction is a managed-mode state. The widget modes page works through the ambiguous case.
A widget that only exists after JavaScript runs. We read the served HTML, not a rendered page. If a site injects its widget from a bundle after load, the checker reports no sitekey and says so plainly rather than guessing. That gap is worth knowing about: it is also what a crawler and a scripted client see.
Whether the key is valid, or which hostnames it allows. That lives in the Cloudflare account, and nothing outside it can read it. A sitekey rejected on your domain usually means the hostname is not on the widget's allowed list, which surfaces as invalid-input-response on validation.
If the key on a page is one of these, the widget is wired for automated tests and will behave the same way every time. These are the only sitekeys whose widget type is public — Cloudflare documents it, so the checker reports it.
| Sitekey | Behaviour | Widget type |
|---|---|---|
1x00000000000000000000AA | Always passes | Visible |
2x00000000000000000000AB | Always fails | Visible |
1x00000000000000000000BB | Always passes | Invisible |
2x00000000000000000000BB | Always fails | Invisible |
3x00000000000000000000FF | Forces an interactive challenge | Visible |
There are matching secret keys for server-side validation, and the full set is on the Turnstile test keys page.
Nothing here is privileged. curl the page and grep for data-sitekey and you have most of it; the sitekey guide covers the explicit-rendering case, extracting a key with Playwright, and the keys you will find that are not real. This page exists because doing it repeatedly is tedious, not because it is hard.
Once you have the sitekey and the page URL, that pair is the whole input to a solve — the mode makes no difference to the request. The solve reference has the call, and the Turnstile solver covers what happens next.
One fetch per check, capped at 2 MB and ten seconds, twenty checks per ten minutes per address. We only ever issue a plain GET, we identify ourselves in the User-Agent, and we return extracted fields rather than the page — this is a checker, not a proxy. Private and reserved addresses are refused, so it cannot be pointed at anything inside a network it can reach but you cannot.
// sitekey + url in, token back in under 1.5s · first 1,000 solves free