glossary / turnstile widget modes

Cloudflare Turnstile widget modes: managed, non-interactive and invisible

Cloudflare Turnstile runs in one of three widget modes — managed, non-interactive or invisible — chosen per widget in the Cloudflare dashboard and carried by that widget's sitekey, not by your page markup. Managed shows a checkbox only when Cloudflare decides an interaction is needed, non-interactive shows a widget with a loading spinner but never prompts the visitor, and invisible runs the challenge in the background with no widget and no loading indicator.

The three widget modes

A Turnstile widget is a configuration object in your Cloudflare account. Cloudflare's own definition: a widget "defines how Turnstile behaves on your webpage" and "has a mode, a label, a sitekey, and a secret key". You can create as many widgets as you need, each with its own mode, and each with its own sitekey and secret key pair.

ModeWhat rendersVisitor interactionCloudflare's stated use case
Managed (recommended)A visible widget that adapts to the visitorA checkbox, only when a further check is neededSimple setup with adaptive security
Non-InteractiveA visible widget with a loading spinnerNeverMinimise friction while showing verification is occurring
InvisibleNothing visibleNeverMaximise visual experience with zero visible verification elements

The mode is the only thing that decides whether a human is ever asked to click. Everything else — size, theme, when the widget appears — is presentation, set from markup, and cannot turn one mode into another.

What each mode renders

Managed mode is fully managed by Cloudflare. It chooses an action from client-side signals and risk level, and "will only require interaction if a further check is necessary to verify that the visitor is human". When that happens the visitor is prompted to select a box. There are no images or text to decipher — Turnstile has no picture grids at any point.

Non-interactive mode shows the same physical widget with a loading spinner while the challenge runs in the browser, but the visitor "will never be required or prompted to interact with the widget". It is a visible receipt for work happening in the background.

Invisible mode behaves like non-interactive with the widget removed: no widget, and no indication that a browser challenge is in progress. Cloudflare attaches a condition to it — as a condition of enabling invisible mode, you must reference Cloudflare's Turnstile Privacy Addendum in your own privacy policy.

  • Managed can be interactive. Non-interactive and invisible cannot.
  • Managed and non-interactive occupy layout space. Invisible has no visual footprint.
  • All three run the same underlying challenge platform; the mode governs presentation and whether a click is ever demanded.

Widget states, and where an interaction can appear

A widget moves through loading (processing), interaction (visitor checks the box, managed mode only) and success. That parenthetical is the single most useful fact on this page for identification: if you ever see a Turnstile checkbox, the widget is in managed mode.

Four documented error states replace success, and each one is a distinct visual:

StateWhen it appears
Unknown errorAn unknown error occurred during the challenge. The visitor can follow the troubleshooting guidance in the widget or reload.
Interaction timed outA checkbox was presented and not interacted with for an extended period. The challenge must be reissued by reloading the page or the widget.
Challenge timed outVerification completed but no further action was taken, so the outcome is no longer valid — for example a login page solved but never submitted.
Outdated or unsupported browserThe visitor's browser is not supported.

Whatever the mode, the token that comes out is the same object: valid for five minutes, single-use, and rejected on replay by the siteverify endpoint with timeout-or-duplicate.

How the mode is set

In the dashboard, Turnstile lives at the account level. Select Add widget, then fill in the widget name, hostname management (the domains it will be deployed on), the widget mode, and optionally pre-clearance support. Select Create, then store the sitekey and the secret key. An existing widget's configuration is edited under its Settings and applied with Save.

Over the API, the widget object carries mode with exactly three values — managed, non-interactive, invisible — alongside sitekey, name, domains and clearance_level (no_clearance, jschallenge, managed, interactive). Note that region (world or china) cannot be changed after creation.

Everything here assumes automation against properties you own or are authorised to test — QA, CI, uptime monitoring, staging, and tuning your own anti-bot configuration. That is the boundary SolveGate is built for.

Data attributes change the presentation, not the mode

Implicit rendering is a script tag plus a container with the cf-turnstile class. Inside a form, an invisible input named cf-turnstile-response is created automatically and carries the token.

html
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

<form method="POST" action="/login">
  <div class="cf-turnstile"
       data-sitekey="0x4AAAAAAAAA_target"
       data-size="flexible"
       data-appearance="interaction-only"></div>
  <button type="submit">Sign in</button>
