← Back
jamespolyakov9829

jamespolyakov9829/captcha-api

Captcha-solving API client - Cloudflare Challenge and Turnstile in one interface, with cost tracking and concurrent batch solves.

View on GitHub ↗
apiautomationcaptchacaptcha-apichallengecloudflarepythonturnstile
Stars
261
Forks
36
Watchers
261
Open issues
0
Contributors
0
Language
Python
License
MIT License
Default branch
main
Created Sep 25, 2026Updated Sep 25, 2026

Star growth

Today—
This week—
This month—

Star history will appear here once this repo has been tracked for a couple of days.

README

Clearance - captcha-solving API, $0.40 per 1,000, 451ms average

captcha-api

A dependency-free Python client and CLI for the Clearance captcha-solving API.

One interface for both Cloudflare services that block automation - the Challenge (the "Just a moment." interstitial) and the Turnstile widget. It adds the parts a production integration needs: cost tracking so you know what a batch charges before it runs, concurrent batch solves on a thread pool, and the browser identity block so your replayed token actually clears.

Get free credits   Pricing   Read the docs

  • Free credits on sign-up. No card, no trial countdown.
  • $0.40 per 1,000 for both Cloudflare services. $0.00040 a solve.
  • 451ms average Turnstile solve, 1.3s for the Challenge.
  • Failed solves are refunded in full - you pay for tokens you received.
  • Cost tracking built in. Know the bill before you run the batch.
  • No runtime dependencies. Standard library only, Python 3.8+.

Contents

  • Pricing
  • Why this exists
  • Install
  • Quickstart
  • Cost tracking
  • Concurrent batches
  • Task types
  • The response: a token and its identity
  • The polling rhythm
  • Error handling
  • CLI reference
  • FAQ

Pricing

Two services, one price. Billed per solve, with no subscription and no minimum spend.

Service task.type Price / 1,000 Per solve Avg solve
Cloudflare Turnstile AntiTurnstileTask $0.40 $0.00040 451ms
Cloudflare Challenge AntiCloudflareTask $0.40 $0.00040 1.3s

Free credits on sign-up - enough to run your first integration before you spend anything.

Unlimited plans are available for sustained volume - ask for pricing.

How that compares

Published per-1,000 rates for Cloudflare Turnstile, gathered from each provider's own pricing page:

Provider Turnstile / 1,000
Clearance $0.40
CapMonster Cloud $0.80
CapSolver $0.80 - $1.00
Anti-Captcha $1.50
CaptchaSonic $1.45
2Captcha $1.45 - $1.99

At $0.40 that is roughly a third of what the field charges, without giving up solve time.

Get free credits


Why this exists

Every captcha API gives you a token. Almost none of them tell you what it cost, and almost none of them handle a batch without you writing the concurrency yourself.

This package is built for the integration that runs at scale:

  • Know the bill first. estimate_cost(10000) tells you the charge before a single task is submitted.
  • Track spend as you go. CostTracker records every solve, refunds nothing, and summarises in one call.
  • Batch without threads. Solver.batch() fans out across a pool and records per-URL results. One bad URL never kills the run.
  • Replay correctly. Every result carries the browser identity - User-Agent, TLS handshake, HTTP/2 settings - so the token clears on the follow-up request instead of being thrown away.

Install

pip install captcha-api

Or straight from source:

git clone https://github.com/<you>/captcha-api.git
cd captcha-api
pip install .

Quickstart

Create an account to get your key - it takes about a minute and comes with free credits:

Get free credits

Then export the key from Dashboard > Settings:

export CLEARANCE_API_KEY="your_key_here"

From the command line

captcha-api challenge --url https://example.com/login
captcha-api turnstile --url https://example.com/login --sitekey 0x4AAAAAAAxxxx
captcha-api estimate --count 10000
captcha-api balance

As a library

from captcha_api import Solver

solver = Solver.from_env()

# Cloudflare Challenge - returns a cf_clearance cookie
result = solver.challenge("https://example.com/login")
print(result.token)

