Widget configurations

Last updated Jun 28, 2026 Configure your Turnstile widget's appearance, behavior, and functionality using data attributes or JavaScript render parameters.

Rendering methods

Turnstile widgets can be implemented using implicit or explicit rendering.

Implicit rendering automatically scans your HTML for elements with the cf-turnstile class and renders the widget when the page loads. It is best used for simple implementations, static websites, or when you want widgets to appear immediately on page load.

How it works

  1. Add the Turnstile script to your page.
  2. Include <div class="cf-turnstile" data-sitekey="your-key"></div> elements.
  3. Widgets will render automatically when the page loads.
  4. Configure the widget using data-* attributes on the HTML element.

Examplehtml

    <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-theme="light"></div>

Explicit rendering gives you programmatic control over when and how widgets are created using JavaScript functions. It is best used for dynamic websites and single-page applications (SPAs), when you need to control timing of widget creation, conditional rendering based on visitor interactions, or for multiple widgets with different configurations.

How it works

  1. Add the Turnstile script with ?render=explicit parameter.
  2. Create container elements (without the cf-turnstile class).
  3. Call turnstile.render() function when you want to create widgets.
  4. Configure the widget using JavaScript object parameters.

Examplehtml

    <script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit" defer></script>
    <div id="my-widget"></div>

    <script>
    window.onload = function() {
        turnstile.render('#my-widget', {
            sitekey: '<YOUR-SITE-KEY>',
            theme: 'light',
            callback: function(token) {
                console.log('Success:', token);
            }
        });
    };
    </script>

Widget sizes

The Turnstile widget can have two different fixed sizes or a flexible width size when using the Managed or Non-Interactive modes.

Size Width Height Use case
Normal 300px 65px Standard implementation
Flexible 100% (min: 300px) 65px Responsive design
Compact 150px 140px Space-constrained layouts
  • normal: The default size works well for most desktop and mobile layouts. Use this if you have adequate horizontal space on your website or form.
  • flexible: Automatically adapts to the container width while maintaining minimum usability. Use this for responsive designs that need to work across all screen sizes.
  • compact: Ideal for mobile interfaces, sidebars, or any space where horizontal space is limited. The compact widget is taller than normal to accommodate the smaller width.

Note

Widget size only applies to Managed and Non-Interactive modes. Invisible widgets have no visual footprint regardless of size configuration.

Normal size (default)html

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>

Flexible sizehtml

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-size="flexible"></div>

Compact sizehtml

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-size="compact"></div>

Normal size (default)js

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>'
    });

Flexible sizejs

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>',
        size: 'flexible'
    });

Compact sizejs

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>',
        size: 'compact'
    });

Theme options

Customize the widget's visual appearance to match your website's design.

  • auto (default): Automatically matches the visitor's system theme preference. Auto is recommended for most implementations as it respects the visitor's preferences and provides the best accessibility experience.
  • light: Light theme with bright colors and clear contrast. Light theme works best on bright backgrounds and provides high contrast for readability.
  • dark: Dark theme optimized for dark interfaces. Dark theme is ideal for dark interfaces, gaming sites, or applications with dark color schemes.

Auto theme (default)html

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>

Light themehtml

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-theme="light"></div>

Dark themehtml

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-theme="dark"></div>

Auto theme (default)js

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>'
    });

Light themejs

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>',
        theme: 'light'
    });

Dark themejs

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>',
        theme: 'dark'
    });

Appearance modes

Control when the widget becomes visible to visitors using the appearance mode.

  • always (default): The widget is always visible from page load. This is the best option for most implementations where you want your visitors to see the widget immediately as it provides clear visual feedback that security verification is in place.
  • execute: The widget only becomes visible after the challenge begins. This is useful for when you need to control the timing of widget appearance, such as showing it only when a visitor starts filling out a form or selecting a submit button.
  • interaction-only: The widget becomes visible only when visitor interaction is required and provides the cleanest visitor experience. Most visitors will never see the widget, but suspected bots will encounter the interactive challenge.

Note

Appearance modes only affect visible widget types (Managed and Non-Interactive). Invisible widgets are never shown regardless of the appearance setting.

Always visible (default)html

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>

Visible only after challenge beginshtml

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-appearance="execute"></div>

