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
Metadata
Release files for captchaai 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| captchaai-1.0.1.tar.gz | 39.6 kB | With provenance | Details for captchaai-1.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| captchaai-1.0.1-py3-none-any.whl | Python 3 | none | any | Details for captchaai-1.0.1-py3-none-any.whl |
Total release size: 81.5 kB
Release files / captchaai-1.0.1.tar.gz
| Download URL | captchaai-1.0.1.tar.gz |
|---|---|
| Size | 39.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0515c9ad1d6971be59beaa0891c74c5272cab89a17058796e929578efa7a5c7e
|
|
BLAKE2b-256 checksum How to use checksums |
9545fdc6663fbf82dc24b225ec7d606c250f7a2d5f516719393080ff68048128
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 26, 2026.
Transparency logRelease files / captchaai-1.0.1-py3-none-any.whl
| Download URL | captchaai-1.0.1-py3-none-any.whl |
|---|---|
| Size | 42.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
762dd71ce531a8b3d856c423c9e7535bddb2f19643f22a4baf52fa04bdefbdd7
|
|
BLAKE2b-256 checksum How to use checksums |
534312d85e7a93c0c9ea6031dea198fe86bb48deb89c202302f6d3c2b12ce684
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 26, 2026.
Transparency logSecurity for captchaai 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for captchaai-1.0.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 26, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.