Solver Cloudflare

Getting Started

This guide walks you through everything needed to go from zero to a solved captcha token: creating an account, funding it, and making your first request.

Prerequisites

  • A SolverCF account (free to create, no credit card required).
  • A little balance on that account — every solved task has a small cost, see Task Types & Pricing.
  • The site key and target URL of the page you need to solve. For Cloudflare Turnstile this is usually visible in the page's HTML as data-sitekey on the widget <div>; for reCAPTCHA v3 it's the key passed to grecaptcha.execute(...).

1. Create an account

Register for a SolverCF account.

2. Get your Client Key

Every request is authenticated with a clientKey — this is your account's API key, found on your Dashboard. See Authentication for how it's used and how to keep it safe.

3. Add balance

Top up your balance from Dashboard → Deposit (PayPal or crypto). Each solved task deducts its cost from your balance when the result is delivered — a task that's created but never solved doesn't charge you.

4. Make your first request

The basic flow is always the same two calls: create a task, then poll for its result.

cURL
# 1. Create a 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",
      "websiteKey": "0x4AAAAAAAf4mfyVrG728T40"
    }
  }'

# => { "taskId": "…", "status": "idle", "errorId": 0 }

# 2. Poll for the result (repeat every 1-2s until status is "ready")
curl -X POST https://solvercf.com/token/extension/getTaskResult \
  -H "Content-Type: application/json" \
  -d '{ "clientKey": "YOUR_CLIENT_KEY", "taskId": "TASK_ID_FROM_STEP_1" }'

# => { "status": "ready", "solution": { "token": "…", "userAgent": "…" }, "errorId": 0 }

Full example with polling

Copy-pasteable end-to-end examples that create a task and poll until it's solved. For cURL, see the plain create/poll calls in step 4 above — a shell loop isn't a single request you can drop into Postman, so it's not repeated here as a "language" example.

Example: Python

Python
import time
import requests

CLIENT_KEY = "YOUR_CLIENT_KEY"
BASE_URL = "https://solvercf.com"

def solve_turnstile(website_url, website_key):
    create = requests.post(f"{BASE_URL}/token/extension/createTask", json={
        "clientKey": CLIENT_KEY,
        "task": {"type": "TurnstileTask", "websiteUrl": website_url, "websiteKey": website_key},
    }).json()

    if create["errorId"] != 0:
        raise Exception(create.get("errorDescription", "createTask failed"))

    task_id = create["taskId"]

    for _ in range(40):  # ~60s budget, task expires after 1 minute if unclaimed
        time.sleep(1.5)
        result = requests.post(f"{BASE_URL}/token/extension/getTaskResult", json={
            "clientKey": CLIENT_KEY,
            "taskId": task_id,
        }).json()

        if result["status"] in ("ready", "success"):
            return result["solution"]["token"], result["solution"]["userAgent"]
        if result["status"] in ("failed", "expired"):
            raise Exception(f"task {result['status']}")

    raise TimeoutError("task did not finish in time")

token, user_agent = solve_turnstile("https://example.com", "0x4AAAAAAAf4mfyVrG728T40")
print(token)

Example: JavaScript

JavaScript
const CLIENT_KEY = "YOUR_CLIENT_KEY";
const BASE_URL = "https://solvercf.com";

async function solveTurnstile(websiteUrl, websiteKey) {
  const create = await fetch(`${BASE_URL}/token/extension/createTask`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      clientKey: CLIENT_KEY,
      task: { type: "TurnstileTask", websiteUrl, websiteKey },
    }),
  }).then((r) => r.json());

  if (create.errorId !== 0) throw new Error(create.errorDescription ?? "createTask failed");

  const taskId = create.taskId;

  for (let i = 0; i < 40; i++) {
    await new Promise((r) => setTimeout(r, 1500));

    const result = await fetch(`${BASE_URL}/token/extension/getTaskResult`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ clientKey: CLIENT_KEY, taskId }),
    }).then((r) => r.json());

    if (["ready", "success"].includes(result.status)) {
      return { token: result.solution.token, userAgent: result.solution.userAgent };
    }
    if (["failed", "expired"].includes(result.status)) {
      throw new Error(`task ${result.status}`);
    }
  }

  throw new Error("task did not finish in time");
}

Example: C#

C#
using System.Net.Http.Json;
using System.Text.Json;

const string clientKey = "YOUR_CLIENT_KEY";
const string baseUrl = "https://solvercf.com";
using var client = new HttpClient();

async Task<JsonElement> SolveTurnstileAsync(string websiteUrl, string websiteKey)
{
    var create = await client.PostAsJsonAsync($"{baseUrl}/token/extension/createTask", new
    {
        clientKey,
        task = new { type = "TurnstileTask", websiteUrl, websiteKey },
    });
    var createJson = await create.Content.ReadFromJsonAsync<JsonElement>();
    var taskId = createJson.GetProperty("taskId").GetString();

    for (var i = 0; i < 40; i++)
    {
        await Task.Delay(1500);

        var result = await client.PostAsJsonAsync($"{baseUrl}/token/extension/getTaskResult", new { clientKey, taskId });
        var resultJson = await result.Content.ReadFromJsonAsync<JsonElement>();
        var status = resultJson.GetProperty("status").GetString();

        if (status is "ready" or "success") return resultJson.GetProperty("solution");
        if (status is "failed" or "expired") throw new Exception($"task {status}");
    }

    throw new TimeoutException("task did not finish in time");
}

Troubleshooting your first request

Symptom Likely cause
errorId: 1, ERROR_KEY_DOES_NOT_EXIST clientKey is wrong or has a typo — copy it fresh from the Dashboard
errorId: 1, "balance not enough" Top up from Dashboard → Deposit
errorId: 1, "Supported [...]" task.type doesn't match one of the values listed in the error — check spelling/casing
Polling never reaches ready Confirm websiteUrl/websiteKey are correct for the page; check status for failed/expired

Next: Create Task for the full request schema of every task type.