Skip to content

Repository files navigation

Captcha Solver Python SDK

python-sdk-banner

PyPI Python Downloads Tests Coverage Typed License: MIT Ruff Checked with mypy GitHub Release JavaScript SDK

Official Python SDK for the Captcha Solver API. Solve reCAPTCHA v2/v3, Cloudflare Turnstile, GeeTest, Yandex SmartCaptcha, Tencent, and image/click captchas with a single method call -- sync or async.

Full API reference (all endpoints, error codes, captcha-type details): https://captcha-solver.com/en/docs/captcha-types

Table of Contents

Installation

pip install captcha-solver-api

Or install the latest version from GitHub:

pip install git+https://github.com/captcha-solver-api/python-sdk.git

Configuration

The client always takes the API key as an explicit argument -- it does not read environment variables on its own. Read CAPTCHA_API_KEY yourself and pass it in:

export CAPTCHA_API_KEY=your_api_key
import os
from captcha_solver_api import CaptchaClient
client = CaptchaClient(os.getenv("CAPTCHA_API_KEY"))

Or just pass the key directly, without an environment variable:

client = CaptchaClient("your_api_key")

Quick Start

Solve a reCAPTCHA v2 with a task object and one solve() call.

from captcha_solver_api import CaptchaClient
from captcha_solver_api.tasks import RecaptchaV2TaskProxyless
client = CaptchaClient("your_api_key")
task = RecaptchaV2TaskProxyless(
    websiteURL="https://example.com/login",
    websiteKey="YOUR_WEBSITE_KEY"
)
result = client.solve(task)
print(result["gRecaptchaResponse"])

Supported CAPTCHA Types

Type Proxyless With Proxy
reCAPTCHA v2 ✅ ✅
reCAPTCHA v2 Enterprise ✅ ✅
reCAPTCHA v3 ✅ ❌
Cloudflare Turnstile ✅ ✅
GeeTest v3 ✅ ✅
GeeTest v4 ✅ ✅
Image to Text ✅ ❌
Yandex SmartCaptcha ✅ ✅
Coordinates (click captcha) ✅ ❌
Tencent ✅ ✅

Client Reference

Every method below is available on both CaptchaClient (sync, requests-based) and AsyncCaptchaClient (async, httpx-based, same names, awaited). Full docstrings with the same content live in captcha_solver_api/client.py, captcha_solver_api/async_client.py, and captcha_solver_api/tasks.py -- this section mirrors them for quick reference without leaving the README.

CaptchaClient(...)

Constructor.

Parameter Type Default Description
client_key str required Your Captcha Solver API key. Raises ValidationError if empty.
base_url str https://api.captcha-solver.com API base URL. Override only for self-hosted/staging deployments.
timeout int 120 Polling window after task creation, in seconds. Overridable per call; each HTTP request has a separate 30-second timeout.
polling_interval int 10 Seconds before the first getTaskResult poll and between subsequent polls.
language_pool Optional[str] None Default worker pool ("en" or "ru") applied to every call that doesn't pass its own language_pool.

Both clients hold a reusable connection pool (requests.Session / httpx.AsyncClient) for their lifetime instead of opening one per request. Close it when you're done -- client.close() (sync) or await client.aclose() (async) -- or use either client as a context manager:

with CaptchaClient("your_api_key") as client:
    result = client.solve(task)

async with AsyncCaptchaClient("your_api_key") as client:
    result = await client.solve(task)

solve(task, language_pool=None, timeout=None)

The main entry point. Submits task, polls until it's solved, and returns the solution -- wraps create_task() + get_task_result() so you don't poll by hand.

Parameter Type Description
task task object One of the classes from captcha_solver_api.tasks (see Captcha Types).
language_pool Optional[str] Worker pool selector, "en" or "ru".
timeout Optional[int] Overrides the client's default timeout for this call only, in seconds. Useful for captcha types that reliably take longer (e.g. classic reCAPTCHA v2, GeeTest, reCAPTCHA v3 with a high minScore).

Returns the solution dict once status is "ready" -- its shape depends on the task type (see Captcha Types). Raises ApiError, CaptchaTimeoutError, or NetworkError.

create_task(task, language_pool=None)

Submits task and returns its numeric task ID without waiting for a solution. Accepts task and language_pool; it does not accept timeout. Use this instead of solve() if you need to manage polling yourself (e.g. checking on many tasks from a different process). Raises ApiError, CaptchaTimeoutError, or NetworkError.

get_task_result(task_id)

