Cloudflare Turnstile

After solving the CAPTCHA, you receive a token that must be inserted into a designated field on the page. All Turnstile subtypes are automatically supported: manual, non-interactive, and invisible. Therefore, you do not need to specify a subtype for a standard captcha.
Request parameters
You are required to solve a regular Turnstile captcha, like this one. Please note that captchas on Cloudflare pages may look identical. See how to distinguish a regular Turnstile from a Cloudflare Challenge.
-
CapMonster Cloud uses built-in proxies by default — their cost is already included in the service. You only need to specify your own proxies in cases where the website does not accept the token or access to the built-in services is restricted.
-
If you are using a proxy with IP authorization, make sure to whitelist the address 65.21.190.34.
-
After solving, you will receive a token to confirm captcha completion.
type<string>requiredTurnstileTask
websiteURL<string>requiredThe URL of the page where the captcha is solved
websiteKey<string>requiredTurnstile site key
pageAction<string>optionalThe action field found in the callback function when the captcha is loaded
data<string>optionalThe value of the data field, taken from the cData parameter.
proxyType<string>optionalhttp - standard http/https proxy;
https - try this if "http" doesn't work (needed for some custom proxies);
socks4 - socks4 proxy;
socks5 - socks5 proxy.
proxyAddress<string>optionalIP address of the proxy (IPv4/IPv6). Not allowed:
- using transparent proxies (those exposing the client IP);
- using local machine proxies.
proxyPort<integer>optionalProxy port.
proxyLogin<string>optionalProxy login.
proxyPassword<string>optionalProxy password.
Create task method
- TurnstileTask (without proxy)
- TurnstileTask (with proxy)
https://api.capmonster.cloud/createTask
Request
{
"clientKey": "API_KEY",
"task": {
"type": "TurnstileTask",
"websiteURL": "http://tsmanaged.zlsupport.com",
"websiteKey": "0x4AAAAAAABUYP0XeMJF0xoy"
}
}
Response
{
"errorId": 0,
"taskId": 407533072
}
https://api.capmonster.cloud/createTask
Request
{
"clientKey": "API_KEY",
"task": {
"type": "TurnstileTask",
"websiteURL": "http://tsmanaged.zlsupport.com",
"websiteKey": "0x4AAAAAAABUYP0XeMJF0xoy",
"proxyType": "http",
"proxyAddress": "8.8.8.8",
"proxyPort": 8080,
"proxyLogin": "proxyLoginHere",
"proxyPassword": "proxyPasswordHere"
}
}
Response
{
"errorId": 0,
"taskId": 407533072
}
Get task result method
Use the getTaskResult method to retrieve the Turnstile solution. Depending on system load, the response can take between 5 and 20 seconds.
https://api.capmonster.cloud/getTaskResult
Request
{
"clientKey": "API_KEY",
"taskId": 407533072
}
Response
{
"errorId": 0,
"status": "ready",
"solution": {
"userAgent": "userAgentPlaceholder",
"token": "0.iGX3xsyFCkbGePM3jP4P4khLo6TrLukt8ZzBvwuQOvbC...f61f3082"
}
}
| Property | Type | Description |
|---|---|---|
| token | String | Use the token in an input field or when calling a callback function |
How to differentiate Cloudflare Turnstile from Cloudflare Challenge
Differences between Turnstile and Challenge
Cloudflare verification types can appear in different ways.
Standard Turnstile:

Stylized variants:
To confirm Challenge presence, open developer tools, inspect network traffic, and check the page source for typical signs:
- The first request to the site returns a 403 status code:

- The form with id challenge-form has an action attribute (not to be confused with Turnstile captcha action) containing the parameter
__cf_chl_f_tk=:

- The page contains two similar
<script>tags that create new values in thewindowobject:

How to find all required parameters for task creation
Manually
- Open your website where the captcha appears in the browser.
- Right-click on the captcha element and select Inspect.
websiteKey
Can be found in Elements:


pageAction
Action and sitekey can also be found in the callback function:

