Cloudflare Turnstile
Cloudflare Turnstile is a smart, privacy-first CAPTCHA alternative designed to verify that visitors are real humans without presenting interactive puzzle challenges.
SolverCF allows you to solve both managed and non-interactive/invisible Cloudflare Turnstile widgets automatically.
Task Object Parameters
When creating a Turnstile task via createTask, pass the following parameters in the task object:
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | Yes | Must be "TurnstileTask". |
websiteUrl |
string | Yes | The full URL of the page containing the Turnstile widget (https://...). |
websiteKey |
string | Yes | The Turnstile site key extracted from the target page (starts with 0x4). |
userAgent |
string | No | Specific browser User-Agent to solve with. If omitted, SolverCF uses a high-reputation default browser User-Agent. |
proxy |
string | No | Optional proxy in host:port or host:port:user:pass format. |
Finding the Site Key
You can find the Turnstile websiteKey by inspecting the page source or DOM:
- Look for an element with
data-sitekey:Html<div class="cf-turnstile" data-sitekey="0x4AAAAAAAB__YGWiObopXheP"></div> - Or search page scripts for calls to
turnstile.render:JavaScriptturnstile.render('#container', { sitekey: '0x4AAAAAAAB__YGWiObopXheP' });
API Workflow
Step 1: Create Task
Send a POST request to https://solvercf.com/token/extension/createTask:
{
"clientKey": "YOUR_CLIENT_KEY",
"task": {
"type": "TurnstileTask",
"websiteUrl": "https://example.com/login",
"websiteKey": "0x4AAAAAAAB__YGWiObopXheP"
}
}
Response:
{
"errorId": 0,
"taskId": "7f8b9c2a-3d4e-5f6a-7b8c-9d0e1f2a3b4c",
"status": "created"
}
Step 2: Poll Task Result
Send periodic POST requests (every 1.5s) to https://solvercf.com/token/extension/getTaskResult:
{
"clientKey": "YOUR_CLIENT_KEY",
"taskId": "7f8b9c2a-3d4e-5f6a-7b8c-9d0e1f2a3b4c"
}
When solved, status becomes "ready":
{
"errorId": 0,
"taskId": "7f8b9c2a-3d4e-5f6a-7b8c-9d0e1f2a3b4c",
"status": "ready",
"cost": 0.0009,
"solution": {
"type": "TurnstileTask",
"token": "0.4AAAAAAAB__YGWiObopXheP_abcdef123456...",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
}
}
Important: Always submit the solved
solution.tokento the target website alongside the exactsolution.userAgentreturned by SolverCF. Cloudflare validates that the token originates from the matching User-Agent.
Complete Code Examples
Below are ready-to-run code examples that submit the task, poll for the result, and return the solved token.
cURL
Step 1: Create Task
curl -X POST https://solvercf.com/token/extension/createTask \
-H "Content-Type: application/json" \
-d '{
"clientKey": "YOUR_CLIENT_KEY",
"task": {
"type": "TurnstileTask",
"websiteUrl": "https://example.com/login",
"websiteKey": "0x4AAAAAAAB__YGWiObopXheP"
}
}'
Step 2: Get Task Result
curl -X POST https://solvercf.com/token/extension/getTaskResult \
-H "Content-Type: application/json" \
-d '{
"clientKey": "YOUR_CLIENT_KEY",
"taskId": "YOUR_TASK_ID_FROM_STEP_1"
}'
Python
import time
import requests
CLIENT_KEY = "YOUR_CLIENT_KEY"
WEBSITE_URL = "https://example.com/login"
WEBSITE_KEY = "0x4AAAAAAAB__YGWiObopXheP"
def solve_turnstile(client_key: str, website_url: str, website_key: str, proxy: str = None, user_agent: str = None):
# 1. Create task
payload = {
"clientKey": client_key,
"task": {
"type": "TurnstileTask",
"websiteUrl": website_url,
"websiteKey": website_key,
}
}
if proxy:
payload["task"]["proxy"] = proxy
if user_agent:
payload["task"]["userAgent"] = user_agent
create_resp = requests.post("https://solvercf.com/token/extension/createTask", json=payload).json()
if create_resp.get("errorId") == 1:
raise Exception(f"Failed to create task: {create_resp.get('errorDescription')}")
task_id = create_resp["taskId"]
print(f"Task created: {task_id}")
# 2. Poll result
timeout = 90
start_time = time.time()
while time.time() - start_time < timeout:
time.sleep(1.5)
result_resp = requests.post("https://solvercf.com/token/extension/getTaskResult", json={
"clientKey": client_key,
"taskId": task_id
}).json()
status = result_resp.get("status")
if status == "ready":
solution = result_resp["solution"]
print("Turnstile solved successfully!")
print(f"Token: {solution['token']}")
print(f"UserAgent: {solution['userAgent']}")
return solution
if status in ("failed", "expired"):
raise Exception(f"Task ended with status: {status}")
raise TimeoutError("Solving Turnstile timed out")
if __name__ == "__main__":
result = solve_turnstile(CLIENT_KEY, WEBSITE_URL, WEBSITE_KEY)
Node.js
const CLIENT_KEY = "YOUR_CLIENT_KEY";
const WEBSITE_URL = "https://example.com/login";
const WEBSITE_KEY = "0x4AAAAAAAB__YGWiObopXheP";
async function solveTurnstile(clientKey, websiteUrl, websiteKey, options = {}) {
// 1. Create task
const createPayload = {
clientKey,
task: {
type: "TurnstileTask",
websiteUrl,
websiteKey,
...(options.proxy ? { proxy: options.proxy } : {}),
...(options.userAgent ? { userAgent: options.userAgent } : {}),
},
};
const createRes = await fetch("https://solvercf.com/token/extension/createTask", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(createPayload),
}).then((r) => r.json());
if (createRes.errorId === 1) {
throw new Error(`Failed to create task: ${createRes.errorDescription}`);
}
const taskId = createRes.taskId;
console.log(`Task created: ${taskId}`);
// 2. Poll result
const deadline = Date.now() + 90000;
while (Date.now() < deadline) {
await new Promise((resolve) => setTimeout(resolve, 1500));
const resultRes = await fetch("https://solvercf.com/token/extension/getTaskResult", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ clientKey, taskId }),
}).then((r) => r.json());
if (resultRes.status === "ready") {
console.log("Turnstile solved successfully!");
return resultRes.solution;
}
if (resultRes.status === "failed" || resultRes.status === "expired") {
throw new Error(`Task failed with status: ${resultRes.status}`);
}
}
throw new Error("Solving Turnstile timed out");
}
solveTurnstile(CLIENT_KEY, WEBSITE_URL, WEBSITE_KEY)
.then((solution) => console.log(solution))
.catch((err) => console.error(err));
C#
using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
private static readonly HttpClient HttpClient = new HttpClient();
private const string ClientKey = "YOUR_CLIENT_KEY";
private const string WebsiteUrl = "https://example.com/login";
private const string WebsiteKey = "0x4AAAAAAAB__YGWiObopXheP";
static async Task Main()
{
var solution = await SolveTurnstileAsync(ClientKey, WebsiteUrl, WebsiteKey);
Console.WriteLine($"Token: {solution.Token}");
Console.WriteLine($"UserAgent: {solution.UserAgent}");
}
public static async Task<TurnstileSolution> SolveTurnstileAsync(
string clientKey,
string websiteUrl,
string websiteKey,
string? proxy = null,
string? userAgent = null)
{
// 1. Create task
var createResponse = await HttpClient.PostAsJsonAsync("https://solvercf.com/token/extension/createTask", new
{
clientKey,
task = new
{
type = "TurnstileTask",
websiteUrl,
websiteKey,
proxy,
userAgent
}
});
var createJson = await createResponse.Content.ReadFromJsonAsync<JsonElement>();
if (createJson.TryGetProperty("errorId", out var errorId) && errorId.GetInt32() == 1)
{
throw new Exception($"Failed to create task: {createJson.GetProperty("errorDescription").GetString()}");
}
string taskId = createJson.GetProperty("taskId").GetString()!;
Console.WriteLine($"Task created: {taskId}");
// 2. Poll result
DateTime deadline = DateTime.UtcNow.AddSeconds(90);
while (DateTime.UtcNow < deadline)
{
await Task.Delay(1500);
var resultResponse = await HttpClient.PostAsJsonAsync("https://solvercf.com/token/extension/getTaskResult", new
{
clientKey,
taskId
});
var resultJson = await resultResponse.Content.ReadFromJsonAsync<JsonElement>();
string status = resultJson.GetProperty("status").GetString()!;
if (status == "ready")
{
var solutionElement = resultJson.GetProperty("solution");
return new TurnstileSolution
{
Token = solutionElement.GetProperty("token").GetString(),
UserAgent = solutionElement.GetProperty("userAgent").GetString()
};
}
if (status == "failed" || status == "expired")
{
throw new Exception($"Task ended with status: {status}");
}
}
throw new TimeoutException("Solving Turnstile timed out");
}
public class TurnstileSolution
{
public string? Token { get; set; }
public string? UserAgent { get; set; }
}
}
Using the Token After Solving (Integration Guide)
Once you retrieve solution.token, integrate it using either of these approaches:
- Direct API Submission (Headless HTTP Request): Place the token in your POST request body under the field expected by the target server (typically
cf-turnstile-responseorturnstile_token), accompanied by the matchingUser-Agentheader. - DOM Injection in Automated Browsers:JavaScript
// Set the token on the hidden input field document.querySelector('[name="cf-turnstile-response"]').value = solution.token; // Trigger site callback or submit form if (window.onTurnstileSuccess) window.onTurnstileSuccess(solution.token); document.querySelector('form').submit();
👉 For complete multi-language code examples (Python curl_cffi, Node.js, C#, Playwright, Selenium), see: Token & Cookie Integration Guide.