3Captcha
DocsLoginSign up

API Documentation

Solve Cloudflare Turnstile, reCAPTCHA v2, reCAPTCHA v3 & image OCR — pay only for successful solves.

What is 3Captcha? Key concepts Quick start Async tasks Authentication Pricing Turnstile reCAPTCHA v2 reCAPTCHA v3 Image OCR Code examples

What is 3Captcha?

3Captcha is a captcha-solving API. When a website you're automating shows a captcha (a "prove you're human" challenge), you send us the captcha's details and we return a token that proves the challenge was passed. You then submit that token to the website, exactly as if a real user had solved it.

You are charged only when a solve succeeds — there is no cost for failed attempts.

Key concepts (start here if you're new)

TermWhat it means
sitekeyThe public identifier of the captcha on the target site. You find it in the site's HTML, usually in a data-sitekey attribute or the render(...) call.
siteurlThe full URL of the page where the captcha appears (e.g. https://example.com/checkout).
tokenThe string our API returns. Submit it in the site's form (the g-recaptcha-response / cf-turnstile-response field, or via its JS callback) to prove the solve.
actionreCAPTCHA v3 only — the action label registered for the key (e.g. submit, login).
base64OCR only — the captcha image encoded as a base64 string.

Quick start

  1. Get your API key — create an account, then copy the prv_… key from your dashboard.
  2. Send a solve request — POST the sitekey + siteurl, passing your key in the x-api-key header.
  3. Submit the token — the response's token goes into the captcha field on the target site.
curl -X POST http://3captcha.world/solve/turnstile \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"sitekey":"0x4AAAAAAActoBfh_En8yr3T","siteurl":"https://example.com/"}'

# Success
{"status":"success","token":"0.w0e4...","elapsed":5.2}
Tip: for reCAPTCHA v2/v3 and OCR, just change the endpoint path (e.g. /solve/recaptcha-v2) and the fields you send — everything else is the same.

Async tasks — createTask / getTaskResult

The async flow is the recommended way to solve. It never blocks your connection and survives long solves. It's just two steps:

  1. Create a task — send the captcha details, get a taskId back instantly.
  2. Poll that task — ask for the taskId every few seconds until you get success (with the token) or error.

Works for every enabled type: turnstile, recaptcha-v2, recaptcha-v3 and ocr.

Step 1 — Create a task

curl -X POST http://3captcha.world/createTask \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"type":"turnstile","sitekey":"0x4AAAAAAActoBfh_En8yr3T","siteurl":"https://example.com/"}'

# 200 OK — keep the taskId, you poll it in step 2
{"status":"success","taskId":"c60c71cdec26fae307cc73ceb8f40a92","type":"turnstile"}
FieldTypeDescription
typestringRequired — turnstile, recaptcha-v2, recaptcha-v3 or ocr.
sitekeystringRequired (except ocr) — the site's public key.
siteurlstringRequired (except ocr) — the page URL hosting the captcha.
base64stringRequired for ocr — the captcha image as base64.
actionstringOptional — reCAPTCHA v3 action label (default submit).
timeoutintOptional — solve timeout in seconds (default 45).

Step 2 — Poll for the result

curl "http://3captcha.world/getTaskResult?taskId=c60c71cdec26fae307cc73ceb8f40a92" \
  -H "x-api-key: YOUR_API_KEY"

The result is always one of three states:

{"status":"processing","taskId":"c60c71..."}                 # still solving → poll again
{"status":"success","taskId":"c60c71...","token":"0.w0e4..."}  # done → use "token"
{"status":"error","taskId":"c60c71...","detail":"..."}      # failed
Tip: poll every 3–5 seconds until you see success or error. Tasks expire after 20 minutes.

Step 3 — Use the token

Once you get success, the token is the solved captcha. Submit it to the target site exactly like a human's answer:

Full examples — create → poll → token

# Python
import requests, time
API = "http://3captcha.world"
HEAD = {"x-api-key": "YOUR_API_KEY"}

task = requests.post(API + "/createTask", headers=HEAD,
    json={"type": "turnstile", "sitekey": "0x4AAAAAAActoBfh_En8yr3T", "siteurl": "https://example.com/"}).json()
task_id = task["taskId"]

while True:
    r = requests.get(API + "/getTaskResult", params={"taskId": task_id}, headers=HEAD).json()
    if r["status"] == "success":
        print("TOKEN:", r["token"]); break
    if r["status"] == "error":
        print("FAILED:", r.get("detail")); break
    time.sleep(4)   # still processing — poll again

# Node.js
const API = "http://3captcha.world";
const HEAD = { "x-api-key": "YOUR_API_KEY" };

const task = await fetch(API + "/createTask", {
  method: "POST",
  headers: { ...HEAD, "Content-Type": "application/json" },
  body: JSON.stringify({ type: "turnstile", sitekey: "0x4AAAAAAActoBfh_En8yr3T", siteurl: "https://example.com/" }),
}).then(r => r.json());
const taskId = task.taskId;

while (true) {
  const r = await fetch(API + "/getTaskResult?taskId=" + taskId, { headers: HEAD }).then(r => r.json());
  if (r.status === "success") { console.log("TOKEN:", r.token); break; }
  if (r.status === "error") { console.log("FAILED:", r.detail); break; }
  await new Promise(res => setTimeout(res, 4000));   // still processing
}

# PHP
$api = "http://3captcha.world";
$head = ["x-api-key: YOUR_API_KEY", "Content-Type: application/json"];

$ch = curl_init($api . "/createTask");
curl_setopt($ch, CURLOPT_HTTPHEADER, $head);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["type" => "turnstile", "sitekey" => "0x4AAAAAAActoBfh_En8yr3T", "siteurl" => "https://example.com/"]));
$task = json_decode(curl_exec($ch), true);
$taskId = $task["taskId"];