# Cloudflare Turnstile - returns a cf-turnstile-response token
result = solver.turnstile("https://example.com/login", sitekey="0x4AAAAAAAxxxx")
print(result.token)

# What did that cost?
print(solver.tracker.summary())

With curl

Two calls, no SDK, no browser:

curl -s https://api.clearance.sh/createTask \
  -H 'content-type: application/json' \
  -H 'x-private-key: YOUR_API_KEY' \
  -d '{"task": {"type": "AntiCloudflareTask", "websiteURL": "https://example.com/login"}}'
curl -s https://api.clearance.sh/getTaskResult \
  -H 'content-type: application/json' \
  -H 'x-private-key: YOUR_API_KEY' \
  -d '{"taskId": "YOUR_TASK_ID"}'

Cost tracking

Two objects handle the money side.

Estimate before you run

from captcha_api import estimate_cost

est = estimate_cost(10000)
print(est.total)        # 4.0
print(est.as_dict())

From the shell:

captcha-api estimate --count 10000
{ "count": 10000, "costPerSolve": 0.0004, "total": 4.0, "freeCreditsFirst": false }

Track as you go

Every Solver carries a CostTracker. Successful solves add $0.00040 each. Failed solves are refunded and add nothing.

solver = Solver.from_env()
solver.challenge("https://a.example/")
solver.challenge("https://b.example/")

print(solver.tracker.summary())
# {"solved": 2, "failed": 0, "totalCost": 0.0008, "avgCostPerSolve": 0.0004}

Batch runs feed the same tracker:

results = solver.batch(urls, task_type=TASK_CHALLENGE, workers=8)
print(solver.tracker.summary())

Concurrent batches

Solver.batch() fans out across a thread pool. One URL per call, per-URL error capture, results in input order.

from captcha_api import Solver, TASK_TURNSTILE

solver = Solver.from_env()

urls = ["https://a.example/", "https://b.example/", "https://c.example/"]
results = solver.batch(urls, task_type=TASK_TURNSTILE, sitekey="0x4AAAAAAAxxxx", workers=8)

for r in results:
    if r["ok"]:
        print(r["url"], r["token"])
    else:
        print(r["url"], "failed:", r["error"])

A failure on one URL never aborts the batch. The tracker records every attempt so summary() reflects the whole run.

From the shell:

captcha-api batch targets.txt --kind turnstile --sitekey 0x4AAAAAAAxxxx --workers 8

Task types

Service task.type Required Optional Price Avg solve
Cloudflare Challenge AntiCloudflareTask websiteURL proxy $0.40 / 1k 1.3s
Cloudflare Turnstile AntiTurnstileTask websiteURL, websiteKey proxy, metadata.action $0.40 / 1k 451ms

websiteURL must be an absolute http or https URL, at most 2,048 characters.

Two field rules that catch people out:

  • websiteKey is required for Turnstile only. The Challenge lane reads what it needs from the page itself.
  • metadata.cdata is rejected, not ignored. Sending it produces ERROR_INVALID_TASK_DATA. Leave it out.

Proxies

Every task accepts an optional proxy so the solve happens from your own exit IP:

solver = Solver(key, proxy="http://user:pass@host:port")

This package also accepts host:port:user:pass and normalises it.


The response: a token and its identity

A ready result carries:

Field Meaning
token What you submit. For the Challenge this equals cookies.cf_clearance.
user_agent The User-Agent the token was earned with.
profile_id The browser profile that solved it.
cookies Cookies to replay.
headers Headers to replay alongside them.
emulation The TLS and HTTP/2 fingerprint block.
cost What this solve charged.

The emulation block is what makes the replay work:

"emulation": {
  "alpn": ["h2", "http/1.1"],
  "curves_list": "X25519MLKEM768:X25519:P-256:P-384",
  "key_shares": ["X25519MLKEM768", "X25519"],
  "min_tls_version": "1.2",
  "max_tls_version": "1.3",
  "permute_extensions": true,
  "http2": {
    "settings_order": [1, 2, 4, 6],
    "headers_pseudo_order": ["m", "a", "s", "p"]
  }
}