</form>

api.js must be fetched from that exact URL — proxying or caching it will break Turnstile when Cloudflare ships updates. Turnstile is hosted under challenges.cloudflare.com, so a Content Security Policy has to allow connections to that origin.

Data attributeDefaultValuesWhat it does
data-sitekeyrequiredyour sitekeyIdentifies the widget — and therefore the mode
data-sizenormalnormal, flexible, compactWidget dimensions
data-themeautolight, dark, autoVisual theme
data-languageautoISO 639-1, e.g. es, en-USWidget language
data-appearancealwaysalways, execute, interaction-onlyWhen the widget becomes visible
data-executionrenderrender, executeWhen the challenge runs and a token is generated
data-actionalphanumeric, _, -, max 32 charsLabel returned at validation, for analytics
data-cdataalphanumeric, _, -, max 255 charsCustom payload returned at validation
data-response-fieldtruetrue, falseWhether to create the hidden token input
data-response-field-namecf-turnstile-responseanyName of that hidden input
data-retryautoauto, neverAutomatic retry on a failed challenge
data-retry-interval8000positive integer < 900000Milliseconds between retries
data-refresh-expiredautoauto, manual, neverBehaviour when a token expires
data-refresh-timeoutautoauto, manual, neverBehaviour when an interactive challenge times out
data-tabindex0anytabindex of the widget iframe
data-feedback-enabledtruetrue, falseVisitor feedback link

Callbacks follow the same pattern: data-callback, data-error-callback, data-expired-callback, data-timeout-callback, data-unsupported-callback, and the pair that matters for identification — data-before-interactive-callback and data-after-interactive-callback, invoked before and after the challenge enters interactive mode. With explicit rendering the same names are passed as object keys to turnstile.render(), minus the data- prefix.

Sizes apply to the two visible modes only. Invisible widgets have no visual footprint regardless of the size configured.

SizeWidthHeightUse case
normal300px65pxStandard implementation
flexible100% (min 300px)65pxResponsive design
compact150px140pxSpace-constrained layouts

The same restriction applies to appearance: always shows the widget from page load, execute reveals it once the challenge begins, and interaction-only reveals it only when interaction is required — but appearance modes affect visible widget types only, and invisible widgets are never shown whatever it is set to. data-appearance="interaction-only" on a managed widget is what produces a page that looks empty until a suspect visitor arrives; it is not the same thing as invisible mode.

How to tell which mode a site uses

Start with the markup. These are the reliable markers that Turnstile is present at all:

  • A script tag for https://challenges.cloudflare.com/turnstile/v0/api.js, optionally with ?render=explicit and &onload=<fn>.
  • A container with class="cf-turnstile" and a data-sitekey attribute.
  • A turnstile.render() call carrying a sitekey option, for explicit rendering in single-page apps.
  • A hidden input named cf-turnstile-response in the submitted form — or whatever data-response-field-name renamed it to.
  • An iframe inserted into the container and served from challenges.cloudflare.com, plus CSP entries allowing that origin.

What the markup will not tell you is the mode. The mode lives on the widget in Cloudflare's account configuration and travels with the sitekey; the Turnstile API exposes mode only for widgets in your own account. Reading the page gives you the sitekey, and then you have to observe.

Two observations settle most cases. If the container renders with zero height and nothing appears at any point, the widget is invisible. If a checkbox ever appears, the widget is managed, because interaction is a managed-mode state. A visible widget that solves without a prompt is the ambiguous case — that is managed passing silently, or non-interactive, and a single page load cannot separate them.

For a widget you own, or a sitekey whose hostname list includes the page you are testing on, render it explicitly and instrument the interactive callbacks:

html
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=onTurnstileLoad" defer></script>
<div id="probe"></div>

<script>
  function onTurnstileLoad() {
    turnstile.render("#probe", {
      sitekey: "0x4AAAAAAAAA_target",
      "before-interactive-callback": function () {
        console.log("entered interactive challenge -> managed mode");
      },
      "after-interactive-callback": function () {
        console.log("left interactive challenge");
      },
      callback: function (token) {
        var box = document.querySelector("#probe").getBoundingClientRect();
        console.log("height", box.height, "-> 0 means no visual footprint");
        console.log("token chars", token.length);
      },
      "error-callback": function () {
        console.log("challenge error");
      }
    });
  }