Fetches the current status of a task created with create_task(). Always returns a dict with a status key ("processing" or "ready"); when "ready", also has a solution dict. This is a single poll, not a wait -- call it repeatedly (as solve() does) until status is "ready". Raises ApiError, CaptchaTimeoutError, or NetworkError.

get_balance()

Returns the account's current balance (float) in the account's currency. Raises ApiError, CaptchaTimeoutError, or NetworkError.

Captcha Types

Each section below covers one captcha type end-to-end: task parameters, the solution shape, a runnable example, and a link to the full spec. Optional fields left unset are omitted from the request. Every code block matches a runnable file under examples/sync (and its examples/async counterpart) -- swap the placeholder websiteURL/websiteKey/etc. for values from your own target page before running. See Running the examples for details.

Types with a *Task counterpart (as opposed to *TaskProxyless) also accept proxyType / proxyAddress / proxyPort / proxyLogin / proxyPassword to solve through your own proxy instead of the service's IPs.

reCAPTCHA v2

API method description.

Use this method to solve reCAPTCHA v2 and obtain a token for the target page. Choose the proxy variant when the solving session must use your own IP address.

RecaptchaV2TaskProxyless (no proxy) / RecaptchaV2Task (with proxy).

Parameter Required Description
websiteURL yes Full URL of the page where the captcha is located.
websiteKey yes Value of the widget's data-sitekey attribute.
isInvisible no True for invisible reCAPTCHA v2.
recaptchaDataSValue no The data-s value, found on Google Search/YouTube pages.
apiDomain no Non-default domain the widget's script is served from, if any.
userAgent no User-Agent to solve with. Recommended to match the agent submitting the token.
cookies no Session cookies to use while solving, if the page requires them.

Response: gRecaptchaResponse -- submit as g-recaptcha-response.

from captcha_solver_api import CaptchaClient
from captcha_solver_api.tasks import RecaptchaV2TaskProxyless
client = CaptchaClient("your_api_key")
task = RecaptchaV2TaskProxyless(
    websiteURL="https://example.com/login",
    websiteKey="YOUR_WEBSITE_KEY"
)
result = client.solve(task)
print(result["gRecaptchaResponse"])

With proxy, use RecaptchaV2Task instead:

task = RecaptchaV2Task(
    websiteURL="https://example.com/login",
    websiteKey="YOUR_WEBSITE_KEY",
    proxyType="http",
    proxyAddress="1.2.3.4",
    proxyPort=8080,
    proxyLogin="user",
    proxyPassword="password"
)

reCAPTCHA v2 Enterprise

API method description.

Use this method to solve the Enterprise version of reCAPTCHA v2 and obtain a token for a page that uses grecaptcha.enterprise.

RecaptchaV2EnterpriseTaskProxyless / RecaptchaV2EnterpriseTask accept websiteURL, websiteKey, isInvisible, apiDomain, userAgent, and cookies, plus enterprisePayload. Use enterprisePayload={"s": "..."} for the Enterprise s value; these classes do not accept recaptchaDataSValue.

Parameter Required Description
enterprisePayload no Extra parameters passed to grecaptcha.enterprise.render on the page, e.g. {"s": "..."}.
apiDomain no Defaults to google.com.

Response: gRecaptchaResponse.

from captcha_solver_api import CaptchaClient
from captcha_solver_api.tasks import RecaptchaV2EnterpriseTaskProxyless
client = CaptchaClient("your_api_key")
task = RecaptchaV2EnterpriseTaskProxyless(
    websiteURL="https://example.com/login",
    websiteKey="YOUR_WEBSITE_KEY"
)
result = client.solve(task)
print(result["gRecaptchaResponse"])

With proxy, use RecaptchaV2EnterpriseTask (same proxy fields as reCAPTCHA v2).

reCAPTCHA v3

API method description.

Use this method to obtain a score-based reCAPTCHA v3 token for a specific site, action, and minimum score. This variant does not use a proxy.

RecaptchaV3TaskProxyless. This API supports v3 through the service's IPs; there is no corresponding task type for your own proxy.

Parameter Required Description
websiteURL yes Full URL of the page where the captcha is located.
websiteKey yes Site key for the v3 widget.
minScore yes Minimum acceptable token score to return, e.g. 0.3, 0.7, 0.9.
pageAction no The action parameter passed to grecaptcha.execute() on the page.
isEnterprise no True for reCAPTCHA v3 Enterprise.
apiDomain no Non-standard domain the widget's script is served from, if any.

Response: gRecaptchaResponse.

from captcha_solver_api import CaptchaClient
from captcha_solver_api.tasks import RecaptchaV3TaskProxyless
client = CaptchaClient("your_api_key")
task = RecaptchaV3TaskProxyless(
    websiteURL="https://example.com/login",
    websiteKey="YOUR_WEBSITE_KEY",
    minScore=0.3,
    pageAction="homepage"
)
result = client.solve(task)
print(result["gRecaptchaResponse"])