Send the follow-up request with all of it:

result = solver.challenge(url)

final = get(
    url,
    headers={**result.headers, "User-Agent": result.user_agent},
    cookies=result.cookies,
    # ... and a TLS/HTTP2 stack configured from result.emulation
)

result.identity returns the three pieces together. A client that replays the cookie with a default HTTP library presents a different handshake, and the clearance is thrown away.


The polling rhythm

Everything is asynchronous. /createTask returns an id immediately; /getTaskResult returns the solution once a node has produced it.

  • Sleep about 500ms after creating the task.
  • Then poll every 200-300ms.
  • A result lives for five minutes, and reading it does not consume it. A retry after a dropped connection is free.
  • After five minutes the id returns ERROR_TASKID_INVALID.

The Solver does all of this for you:

result = solver.poll(task_id)

Error handling

Seven codes cover everything the API can refuse or fail to do. Three are worth retrying, four are not.

Protocol errors arrive as HTTP 200 with errorId: 1. Branch on the body, check errorId, then switch on errorCode.

errorCode HTTP Retry? Meaning
ERROR_KEY_DOES_NOT_EXIST 401 no The key is wrong or missing.
ERROR_INVALID_TASK_DATA 200 no A required field is missing or rejected.
ERROR_TASK_NOT_SUPPORTED 200 no Unknown task.type, or the service is disabled.
ERROR_TASKID_INVALID 200 no No such id, or it is older than five minutes.
ERROR_CAPTCHA_UNSOLVABLE 200 yes Attempted and failed. Refunded.
ERROR_SERVICE_UNAVAILABLE 200 yes Did not answer in time, or maintenance.
ERROR_NO_SLOT_AVAILABLE 503 yes No capacity. Nothing charged. Honour Retry-After.
from captcha_api import ApiError

try:
    result = solver.challenge(url)
except ApiError as exc:
    if exc.code == "ERROR_KEY_DOES_NOT_EXIST":
        ...                       # fix the key
    elif exc.retryable:
        ...                       # back off and try again
    else:
        raise

Solver applies exponential backoff to retryable codes and prefers Retry-After when the server sends one.


CLI reference

captcha-api challenge --url URL
captcha-api turnstile --url URL [--sitekey KEY] [--action NAME]
captcha-api extract   --page URL
captcha-api estimate  --count N
captcha-api balance
captcha-api batch     FILE [--kind turnstile|challenge] [--sitekey KEY] [--workers N]

Global flags: --api-key, --proxy, --timeout, --retries, --quiet, --verbose, --version.

Exit codes: 0 success, 1 solve failed, 2 usage or credential problem.


FAQ

How much does a solve cost? $0.40 per 1,000 - $0.00040 each - for both services. Failed solves are refunded.

How fast is a solve? Turnstile averages 451ms, Challenge about 1.3s. Live figures on clearance.sh/status.

Do I need a browser? No. Two REST calls, no SDK.

How do I know what a batch will cost? captcha-api estimate --count N or estimate_cost(n).total before you run it. solver.tracker.summary() after.

Can I run solves concurrently? Yes - Solver.batch() uses a thread pool. Set --workers on the CLI or workers= in Python.

Why did my token fail even though the solve succeeded? Almost always the identity. Replay result.headers, result.user_agent and a stack configured from result.emulation.

Is there a public status page? Yes - clearance.sh/status, no key needed, refreshes every 30 seconds.


Start solving

Free credits on sign-up, no card required.

Get free credits   Pricing   Read the docs   Live status


Captchas in 451ms. Priced before you run.
Cloudflare Turnstile & Challenge at $0.40 per 1,000 - cost tracking, concurrent batches, failed solves refunded.

451ms avg  ·  $0.40 / 1K  ·  Free credits  ·  Failures refunded

Get free credits

License

MIT - see LICENSE.

See CHANGELOG.md for release history, CONTRIBUTING.md for the ground rules, and SECURITY.md for private vulnerability reporting.

This is an unofficial client. Clearance is a separate service; see clearance.sh for terms.