Back to skills
SKILL.md
076 Api 41b37b98
ASecurityThe Turnstile JavaScript API is available at `window.turnstile` after loading the script.
- 9 stars
- 0 votes
- 0 copies
- 0 views
- Added October 11, 2026
Works with
Security analysis
100/100npx -y skills add tools-only/X-Skills --skill 076-api_41b37b98 --agent claude-codeAre you the author of 076 Api 41b37b98?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/tools-only-076-api-41b37b98)# API Reference
## Client-Side JavaScript API
The Turnstile JavaScript API is available at `window.turnstile` after loading the script.
### `turnstile.render(container, options)`
Renders a Turnstile widget into a container element.
**Parameters:**
- `container` (string | HTMLElement): CSS selector or DOM element
- `options` (TurnstileOptions): Configuration object (see [configuration.md](configuration.md))
**Returns:** `string` - Widget ID for use with other API methods
**Example:**
```javascript
const widgetId = window.turnstile.render('#my-container', {
sitekey: 'YOUR_SITE_KEY',
callback: (token) => console.log('Success:', token),
'error-callback': (code) => console.error('Error:', code),
})
```
### `turnstile.reset(widgetId)`
Resets a widget (clears token, resets challenge state). Useful when form validation fails.
**Parameters:**
- `widgetId` (string): Widget ID from `render()`, or container element
**Returns:** `void`
**Example:**
```javascript
// Reset on form error
if (!validateForm()) {
window.turnstile.reset(widgetId)
}
```
### `turnstile.remove(widgetId)`
Removes a widget from the DOM completely.
**Parameters:**
- `widgetId` (string): Widget ID from `render()`
**Returns:** `void`
**Example:**
```javascript
// Cleanup on navigation
window.turnstile.remove(widgetId)
```
### `turnstile.getResponse(widgetId)`
Gets the current token from a widget (if challenge completed).
**Parameters:**
- `widgetId` (string): Widget ID from `render()`, or container element
**Returns:** `string | undefined` - Token string, or undefined if not ready
**Example:**
```javascript
const token = window.turnstile.getResponse(widgetId)
if (token) {
submitForm(token)
}
```
### `turnstile.isExpired(widgetId)`
Checks if a widget's token has expired (>5 minutes old).
**Parameters:**
- `widgetId` (string): Widget ID from `render()`
**Returns:** `boolean` - True if expired
**Example:**
```javascript
if (window.turnstile.isExpired(widgetId)) {
window.turnstile.reset(widgetId)
}
```
## Callback Signatures
```typescript
type TurnstileCallback = (token: string) => void
type ErrorCallback = (errorCode: string) => void
type TimeoutCallback = () => void
type ExpiredCallback = () => void
type BeforeInteractiveCallback = () => void
type AfterInteractiveCallback = () => void
type UnsupportedCallback = () => void
```
## Siteverify API (Server-Side)
**Endpoint:** `https://challenges.cloudflare.com/turnstile/v0/siteverify`
### Request
**Method:** POST
**Content-Type:** `application/json` or `application/x-www-form-urlencoded`
```typescript
interface SiteverifyRequest {
secret: string // Your secret key (never expose client-side)
response: string // Token from cf-turnstile-response
remoteip?: string // User's IP (optional but recommended)
idempotency_key?: string // Unique key for idempotent validation
}
```
**Example:**
```javascript
// Cloudflare Workers
const result = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: env.TURNSTILE_SECRET,
response: token,
remoteip: request.headers.get('CF-Connecting-IP'),
}),
})
const data = await result.json()
```
### Response
```typescript
interface SiteverifyResponse {
success: boolean // Validation result
challenge_ts?: string // ISO timestamp of challenge
hostname?: string // Hostname where widget was solved
'error-codes'?: string[] // Error codes if success=false
action?: string // Action name from widget config
cdata?: string // Custom data from widget config
}
```
**Example Success:**
```json
{
"success": true,
"challenge_ts": "2024-01-15T10:30:00Z",
"hostname": "example.com",
"action": "login",
"cdata": "user123"
}
```
**Example Failure:**
```json
{
"success": false,
"error-codes": ["timeout-or-duplicate"]
}
```
## Error Codes
| Code | Cause | Solution |
| ------------------------ | ------------------------------- | --------------------------------- |
| `missing-input-secret` | Secret key not provided | Include `secret` in request |
| `invalid-input-secret` | Secret key is wrong | Check secret key in dashboard |
| `missing-input-response` | Token not provided | Include `response` token |
| `invalid-input-response` | Token is invalid/malformed | Verify token from widget |
| `timeout-or-duplicate` | Token expired (>5min) or reused | Generate new token, validate once |
| `internal-error` | Cloudflare server error | Retry with exponential backoff |
| `bad-request` | Malformed request | Check JSON/form encoding |
## TypeScript Types
```typescript
interface TurnstileOptions {
sitekey: string
action?: string
cData?: string
callback?: (token: string) => void
'error-callback'?: (errorCode: string) => void
'expired-callback'?: () => void
'timeout-callback'?: () => void
'before-interactive-callback'?: () => void
'after-interactive-callback'?: () => void
'unsupported-callback'?: () => void
theme?: 'light' | 'dark' | 'auto'
size?: 'normal' | 'compact' | 'flexible'
tabindex?: number
'response-field'?: boolean
'response-field-name'?: string
retry?: 'auto' | 'never'
'retry-interval'?: number
language?: string
execution?: 'render' | 'execute'
appearance?: 'always' | 'execute' | 'interaction-only'
'refresh-expired'?: 'auto' | 'manual' | 'never'
}
interface Turnstile {
render(container: string | HTMLElement, options: TurnstileOptions): string
reset(widgetId: string): void
remove(widgetId: string): void
getResponse(widgetId: string): string | undefined
isExpired(widgetId: string): boolean
execute(container?: string | HTMLElement, options?: TurnstileOptions): void
}
declare global {
interface Window {
turnstile: Turnstile
onloadTurnstileCallback?: () => void
}
}
```
## Script Loading
```html
<!-- Standard -->
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<!-- Explicit render mode -->
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"></script>
<!-- With load callback -->
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback"></script>
<script>
window.onloadTurnstileCallback = () => {
window.turnstile.render('#container', { sitekey: 'YOUR_SITE_KEY' })
}
</script>
```
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.