Official Python client for the CaptchaAI captcha-solving API.
Project description
CaptchaAI Python SDK
Python client for the CaptchaAI captcha-solving API.
Call one method per captcha type; the SDK handles HTTP, polling, retries, and error mapping.
For full copy-paste examples of every captcha type and SDK feature, see examples.md.
Table of Contents
- Examples
- Installation
- Configuration
- Solve result
- Normal captcha
- Grid captcha
- BLS captcha
- reCAPTCHA v2
- reCAPTCHA v3
- Cloudflare Turnstile
- Cloudflare Challenge
- GeeTest
- CaptchaFox
- Friendly Captcha
- Lemin
- Other methods
- Error handling
- Proxies
- Async usage
- License
Installation
pip install captchaai
Configuration
Create a sync client with your API key. The constructor validates the key and reads the account thread cap via a startup threadsinfo call.
from captchaai import CaptchaAI
solver = CaptchaAI(
api_key="YOUR_32_CHAR_API_KEY",
proxy="user:pass@host:port", # optional
proxytype="HTTP", # required when proxy is set
auto_retry=True,
base_url="https://ocr.captchaai.com",
thread_busy_timeout=120.0,
max_retries=None, # optional; overrides auto_retry when set
)
| Option | Default | Description |
|---|---|---|
api_key |
(required) | 32-character CaptchaAI API key |
proxy |
None |
"user:pass@host:port" applied to every solve |
proxytype |
None |
HTTP / HTTPS / SOCKS4 / SOCKS5 — required when proxy is set |
auto_retry |
True |
True = SDK retries transient errors with backoff; False = raise immediately |
base_url |
https://ocr.captchaai.com |
API host for in.php / res.php |
thread_busy_timeout |
120.0 |
Seconds to keep retrying while all account threads are busy |
max_retries |
None |
When set: 0 disables retries; N > 0 enables up to N submit attempts (supersedes auto_retry) |
A bad key raises InvalidKeyError before any solve runs. Call solver.close() when finished to release the HTTP client.
Solve result
Every solve method returns a SolveResult:
result.task_id # str — task ID from submit (always present)
result.solution # str | list | dict — token, cell indices, or structured answer
result.user_agent # str | None — set for Enterprise / Cloudflare Challenge / CaptchaFox
result.raw # dict | None — full API response (debugging)
result.raw_text # str | None — unparsed solution string before JSON parsing
str(result) # token string for common token types
Reuse result.user_agent on the target site when it is present (Enterprise, Cloudflare Challenge, CaptchaFox).
Normal captcha
Solve a text/image captcha. image may be a file path, URL, data-URI, raw base64, or bytes.
from captchaai import CaptchaAI
solver = CaptchaAI(api_key="YOUR_32_CHAR_API_KEY")
result = solver.normal(
"captcha.png",
numeric=1, # 0=any, 1=digits, 2=letters, 3=digits+letters, 4=no digits
min_len=4,
max_len=6,
phrase=0, # 0=single word, 1=multi-word
case_sensitive=0, # 0=insensitive, 1=case-sensitive
lang="en",
instructions="Type the characters you see",
)
print(result.solution)
Grid captcha
Solve a tile-selection captcha. grid_size must be "3x3" or "4x4". solution is a list of cell indices.
result = solver.grid(
"grid.png",
instructions="select all traffic lights",
grid_size="3x3",
)
print(result.solution)
BLS captcha
Solve a BLS multi-image captcha. Pass exactly 9 images (path/URL/base64/bytes each). solution is a list of cell indices.
result = solver.bls(
images=[f"img{i}.png" for i in range(9)],
instructions="YOUR_INSTRUCTIONS",
)
print(result.solution)
reCAPTCHA v2
Solve reCAPTCHA v2 (standard, invisible, or enterprise). Pass sitekey and page url. Enterprise results include user_agent.
# Standard
result = solver.recaptcha_v2(
sitekey="YOUR_SITEKEY",
url="https://example.com",
)
print(result.solution)
# Invisible
result = solver.recaptcha_v2(
sitekey="YOUR_SITEKEY",
url="https://example.com",
invisible=True,
)
# Enterprise (optional action; result may include user_agent)
result = solver.recaptcha_v2(
sitekey="YOUR_SITEKEY",
url="https://example.com",
enterprise=True,
action="login",
)
print(result.solution, result.user_agent)
Optional keyword args: cookies, user_agent, proxy, proxytype.
reCAPTCHA v3
Solve reCAPTCHA v3 (standard or enterprise). The registry requires action for both variants.
result = solver.recaptcha_v3(
sitekey="YOUR_SITEKEY",
url="https://example.com",
action="login",
min_score=0.3,
)
print(result.solution)
# Enterprise
result = solver.recaptcha_v3(
sitekey="YOUR_SITEKEY",
url="https://example.com",
action="login",
enterprise=True,
)
print(result.solution, result.user_agent)
Optional keyword args: cookies, user_agent, proxy, proxytype.
Cloudflare Turnstile
Solve a Cloudflare Turnstile widget.
result = solver.turnstile(
sitekey="YOUR_SITEKEY",
url="https://example.com",
)
print(result.solution)
Optional keyword args: cookies, user_agent, proxy, proxytype.
Cloudflare Challenge
Solve a Cloudflare interstitial challenge page. A proxy is mandatory (client-level or per-call). The result includes user_agent to reuse on the target site.
solver = CaptchaAI(
api_key="YOUR_32_CHAR_API_KEY",
proxy="user:pass@host:port",
proxytype="HTTP",
)
result = solver.cloudflare_challenge(url="https://example.com")
print(result.solution, result.user_agent)
Optional keyword args: cookies, user_agent, proxy, proxytype.
GeeTest
Solve GeeTest v3. solution is a dict with challenge, validate, and seccode.
result = solver.geetest(
gt="YOUR_GT",
challenge="YOUR_CHALLENGE",
url="https://example.com",
)
print(result.solution["challenge"])
print(result.solution["validate"])
print(result.solution["seccode"])
Optional keyword args: cookies, user_agent, proxy, proxytype.
CaptchaFox
Solve a CaptchaFox slider challenge. A proxy is mandatory. Reuse result.user_agent when submitting the token.
solver = CaptchaAI(
api_key="YOUR_32_CHAR_API_KEY",
proxy="user:pass@host:port",
proxytype="HTTP",
)
result = solver.captchafox(
sitekey="YOUR_SITEKEY",
url="https://example.com",
)
print(result.solution, result.user_agent)
Optional keyword args: cookies, user_agent, proxy, proxytype.
Friendly Captcha
Solve a Friendly Captcha proof-of-work challenge. No proxy is required.
result = solver.friendly_captcha(
sitekey="YOUR_SITEKEY",
url="https://example.com",
version="v1", # optional: "v1" or "v2"
)
print(result.solution)
Optional keyword args: proxy, proxytype.
Lemin
Solve a Lemin puzzle. solution is a dict with answer and challenge_uuid.
result = solver.lemin(
captcha_id="YOUR_CAPTCHA_ID",
div_id="lemin-cropped-captcha",
url="https://example.com",
api_server="api.leminnow.com", # optional
)
print(result.solution["answer"])
print(result.solution["challenge_uuid"])
Optional keyword args: proxy, proxytype.
Other methods
Thread usage
CaptchaAI is thread-based. Check current usage:
info = solver.threads_info()
# {"threads": 10, "working_threads": 3}
Manual submit / fetch
Submit now and poll later (params use API names, e.g. googlekey, pageurl):
task_id = solver.send(
"recaptcha_v2",
googlekey="YOUR_SITEKEY",
pageurl="https://example.com",
)
result = solver.get_result("recaptcha_v2", task_id)
print(result.solution)
Close
solver.close()
Error handling
All SDK errors inherit from CaptchaAIError:
from captchaai import (
CaptchaAI,
CaptchaAIError,
InvalidKeyError,
ValidationError,
ProxyError,
ThreadLimitError,
NoThreadsError,
UnsolvableError,
APIError,
NetworkError,
TimeoutError,
)
solver = CaptchaAI(api_key="YOUR_32_CHAR_API_KEY")
try:
result = solver.recaptcha_v2(
sitekey="YOUR_SITEKEY",
url="https://example.com",
)
except InvalidKeyError:
... # wrong-length key, or API rejected the key
except ValidationError:
... # missing/invalid params, bad image input, missing required proxy, etc.
except ProxyError:
... # bad proxy or proxy connection failed
except ThreadLimitError:
... # all account threads busy (and retries skipped or exhausted)
except NoThreadsError:
... # account expired or has no active plan
except UnsolvableError:
... # service could not solve the captcha
except NetworkError:
... # could not reach the API
except TimeoutError:
... # poll deadline exceeded before a result was ready
except APIError:
... # unexpected / malformed API response
except CaptchaAIError:
... # any other SDK error
Retry behaviour
| Setting | Behaviour |
|---|---|
auto_retry=True (default) |
Retry transient submit/proxy errors with exponential backoff |
auto_retry=False |
Raise immediately on transient errors; also fast-fails when the local in-flight count hits the thread cap |
max_retries=N (N > 0) |
Like auto_retry=True, capped at N submit attempts |
max_retries=0 |
Like auto_retry=False |
max_retries supersedes auto_retry when both are provided. Fatal errors (InvalidKeyError, ValidationError, UnsolvableError, NoThreadsError, and similar) always raise immediately.
Proxies
Proxies are supported at client level and per call. Format: "user:pass@host:port". proxytype is required whenever a proxy is set (HTTP, HTTPS, SOCKS4, or SOCKS5).
# Client-level (every solve)
solver = CaptchaAI(
api_key="YOUR_32_CHAR_API_KEY",
proxy="user:pass@host:port",
proxytype="HTTP",
)
# Per-call override (does not mutate client config)
result = solver.recaptcha_v2(
sitekey="YOUR_SITEKEY",
url="https://example.com",
proxy="user:pass@other-host:port",
proxytype="SOCKS5",
)
Proxy is mandatory for:
cloudflare_challengecaptchafox
Async usage
Build the async client with await AsyncCaptchaAI.create(...) — not AsyncCaptchaAI(...) — because key validation must be awaited at construction.
import asyncio
from captchaai import AsyncCaptchaAI
async def main():
solver = await AsyncCaptchaAI.create(api_key="YOUR_32_CHAR_API_KEY")
result = await solver.turnstile(
sitekey="YOUR_SITEKEY",
url="https://example.com",
)
print(result.solution)
await solver.aclose()
asyncio.run(main())
The async client mirrors the sync methods (normal, recaptcha_v2, send, get_result, threads_info, …). You can also use it as an async context manager:
async with await AsyncCaptchaAI.create(api_key="YOUR_32_CHAR_API_KEY") as solver:
result = await solver.normal("captcha.png")
print(result.solution)
Note:
async with await AsyncCaptchaAI.create(...)requires Python 3.10+; alternatively assign the client first, thenasync with solver.
License
This project is licensed under the MIT License.
Copyright (c) 2026 Dev@Captchaai
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file captchaai-0.1.0.tar.gz.
File metadata
- Download URL: captchaai-0.1.0.tar.gz
- Upload date:
- Size: 39.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5d89b77af610c553a9d0ff39dd611aeced6e391be2548cdf5b522905f68e680
|
|
| MD5 |
86c3ccd2e0e423b06a646ae9c32f9efb
|
|
| BLAKE2b-256 |
94bf2ba58e95e084d3624c2ae8fd45a71aa64a32d3fbc7bba189d9ab5571346d
|
Provenance
The following attestation bundles were made for captchaai-0.1.0.tar.gz:
Publisher:
publish.yml on CaptchaAI/captchaai-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
captchaai-0.1.0.tar.gz -
Subject digest:
e5d89b77af610c553a9d0ff39dd611aeced6e391be2548cdf5b522905f68e680 - Sigstore transparency entry: 2255909502
- Sigstore integration time:
-
Permalink:
CaptchaAI/captchaai-python@36e4af8b0cbd5bc24066ef6437f5980251bf7192 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/CaptchaAI
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@36e4af8b0cbd5bc24066ef6437f5980251bf7192 -
Trigger Event:
push
-
Statement type:
File details
Details for the file captchaai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: captchaai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 42.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
888465796951a99a4b0516201951ba02e66802e9767f96b65b6ef5a4e6f2ad37
|
|
| MD5 |
0bad99331c866ef40c1a572bdc843d60
|
|
| BLAKE2b-256 |
c173b1d623c6d39de2d3a19f81dab682adb4c6e7600e261d3098085958033ad3
|
Provenance
The following attestation bundles were made for captchaai-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on CaptchaAI/captchaai-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
captchaai-0.1.0-py3-none-any.whl -
Subject digest:
888465796951a99a4b0516201951ba02e66802e9767f96b65b6ef5a4e6f2ad37 - Sigstore transparency entry: 2255909513
- Sigstore integration time:
-
Permalink:
CaptchaAI/captchaai-python@36e4af8b0cbd5bc24066ef6437f5980251bf7192 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/CaptchaAI
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@36e4af8b0cbd5bc24066ef6437f5980251bf7192 -
Trigger Event:
push
-
Statement type: