Skip to main content
The Turnstile API allows you to manage challenge widgets that provide bot protection without the frustration of traditional CAPTCHAs. Turnstile uses machine learning to validate users with minimal friction.

Initialize the Turnstile resource

import Cloudflare from 'cloudflare';

const client = new Cloudflare({
  apiToken: process.env.CLOUDFLARE_API_TOKEN,
});

const turnstile = client.turnstile;

Widget management

Manage Turnstile widgets for your applications.

Create widget

Create a new Turnstile widget for bot protection.
const widget = await client.turnstile.widgets.create({
  account_id: '023e105f4ecef8ad9ca31a8372d0c353',
  domains: [
    'cloudflare.com',
    'blog.example.com',
    '203.0.113.1',
  ],
  mode: 'invisible',
  name: 'blog.cloudflare.com login form',
});
account_id
string
required
Account identifier
domains
string[]
required
List of domains where the widget will work. Accepts hostnames or IPv4/IPv6 addresses. The widget will work on these domains and their subdomains.
mode
string
required
Widget mode. Options:
  • non-interactive - No user interaction required
  • invisible - Invisible challenge, minimal user interaction
  • managed - Adaptive challenge based on risk
name
string
required
Human readable widget name. This should be a meaningful string to identify your widget and where it is used.
bot_fight_mode
boolean
When set to true, Cloudflare issues computationally expensive challenges in response to malicious bots (Enterprise only).
clearance_level
string
If Turnstile is embedded on a Cloudflare site, this determines the challenge clearance level. Options: no_clearance, jschallenge, managed, interactive
ephemeral_id
boolean
Return the Ephemeral ID in /siteverify (Enterprise only).
offlabel
boolean
Do not show any Cloudflare branding on the widget (Enterprise only).
region
string
Region where this widget can be used. Options: world, china. This cannot be changed after creation.

Update widget

Update the configuration of an existing widget.
const widget = await client.turnstile.widgets.update(
  '0x4AAF00AAAABn0R22HWm-YUc',
  {
    account_id: '023e105f4ecef8ad9ca31a8372d0c353',
    domains: ['cloudflare.com', 'blog.example.com'],
    mode: 'managed',
    name: 'Updated widget name',
  }
);

List widgets

List all Turnstile widgets in your account.
// Automatically fetches more pages as needed
for await (const widget of client.turnstile.widgets.list({
  account_id: '023e105f4ecef8ad9ca31a8372d0c353',
})) {
  console.log(widget.name, widget.sitekey);
}
direction
string
Direction to order widgets. Options: asc, desc
order
string
Field to order widgets by. Options: id, sitekey, name, created_on, modified_on
page
number
Page number of paginated results
per_page
number
Number of items per page

Get widget

Retrieve a single widget configuration by sitekey.
const widget = await client.turnstile.widgets.get(
  '0x4AAF00AAAABn0R22HWm-YUc',
  { account_id: '023e105f4ecef8ad9ca31a8372d0c353' }
);

Delete widget

Delete a Turnstile widget.
const widget = await client.turnstile.widgets.delete(
  '0x4AAF00AAAABn0R22HWm-YUc',
  { account_id: '023e105f4ecef8ad9ca31a8372d0c353' }
);

Rotate secret

Generate a new secret key for a widget.
const widget = await client.turnstile.widgets.rotateSecret(
  '0x4AAF00AAAABn0R22HWm-YUc',
  {
    account_id: '023e105f4ecef8ad9ca31a8372d0c353',
    invalidate_immediately: false,
  }
);
invalidate_immediately
boolean
If set to false, the previous secret will remain valid for two hours. Otherwise, the secret is immediately invalidated and requests using it will be rejected.
By default, the previous secret remains valid for 2 hours during rotation, allowing for a graceful transition. Note that secrets cannot be rotated again during this grace period.

Response types

Widget

A Turnstile widget configuration.
sitekey
string
required
Widget item identifier tag
secret
string
required
Secret key for this widget (only returned on creation and rotation)
name
string
required
Human readable widget name
domains
string[]
required
List of domains where the widget will work
mode
string
required
Widget mode: non-interactive, invisible, or managed
bot_fight_mode
boolean
required
Whether bot fight mode is enabled
clearance_level
string
required
Challenge clearance level
ephemeral_id
boolean
required
Whether ephemeral ID is enabled
offlabel
boolean
required
Whether Cloudflare branding is hidden
region
string
required
Region where widget can be used: world or china
created_on
string
required
When the widget was created
modified_on
string
required
When the widget was last modified

Build docs developers (and LLMs) love