do {
    sleep(4);
    $r = json_decode(file_get_contents($api . "/getTaskResult?taskId=" . $taskId, false,
        stream_context_create(["http" => ["header" => "x-api-key: YOUR_API_KEY"]])), true);
} while ($r["status"] === "processing");
echo ($r["status"] === "success") ? "TOKEN: " . $r["token"] : "FAILED: " . $r["detail"];

Authentication

Every solve request needs your API key. Send it in the x-api-key header (or api_key in the JSON body).

curl -X POST http://3captcha.world/solve/turnstile \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"sitekey":"0x4AAAAAAActoBfh_En8yr3T","siteurl":"https://example.com/"}'

Pricing

Cloudflare Turnstile
invisible / managed
$0.10
per 1,000 solves
reCAPTCHA v2
checkbox & image
$2.00
per 1,000 solves
reCAPTCHA v3
score-based token
$3.00
per 1,000 solves
hCaptcha
coming soon
$3.00
per 1,000 solves
Image OCR
high-accuracy extraction
$0.10
per 1,000 solves

All endpoints

POST/solve/turnstileSolve Cloudflare Turnstile
POST/solve/recaptcha-v2Solve reCAPTCHA v2
POST/solve/recaptcha-v3Solve reCAPTCHA v3 (returns a high-score token)
POST/solve/ocrSolve image OCR (returns the recognized text)
POST/createTaskCreate a solve task (async)
GET/getTaskResultPoll a task for its result
POST/api/auth/registerCreate an account
POST/api/auth/loginLog in
GET/api/user/overviewYour balance + stats (dashboard)

Cloudflare Turnstile

FieldTypeDescription
sitekeystringRequired — the Turnstile site key.
siteurlstringRequired — the page URL hosting the widget.
timeoutintOptional solve timeout in seconds (default 45).
curl -X POST http://3captcha.world/solve/turnstile \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"sitekey":"0x4AAAAAAActoBfh_En8yr3T","siteurl":"https://example.com/"}'

# 200 OK — submit "token" as cf-turnstile-response
{"status":"success","token":"0.w0e4...","elapsed":5.2}

reCAPTCHA v2

FieldTypeDescription
sitekeystringRequired — the reCAPTCHA v2 site key.
siteurlstringRequired — the page URL hosting the widget.
curl -X POST http://3captcha.world/solve/recaptcha-v2 \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"sitekey":"6LfyCr4rAAAAAEEBPic8UihJxtI4IeOMuPXRLebm","siteurl":"https://example.com/"}'

# 200 OK — submit "token" as g-recaptcha-response
{"status":"success","token":"03AFcWeA...","elapsed":19.4}

reCAPTCHA v3

v3 runs in the background (no image challenge) and returns a token whose score is decided by Google. Submit the token to your own verification endpoint to read the score.

FieldTypeDescription
sitekeystringRequired — the reCAPTCHA v3 site key.
siteurlstringRequired — the page URL hosting the widget.
actionstringOptional action label (default submit).
curl -X POST http://3captcha.world/solve/recaptcha-v3 \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"sitekey":"6Lcyqq8oAAAAAJE7eVJ3aZp_hnJcI6LgGdYD8lge","siteurl":"https://example.com/","action":"submit"}'

# 200 OK
{"status":"success","token":"03AGdBq26...","elapsed":33.2}

Image OCR

Our OCR engine extracts letters and numbers from any captcha image — built to handle noisy, distorted and overlapping characters with high accuracy.

FieldTypeDescription
base64stringRequired — the captcha image as a base64 string (with or without the data:image/…;base64, prefix).
curl -X POST http://3captcha.world/solve/ocr \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"base64":"/9j/4AAQSkZJRg..."}'

# 200 OK — "token" is the recognized text (letters/numbers only)
{"status":"success","token":"42ST","elapsed":22.7}

Code examples

# Python
import requests
r = requests.post("http://3captcha.world/solve/turnstile",
  headers={"x-api-key": "YOUR_API_KEY"},
  json={"sitekey":"0x4AAAAAAActoBfh_En8yr3T","siteurl":"https://example.com/"})
print(r.json())

# Node.js
const res = await fetch("http://3captcha.world/solve/turnstile", {
  method: "POST",
  headers: { "Content-Type": "application/json", "x-api-key": "YOUR_API_KEY" },
  body: JSON.stringify({ sitekey: "0x4AAAAAAActoBfh_En8yr3T", siteurl: "https://example.com/" }),
});
console.log(await res.json());

# PHP
$ch = curl_init("http://3captcha.world/solve/turnstile");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => ["Content-Type: application/json", "x-api-key: YOUR_API_KEY"],
  CURLOPT_POSTFIELDS => '{"sitekey":"0x4AAAAAAActoBfh_En8yr3T","siteurl":"https://example.com/"}',
]);
echo curl_exec($ch);