Visible only when interaction is neededhtml

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-appearance="interaction-only"></div>

Always visible (default)js

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>'
    });

Visible only after challenge beginsjs

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>',
        appearance: 'execute'
    });

Visible only when interaction is neededjs

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>',
        appearance: 'interaction-only'
    });

Execution modes

Control when the challenge runs and a token is generated.

  • render (default): The challenge runs automatically after calling the render() function and provides immediate protection as soon as the widget loads. The challenge runs in the background while the page loads, ensuring the token is ready when the visitor submits data.
  • execute: The challenge runs after calling the turnstile.execute() function separately and gives you precise control over when verification occurs. This option is useful for multi-step forms, conditional verification, or when you want to defer the challenge until the visitor actually attempts to submit data. This can improve page load performance and visitor experience by only running verification when needed.

Common scenarios - Multi-step forms: Run verification only on the final step. - Conditional protection: Only verify visitors who meet certain criteria. - Performance optimization: Defer verification to reduce initial page load time. - User-triggered verification: Let visitors manually start the verification process.

Auto execution (default)html

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>

Manual executionhtml

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-execution="execute"></div>

Auto execution (default)js

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>'
    });

Manual executionjs

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>',
        execution: 'execute'
    });

Execute the challenge laterjs

    turnstile.execute('#widget-container');

Language configuration

Set the language for the widget interface.

  • auto (default): Uses the visitor's browser language preference.
  • Specific language codes: ISO 639-1 two-letter codes, such as es, fr, de.
  • Language and region: Combined codes for regional variants, such as en-US, es-MX, pt-BR.

Notes

  • When set to auto, Turnstile automatically detects the visitor's preferred language from their browser settings.
  • If a requested language is not supported, Turnstile falls back to English.
  • Language affects all visitor-facing text including loading messages, error states, and accessibility labels.
  • Setting specific languages can improve visitor experience for international audiences.

Auto language (default)html

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>

Specific languagehtml

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-language="es"></div>

Language and countryhtml

    <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-language="en-US"></div>

Auto language (default)js

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>'
    });

Specific languagejs

    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>',
        language: 'es'
    });

Callback configuration

Handle widget events with callbacks.

  • callback: Triggered when the challenge is successfully completed.
  • error-callback: Triggered when an error occurs during the challenge.
  • expired-callback: Triggered when a token expires (before timeout).
  • timeout-callback: Triggered when an interactive challenge times out.

The success callback receives a token that must be validated on your server using the Siteverify API. Tokens are single-use and expire after 300 seconds (five minutes).

    <div class="cf-turnstile"
        data-sitekey="<YOUR-SITE-KEY>"
        data-callback="onSuccess"
        data-error-callback="onError"
        data-expired-callback="onExpired"
        data-timeout-callback="onTimeout"></div>
    <script>
    function onSuccess(token) {
    console.log('Challenge Success:', token);
    }
    function onError(errorCode) {
    console.log('Challenge Error:', errorCode);
    }
    function onExpired() {
    console.log('Token expired');
    }
    function onTimeout() {
    console.log('Challenge timed out');
    }
    </script>
    turnstile.render('#widget-container', {
        sitekey: '<YOUR-SITE-KEY>',
        callback: function(token) {
            console.log('Challenge Success:', token);
        },
        'error-callback': function(errorCode) {
            console.log('Challenge Error:', errorCode);
        },
        'expired-callback': function() {
            console.log('Token expired');
        },
        'timeout-callback': function() {
            console.log('Challenge timed out');
        }
    });

Best practices

  • Always implement the success callback to handle the token and proceed with form submission or next steps.
  • Use error callbacks for graceful error handling and visitor feedback.
  • Monitor expired tokens to refresh challenges before they become invalid.
  • Handle timeouts to guide visitors through challenge resolution.

Advanced configuration options

Retry behavior

Control how Turnstile handles failed challenges.

  • auto (default): Automatically retries failed challenges. Auto retry provides better visitor experience by automatically recovering from temporary network issues or processing errors.
  • never: Disables automatic retry. This requires manual intervention and gives you full control over error handling in applications that need custom retry logic.
  • retry-interval: Controls the time between retry attempts (default: 8000ms) and lets you balance between quick recovery and server load.