Cloudflare Turnstile

API method description.

Use this method to solve a Cloudflare Turnstile widget and obtain the token that the target page expects in cf-turnstile-response.

TurnstileTaskProxyless / TurnstileTask.

Parameter Required Description
websiteURL yes Full URL of the page where the widget is located.
websiteKey yes Value of the widget's data-sitekey attribute.
action no Value of the widget's data-action attribute, if set.
data no Custom payload from the widget's data-cdata attribute, if set.
pagedata no Value of the chlPageData parameter, needed for some Cloudflare challenge pages beyond the basic widget.
userAgent no User-Agent to solve with -- the returned token is tied to it, submit with the same one.

Response: token -- submit as cf-turnstile-response. For Cloudflare Challenge pages, the solution also includes userAgent; use that User-Agent when submitting the token. Pass action, data, and pagedata when the page provides them. The API field is spelled pagedata, all lowercase.

from captcha_solver_api import CaptchaClient
from captcha_solver_api.tasks import TurnstileTaskProxyless
client = CaptchaClient("your_api_key")
task = TurnstileTaskProxyless(
    websiteURL="https://example.com/login",
    websiteKey="YOUR_WEBSITE_KEY"
)
result = client.solve(task)
print(result["token"])

With proxy, use TurnstileTask (same proxy fields as reCAPTCHA v2).

Image to Text

API method description.

Use this method to recognize text, numbers, or simple math expressions in an image captcha. The image is sent directly and does not require a proxy.

ImageToTextTask. No proxy variant -- the image is submitted directly, no browser session involved.

Parameter Required Description
body yes The captcha image, base64-encoded (no data:image/...;base64, prefix).
phrase no True if the answer is multiple words.
case no True if the answer is case-sensitive.
numeric no 0 unspecified, 1 digits only, 2 letters only, 3 any with digits, 4 any with letters.
math no True if the image contains a math expression to evaluate.
minLength / maxLength no Expected answer length bounds.
comment no Free-text hint for the worker.
imgInstructions no Optional supplementary instruction image, base64-encoded.

Response: text -- the recognized text/answer.

from captcha_solver_api import CaptchaClient
from captcha_solver_api.tasks import ImageToTextTask
import base64
with open("examples/assets/captcha-digits.png", "rb") as f:
    image_base64 = base64.b64encode(f.read()).decode("utf-8")
client = CaptchaClient("your_api_key")
task = ImageToTextTask(
    body=image_base64,
    numeric=1,
    minLength=4,
    maxLength=6
)
result = client.solve(task)
print(result["text"])

GeeTest (v3 & v4)

API method description: v3, v4

Use this method to solve GeeTest puzzle captchas. Select version 3 or 4 and pass the values collected from the target page before creating the task.

GeeTestTaskProxyless / GeeTestTask. Set version=4 for v4 (with initParameters["captcha_id"]); v3 is the default and needs gt/challenge instead.

Parameter Required Description
websiteURL yes Full URL of the page where the widget is located.
version no 3 (default) or 4.
gt v3 only Public key of the GeeTest widget.
challenge v3 only Session-specific challenge value from the page -- must be freshly fetched for every request, it cannot be reused.
initParameters required for v4; optional for v3 Extra initialization parameters; for v4 must contain captcha_id.
geetestApiServerSubdomain no Custom GeeTest API subdomain, if the site uses one.
userAgent no User-Agent to solve with.
risk_type no Value of the risk_type parameter from the captcha-loading request, if present. Dynamic, single-use, and time-limited.

Response: v3 -- challenge, validate, seccode. v4 -- captcha_id, lot_number, pass_token, gen_time, captcha_output. Docs: v3 ↗, v4 ↗

from captcha_solver_api import CaptchaClient
from captcha_solver_api.tasks import GeeTestTaskProxyless
client = CaptchaClient("your_api_key")
task = GeeTestTaskProxyless(
    websiteURL="https://example.com/login",
    gt="f2ae6cadcf7886856696c46d84d109d1",
    challenge="12345678abc90123d45678e90123f45g6"  # dynamic -- fetch a fresh one per request
)
result = client.solve(task)
print(result["validate"])
print(result["seccode"])

challenge is session-specific and expires quickly, so it can't be hardcoded into a static example -- see examples/sync/geetest_v3.py for where the fetch belongs in the flow.