</script>

If the sitekey you find is one of Cloudflare's documented dummy keys, you are looking at a test or staging build, not production traffic:

SitekeyBehaviourWidget type
1x00000000000000000000AAAlways passesVisible
2x00000000000000000000ABAlways failsVisible
1x00000000000000000000BBAlways passesInvisible
2x00000000000000000000BBAlways failsInvisible
3x00000000000000000000FFForces an interactive challengeVisible

Matching dummy secret keys exist for the server side: 1x0000000000000000000000000000000AA always passes validation, 2x0000000000000000000000000000000AA always fails, and 3x0000000000000000000000000000000AA returns the token-already-spent error.

Widget modes are not WAF challenge pages

A Turnstile widget is embedded by the site owner into their own page and works without routing traffic through Cloudflare. A WAF challenge page is served by Cloudflare in front of the origin, as an interstitial, before the page you asked for exists. They share a challenge platform but they are different surfaces, and they fail differently: a widget failure leaves you on the page with an unusable form, a WAF challenge failure leaves you never reaching the page.

Pre-clearance is the documented bridge between them. A widget configured with pre-clearance issues a cf_clearance cookie, which lets a visitor bypass WAF challenges on subsequent requests across the zone, including API requests, at the clearance level the customer set. That is why a login page can carry a Turnstile widget and the API calls after it can pass without further challenges.

SolveGate treats the two as separate targets: gate: "turnstile" for the embedded widget in any of its three modes, gate: "waf" for a Turnstile WAF challenge page. Those are the only two gates it handles — it does not solve reCAPTCHA, hCaptcha, GeeTest, FunCaptcha or AWS WAF.

Solving Turnstile against your own properties

For automation purposes the mode barely matters. Managed, non-interactive and invisible all resolve to the same thing on the wire — a sitekey, a page URL, and a token that your server-side validation will accept for five minutes, once. You send the same request whichever mode the widget was configured in.

bash
curl -s https://api.solvegate.io/v1/solve \
  -H "Authorization: Bearer $SOLVEGATE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "gate": "turnstile",
    "sitekey": "0x4AAAAAAAAA_target",
    "url": "https://staging.example.com/login"
  }'

A token typically comes back in under 1.5 seconds. Pass "async": true to return immediately and poll GET /v1/solve/{id} instead; retrieving a solve is free. Failed solves are never billed. Prepaid credits start at $0.40 per 1,000 solves and fall to $0.075 at volume, and the first 1,000 solves are free.

The SDKs are published as solvegate on npm (Node 18+) and PyPI (Python 3.9+). Both wrap auth, the error envelope, 429 backoff and async polling, and both take the same gate, sitekey, url and optional action arguments.

Common questions

No. The markup carries the sitekey; the mode is stored on the widget in the Cloudflare account that owns that sitekey. You can infer it by observing: nothing rendered means invisible, and a checkbox means managed, because interaction is a managed-mode state. A visible widget that never prompts could be either managed or non-interactive.

No. data-size takes normal, flexible or compact, and it applies to managed and non-interactive widgets only. Invisible is a widget mode set in the Cloudflare dashboard, and an invisible widget has no visual footprint regardless of the size configured.

interaction-only is a presentation setting on a visible widget: it stays hidden until an interaction is required, then appears. It only affects managed and non-interactive widgets. Invisible mode has no widget at any point and can never show one, whatever appearance is set to.

The mode is part of a widget's configuration, editable from that widget's Settings in the Turnstile dashboard and applied with Save. Region (world or china) is the field that cannot be changed after creation.

No. Whichever mode issued it, the Turnstile token is valid for five minutes, can be validated once, and a replayed token is rejected by siteverify with timeout-or-duplicate.

Yes. POST /v1/solve with gate: "turnstile", the sitekey and the page URL covers managed, non-interactive and invisible widgets, and gate: "waf" covers Turnstile WAF challenge pages. Use it against properties you own or are authorised to test.

Related

More in Glossary

Automating a gate you own or are authorised to test?

// SolveGate clears Cloudflare Turnstile and WAF challenges through one REST call · first 1,000 solves free