# Turnstile Widget Configuration Reference **Complete reference for all widget configuration options** **Official Docs**: https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/widget-configurations --- ## Widget Modes ### Managed (Recommended) Functions like a Managed Challenge Page. Selects a challenge based on visitor signals. - Shows interactive checkbox only if bot is suspected - Best balance of security and UX - Use for most production deployments ### Non-Interactive Widget is displayed but visitor never needs to interact. - No checkbox required - Runs challenge in background - Use for minimal user friction ### Invisible Widget is completely hidden from visitor. - No visual presence - Challenge runs invisibly - Use for seamless UX, API protection --- ## Configuration Parameters ### Core Parameters #### `sitekey` (Required) - **Type**: `string` - **Description**: Your widget's public sitekey from Cloudflare Dashboard - **Example**: `data-sitekey="YOUR_SITE_KEY"` or `{ sitekey: 'YOUR_SITE_KEY' }` #### `action` - **Type**: `string` - **Max Length**: 32 characters - **Valid Characters**: `a-z`, `A-Z`, `0-9`, `-`, `_` - **Description**: Custom action name tracked in analytics - **Example**: `action: 'login'`, `action: 'signup'` #### `cdata` - **Type**: `string` - **Max Length**: 255 characters - **Description**: Custom data passed through to server validation - **Example**: `cdata: JSON.stringify({ userId: '123' })` --- ## Appearance ### `theme` Controls widget color scheme. - **`auto`** (default) - Matches system preference - **`light`** - Light mode - **`dark`** - Dark mode **Example**: ```html
``` ```typescript { theme: 'dark' } ``` ### `appearance` Controls when widget becomes visible. - **`always`** (default) - Visible from page load - **`execute`** - Visible only after challenge begins - **`interaction-only`** - Visible only when user interaction required **Note**: Only affects managed/non-interactive modes. Invisible widgets never show. **Example**: ```html ``` ```typescript { appearance: 'interaction-only' } ``` ### `size` Controls widget dimensions. - **`normal`** (default) - 300px × 65px - **`compact`** - 150px × 140px - **`flexible`** - 100% width, adapts to container **Example**: ```html ``` ```typescript { size: 'flexible' } ``` --- ## Execution ### `execution` Controls when challenge runs and token is generated. - **`render`** (default) - Runs automatically after rendering - **`execute`** - Runs only when `turnstile.execute()` is called **Use Cases**: - `render`: Standard forms, immediate protection - `execute`: Multi-step forms, conditional verification, performance optimization **Example**: ```typescript const widgetId = turnstile.render('#container', { sitekey: SITE_KEY, execution: 'execute', // Manual trigger }) // Later, when needed: turnstile.execute(widgetId) ``` --- ## Callbacks ### `callback` Called when challenge succeeds. **Signature**: `(token: string) => void` **Example**: ```html ``` ```typescript { callback: (token) => { console.log('Success:', token) document.getElementById('submit-btn').disabled = false } } ``` ### `error-callback` Called when challenge fails or errors occur. **Signature**: `(errorCode: string) => void` **Example**: ```typescript { 'error-callback': (error) => { console.error('Turnstile error:', error) showErrorMessage('Verification failed') } } ``` ### `expired-callback` Called when token expires (after 5 minutes). **Signature**: `() => void` **Example**: ```typescript { 'expired-callback': () => { console.warn('Token expired') turnstile.reset(widgetId) } } ``` ### `timeout-callback` Called when interactive challenge times out (user didn't interact). **Signature**: `() => void` **Example**: ```typescript { 'timeout-callback': () => { console.warn('Challenge timed out') turnstile.reset(widgetId) } } ``` --- ## Retry Behavior ### `retry` Controls automatic retry on errors. - **`auto`** (default) - Automatically retries on transient errors - **`never`** - No automatic retry, manual control via `turnstile.reset()` **Example**: ```typescript { retry: 'never', // Manual control 'error-callback': (error) => { if (shouldRetry(error)) { turnstile.reset(widgetId) } } } ``` ### `retry-interval` Milliseconds between automatic retries. - **Default**: 8000ms (8 seconds) - **Min**: 0 - **Max**: No limit **Example**: ```typescript { retry: 'auto', 'retry-interval': 5000, // 5 seconds } ``` --- ## Complete Configuration Example ### Implicit Rendering (HTML) ```html