task = GeeTestTaskProxyless(
    websiteURL="https://example.com/login",
    version=4,
    initParameters={"captcha_id": "YOUR_CAPTCHA_ID"}
)
result = client.solve(task)
print(result["captcha_output"])

With proxy, use GeeTestTask (same proxy fields as reCAPTCHA v2).

Yandex SmartCaptcha

API method description.

Use this method to solve the token-based Yandex SmartCaptcha and obtain a token for the widget on the target page. Use the coordinates method for image challenges.

YandexSmartCaptchaTaskProxyless / YandexSmartCaptchaTask -- token-based challenge. For the image challenge instead, use CoordinatesTask with Coordinates is available for generic click captchas.

Parameter Required Description
websiteURL yes Full URL of the page where the widget is located.
websiteKey yes The sitekey value from the page source or captcha iframe.
userAgent no User-Agent to solve with.
cookies no Session cookies to use while solving, if the page requires them.

Proxy variant note: proxyType also accepts "https" for this captcha type only (in addition to http/socks4/socks5).

Response: token.

from captcha_solver_api import CaptchaClient
from captcha_solver_api.tasks import YandexSmartCaptchaTaskProxyless
client = CaptchaClient("your_api_key")
task = YandexSmartCaptchaTaskProxyless(
    websiteURL="https://example.com/login",
    websiteKey="YOUR_WEBSITE_KEY"
)
result = client.solve(task)
print(result["token"])

With proxy, use YandexSmartCaptchaTask (same proxy fields as reCAPTCHA v2, plus the https option above).

Coordinates (click captcha)

API method description.

Use this method to identify points that a worker should click in an image. It supports generic click captchas and the image version of Yandex SmartCaptcha.

CoordinatesTask. Used both for generic "click on X" captchas and for Yandex SmartCaptcha's image challenge. No proxy variant -- the image is submitted directly.

Parameter Required Description
body yes The captcha image, base64-encoded.
comment no (recommended) Hint for the worker, e.g. "click on the green apple".
imgInstructions no Optional instruction image, base64-encoded.
minClicks no Minimum number of clicks expected (default 1).
maxClicks no Maximum number of clicks allowed.

Response: coordinates -- a list of {"x": int, "y": int} pixel positions to click, in order.

from captcha_solver_api import CaptchaClient
from captcha_solver_api.tasks import CoordinatesTask
import base64
with open("examples/assets/fruit-click.png", "rb") as f:
    image_base64 = base64.b64encode(f.read()).decode("utf-8")
client = CaptchaClient("your_api_key")
task = CoordinatesTask(
    body=image_base64,
    comment="click on the green apple"
)
result = client.solve(task)
print(result["coordinates"])  # [{"x": 140, "y": 110}]

Tencent

API method description.

Use this method to solve Tencent Captcha and obtain the ticket and callback values required by the target page.

TencentTaskProxyless / TencentTask.

Parameter Required Description
websiteURL yes Full URL of the page where the captcha is located.
appId yes Value of the appId parameter found in the page source.
captchaScript no URL of the Tencent captcha script, if the page uses a non-default one.

Response: appid, ret, ticket, randstr -- pass all four into the page's Tencent captcha callback.

from captcha_solver_api import CaptchaClient
from captcha_solver_api.tasks import TencentTaskProxyless
client = CaptchaClient("your_api_key")
task = TencentTaskProxyless(
    websiteURL="https://example.com/register",
    appId="YOUR_APP_ID"
)
result = client.solve(task)
print(result["ticket"])

With proxy, use TencentTask (same proxy fields as reCAPTCHA v2).

Advanced Usage

Check balance

from captcha_solver_api import CaptchaClient
client = CaptchaClient("your_api_key")
balance = client.get_balance()
print(f"Balance: {balance}")

Custom timeout and polling

client = CaptchaClient(
    client_key="your_api_key",
    timeout=180,
    polling_interval=5
)

A single solve() call can also override the client's default timeout, which is handy for captcha types that reliably take longer to solve (e.g. classic reCAPTCHA v2) without changing it for every other call:

result = client.solve(task, timeout=300)

The API requires at least 5 seconds between polls. The SDK defaults to 10 seconds. solve() waits for polling_interval before its first poll and between polls. Its default 120-second polling window is independent of the API's five-minute task lifetime. A local timeout does not cancel a task or mean that the API failed to solve it. Use create_task() and keep its task_id if you need to check the same task later; calling solve() again creates a new task.

Worker language pool

Set a default language_pool once at construction instead of passing it to every call:

client = CaptchaClient(client_key="your_api_key", language_pool="en")
result = client.solve(task)  # uses the "en" pool
result = client.solve(task, language_pool="ru")  # overrides it just for this call