Automatically
To automate parameter extraction, you can retrieve them via a browser (regular or headless, e.g., using Playwright) or directly from HTTP requests. Since dynamic parameter values are short-lived, it is recommended to use them immediately after retrieval.
The provided code snippets are basic examples for learning how to extract the required parameters. The exact implementation will depend on your captcha page, its structure, and the HTML elements and selectors used.
- JavaScript
- Python
- C#
Show code (for browser)
// Function to check for the presence of window.onloadTurnstileCallback
const checkTurnstileCallback = () => {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => reject('Callback timeout'), 30000);
const interval = setInterval(() => {
if (window.onloadTurnstileCallback !== undefined) {
clearInterval(interval);
clearTimeout(timeout);
const callbackDetails = window.onloadTurnstileCallback.toString();
const sitekeyMatch = callbackDetails.match(/sitekey: ['"]([^'"]+)['"]/);
const actionMatch = callbackDetails.match(/action: ['"]([^'"]+)['"]/);
resolve({
sitekey: sitekeyMatch ? sitekeyMatch[1] : null,
action: actionMatch ? actionMatch[1] : null,
});
}
}, 500);
});
};
// Try to find any element with data-sitekey
const turnstileElement = document.querySelector('[data-sitekey]');
if (turnstileElement) {
// Extract the data-sitekey attribute value
const sitekey = turnstileElement.getAttribute("data-sitekey");
console.log("Turnstile Sitekey (from element):", sitekey);
} else {
console.log("Turnstile element not found. Checking via callback...");
// If the element is not found, check via window.onloadTurnstileCallback
checkTurnstileCallback()
.then((data) => {
console.log("Turnstile Params (from callback):", data);
})
.catch((error) => {
console.error(error);
});
}
Show code
import asyncio
from playwright.async_api import async_playwright
async def run():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
context = await browser.new_context()
page = await context.new_page()
await page.goto("https://example.com") # Replace with your website
# Try to find an element with data-sitekey
element = await page.query_selector('[data-sitekey]')
if element:
sitekey = await element.get_attribute("data-sitekey")
print("Turnstile Sitekey (from element):", sitekey)
else:
print("Turnstile element not found. Checking via callback...")
try:
result = await page.evaluate('''() => {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => reject('Callback timeout'), 30000);
const interval = setInterval(() => {
if (window.onloadTurnstileCallback !== undefined) {
clearInterval(interval);
clearTimeout(timeout);
const cbStr = window.onloadTurnstileCallback.toString();
const sitekeyMatch = cbStr.match(/sitekey: ['"]([^'"]+)['"]/);
const actionMatch = cbStr.match(/action: ['"]([^'"]+)['"]/);
resolve({
sitekey: sitekeyMatch ? sitekeyMatch[1] : null,
action: actionMatch ? actionMatch[1] : null,
});
}
}, 500);
});
}''')
print("Turnstile Params (from callback):", result)
except Exception as e:
print("Error:", e)
await browser.close()
asyncio.run(run())
Show code
using System;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Playwright;
class Program
{
public static async Task Main()
{
using var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
{
Headless = false
});
var context = await browser.NewContextAsync();
var page = await context.NewPageAsync();
await page.GotoAsync("https://example.com"); // Replace with the target URL
var element = await page.QuerySelectorAsync("[data-sitekey]");
if (element != null)
{
var sitekey = await element.GetAttributeAsync("data-sitekey");
Console.WriteLine($"Turnstile Sitekey (from element): {sitekey}");
}
else
{
Console.WriteLine("Turnstile element not found. Checking via callback...");
try
{
var result = await page.EvaluateAsync(@"() => {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => reject('Callback timeout'), 30000);
const interval = setInterval(() => {
if (window.onloadTurnstileCallback !== undefined) {
clearInterval(interval);
clearTimeout(timeout);
const cbStr = window.onloadTurnstileCallback.toString();
const sitekeyMatch = cbStr.match(/sitekey: ['""]([^'""]+)['""]/);
const actionMatch = cbStr.match(/action: ['""]([^'""]+)['""]/);
resolve({
sitekey: sitekeyMatch ? sitekeyMatch[1] : null,
action: actionMatch ? actionMatch[1] : null
});
}
}, 500);
});
}");
Console.WriteLine("Turnstile Params (from callback): " + result?.ToString());
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
await browser.CloseAsync();
}
}
Use the SDK Library
- JavaScript
- Python
- C#
Show code (for browser)
// https://github.com/ZennoLab/capmonstercloud-client-js
import {
CapMonsterCloudClientFactory,
ClientOptions,
TurnstileRequest
} from '@zennolab_com/capmonstercloud-client';
const API_KEY = "YOUR_API_KEY"; // Specify your CapMonster Cloud API key
document.addEventListener("DOMContentLoaded", async () => {
const client = CapMonsterCloudClientFactory.Create(
new ClientOptions({ clientKey: API_KEY })
);
// Basic example without proxy
// CapMonster Cloud automatically uses its own proxies
let turnstileRequest = new TurnstileRequest({
websiteURL: "http://tsmanaged.zlsupport.com", // URL of the page with the captcha
websiteKey: "0x4AAAAAAABUYP0XeMJF0xoy" // Replace with the correct value
});
// Example of using your own proxy
// Uncomment this block if you want to use your own proxy
/*
const proxy = {
proxyType: "https",
proxyAddress: "123.45.67.89",
proxyPort: 8080,
proxyLogin: "username",
proxyPassword: "password"
};
turnstileRequest = new TurnstileRequest({
websiteURL: "http://tsmanaged.zlsupport.com",
websiteKey: "0x4AAAAAAABUYP0XeMJF0xoy",
proxy,
userAgent: "userAgentPlaceholder"
});
*/
// Optionally, you can check the balance
const balance = await client.getBalance();
console.log("Balance:", balance);
const result = await client.Solve(turnstileRequest);
console.log("Solution:", result);
});
Show code (Node.js)
// https://github.com/ZennoLab/capmonstercloud-client-js
import { CapMonsterCloudClientFactory, ClientOptions, TurnstileRequest } from '@zennolab_com/capmonstercloud-client';
const API_KEY = "YOUR_API_KEY"; // Specify your CapMonster Cloud API key
async function solveTurnstile() {
const client = CapMonsterCloudClientFactory.Create(
new ClientOptions({ clientKey: API_KEY })
);
// Basic example without proxy
// CapMonster Cloud automatically uses its own proxies
let turnstileRequest = new TurnstileRequest({
websiteURL: "http://tsmanaged.zlsupport.com", // URL of the page with the captcha
websiteKey: "0x4AAAAAAABUYP0XeMJF0xoy" // Replace with the correct value
});
// Example of using your own proxy
// Uncomment this block if you want to use your own proxy
/*
const proxy = {
proxyType: "https",
proxyAddress: "123.45.67.89",
proxyPort: 8080,
proxyLogin: "username",
proxyPassword: "password"
};
turnstileRequest = new TurnstileRequest({
websiteURL: "http://tsmanaged.zlsupport.com",
websiteKey: "0x4AAAAAAABUYP0XeMJF0xoy",
proxy,
userAgent: "userAgentPlaceholder"
});
*/
// Optionally, you can check the balance
const balance = await client.getBalance();
console.log("Balance:", balance);
const result = await client.Solve(turnstileRequest);
console.log("Solution:", result);
}
solveTurnstile().catch(err => console.error("Error:", err));
Show code
# https://github.com/ZennoLab/capmonstercloud-client-python
import asyncio
from capmonstercloudclient import CapMonsterClient, ClientOptions
from capmonstercloudclient.requests import TurnstileRequest
# from capmonstercloudclient.requests.baseRequestWithProxy import ProxyInfo # Uncomment if you plan to use a proxy
API_KEY = "YOUR_API_KEY" # Specify your CapMonster Cloud API key
async def solve_turnstile_token():
client_options = ClientOptions(api_key=API_KEY)
cap_monster_client = CapMonsterClient(options=client_options)
# Basic example without proxy
# CapMonster Cloud automatically uses its own proxies
turnstile_request = TurnstileRequest(
websiteURL="http://tsmanaged.zlsupport.com",
websiteKey="0x4AAAAAAABUYP0XeMJF0xoy",
)
# Example of using your own proxy
# Uncomment this block if you want to use your own proxy
#
# proxy = ProxyInfo(
# proxyType="http",
# proxyAddress="123.45.67.89",
# proxyPort=8080,
# proxyLogin="username",
# proxyPassword="password"
# )
#
# turnstile_request = TurnstileRequest(
# websiteURL="http://tsmanaged.zlsupport.com",
# websiteKey="0x4AAAAAAABUYP0XeMJF0xoy",
# proxy=proxy
# )
# Optionally, you can check the balance
balance = await cap_monster_client.get_balance()
print("Balance:", balance)
result = await cap_monster_client.solve_captcha(turnstile_request)
print("Solution:", result)
asyncio.run(solve_turnstile_token())
Show code
// https://github.com/ZennoLab/capmonstercloud-client-dotnet
using System;
using System.Threading.Tasks;
using Zennolab.CapMonsterCloud;
using Zennolab.CapMonsterCloud.Requests;
class Program
{
static async Task Main(string[] args)
{
// Your CapMonster Cloud API key
var clientOptions = new ClientOptions
{
ClientKey = "YOUR_API_KEY"
};
var cmCloudClient = CapMonsterCloudClientFactory.Create(clientOptions);
// Basic example without proxy
// CapMonster Cloud automatically uses its own proxies
var turnstileRequest = new TurnstileRequest
{
WebsiteUrl = "http://tsmanaged.zlsupport.com", // URL of the page with the captcha
WebsiteKey = "0x4AAAAAAABUYP0XeMJF0xoy" // Replace with the correct value
};
// Example of using your own proxy
// Uncomment this block if you want to use your own proxy
/*
var turnstileRequest = new TurnstileRequest
{
WebsiteUrl = "http://tsmanaged.zlsupport.com",
WebsiteKey = "0x4AAAAAAABUYP0XeMJF0xoy",
Proxy = new ProxyContainer(
"123.45.67.89",
8080,
ProxyType.Http,
"username",
"password"
)
};
*/
// Optionally, you can check the balance
var balance = await cmCloudClient.GetBalanceAsync();
Console.WriteLine("Balance: " + balance);
var turnstileResult = await cmCloudClient.SolveAsync(turnstileRequest);
Console.WriteLine("Solution: " + turnstileResult.Solution.Value);
}
}