Async client

AsyncCaptchaClient mirrors CaptchaClient method-for-method (create_task, get_task_result, get_balance, solve, same constructor options), just awaited and built on httpx instead of requests. It keeps one httpx.AsyncClient connection pool open for its whole lifetime, so concurrent solve() calls (see below) and repeated polling share keep-alive connections instead of each opening a new one:

import asyncio
from captcha_solver_api import AsyncCaptchaClient
from captcha_solver_api.tasks import RecaptchaV2TaskProxyless

async def main():
    client = AsyncCaptchaClient("your_api_key")
    task = RecaptchaV2TaskProxyless(
        websiteURL="https://example.com/login",
        websiteKey="YOUR_WEBSITE_KEY"
    )
    result = await client.solve(task)
    print(result["gRecaptchaResponse"])

asyncio.run(main())

See examples/async for every captcha type in async form.

Solving multiple captchas in parallel

This is the main reason to reach for the async client -- run several solve() calls concurrently instead of waiting for each one in turn:

import asyncio
from captcha_solver_api import AsyncCaptchaClient
from captcha_solver_api.tasks import RecaptchaV2TaskProxyless, TurnstileTaskProxyless

async def solve_multiple():
    client = AsyncCaptchaClient("your_api_key")

    task1 = client.solve(RecaptchaV2TaskProxyless(websiteURL="https://site1.com", websiteKey="key1"))
    task2 = client.solve(TurnstileTaskProxyless(websiteURL="https://site2.com", websiteKey="key2"))

    results = await asyncio.gather(task1, task2, return_exceptions=True)
    return results

results = asyncio.run(solve_multiple())

This completes in roughly the time of the slowest single captcha, not the sum of all of them.

Error handling

from captcha_solver_api import CaptchaClient, ApiError, CaptchaTimeoutError, NetworkError, ValidationError
client = CaptchaClient("your_api_key")
try:
    result = client.solve(task)
except ValidationError as e:
    print(f"Invalid argument: {e}")
except ApiError as e:
    print(f"API error: {e.error_code} {e.error_description}")
except CaptchaTimeoutError:
    print("Task timed out")
except NetworkError as e:
    print(f"Network error: {e}")

TimeoutError is still exported as a deprecated alias of CaptchaTimeoutError. Avoid importing it by name: it shadows Python's built-in TimeoutError.

Running the examples

See the dedicated examples documentation for the full sync/async example list, setup steps, expected results, and placeholder guidance.

  • Image/click captchas (image_to_text.py, coordinates.py) run after installing the dependencies and setting a valid CAPTCHA_API_KEY -- they read sample images bundled in examples/assets, no target page needed. python-dotenv is optional: install it only if you want the scripts to load a .env file.
  • Token captchas (recaptcha_v2.py, recaptcha_v2_enterprise.py, recaptcha_v3.py, turnstile.py, yandex_smartcaptcha.py, geetest_v4.py, tencent.py) use placeholder values (https://example.com/..., YOUR_WEBSITE_KEY, YOUR_APP_ID, YOUR_CAPTCHA_ID) -- replace these with the real values from your own target page before running.
  • geetest_v3.py additionally needs challenge fetched fresh for every request -- it's single-use and expires within seconds, so it can't be hardcoded into a static example. "https://target-site.com/path/to/geetest/init" is a placeholder; replace it with a request to your own target's equivalent endpoint (or wherever it exposes gt/challenge) -- see the script for where that fetch belongs in the flow.
  • Proxy variants (*Task classes, as opposed to *TaskProxyless) use placeholder proxy credentials (1.2.3.4 / user / password) in every example file -- proxies are a paid, account-specific resource, so there's nothing public to ship here. Swap in your own proxy details to run those blocks for real.
export CAPTCHA_API_KEY=your_api_key
python examples/sync/balance.py
python examples/sync/image_to_text.py
python examples/sync/coordinates.py

Live checks with real parameters have exercised all supported task types. Individual tasks may return ERROR_CAPTCHA_UNSOLVABLE or exceed the client's polling timeout. A ready response confirms that the service returned a solution; the target website must still accept the token with the matching page and session parameters.

Requirements

  • Python 3.9 or newer.
  • Captcha Solver account with a valid API key.

API Documentation

Full API reference: https://captcha-solver.com/en/docs/captcha-types

License

This project is licensed under the MIT License. See LICENSE.md for details.

About

Official Python SDK for solving reCAPTCHA v2/v3, Cloudflare Turnstile, GeeTest v3/v4, and image captchas via the Captcha Solver API.

Topics

Resources

Code of conduct

Contributing

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages