CaptchaAI Python library β an official CAPTCHA solver and solving API client for reCAPTCHA v2/v3/Enterprise, Cloudflare Turnstile, Cloudflare Challenge, GeeTest v3, and image CAPTCHAs.
Call one method per captcha type; the SDK handles HTTP, polling, retries, and typed error mapping.
For full copy-paste examples of every captcha type and SDK feature, see examples.md.
- Examples
- Packages
- Installation
- Configuration
- Solve result
- Normal captcha
- Grid captcha
- BLS captcha
- reCAPTCHA v2 & v3
- Cloudflare Turnstile
- Cloudflare Challenge
- GeeTest v3
- CaptchaFox (beta)
- Friendly Captcha (beta)
- Lemin (beta)
- Other methods
- Error handling
- Proxies
- Async usage
- License
- PyPI Package: https://pypi.org/project/captchaai/ (
pip install captchaai) - GitHub Releases: https://github.com/CaptchaAI/captchaai-python/releases
pip install captchaaiCreate a sync client with your API key from CaptchaAI. 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.
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 typesReuse result.user_agent on the target site when it is present (Enterprise, Cloudflare Challenge, CaptchaFox).
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)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)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)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)
print(result.user_agent)Solve reCAPTCHA v3. min_score defaults to 0.3. Enterprise results include user_agent.
# Standard v3
result = solver.recaptcha_v3(
sitekey="YOUR_SITEKEY",
url="https://example.com",
action="verify",
min_score=0.7,
)
print(result.solution)
# Enterprise v3
result = solver.recaptcha_v3(
sitekey="YOUR_SITEKEY",
url="https://example.com",
action="login",
min_score=0.9,
enterprise=True,
)Solve a Cloudflare Turnstile challenge. Optional: action, cdata, user_agent.
result = solver.turnstile(
sitekey="0x4AAAAAAAB...",
url="https://example.com",
action="login",
)
print(result.solution)Solve Cloudflare Challenge (5s / Managed / Non-Interactive). A working proxy is required.
result = solver.cloudflare_challenge(
url="https://example.com",
html="<html>...</html>", # full page HTML
proxy="user:pass@host:port", # required
proxytype="HTTP", # required
user_agent="Mozilla/5.0 ...", # must match the session that fetched the HTML
)
print(result.solution) # clearance cf_clearance cookie or token
print(result.user_agent)Solve a GeeTest v3 challenge. Requires gt, challenge, and url. Optional: api_server.
result = solver.geetest_v3(
gt="YOUR_GT",
challenge="YOUR_CHALLENGE",
url="https://example.com",
)
print(result.solution["geetest_challenge"])
print(result.solution["geetest_validate"])
print(result.solution["geetest_seccode"])Solve CaptchaFox. A working proxy is required.
result = solver.captchafox(
sitekey="YOUR_SITEKEY",
url="https://example.com",
proxy="user:pass@host:port",
proxytype="HTTP",
)
print(result.solution)Solve Friendly Captcha (v1 or v2). No proxy is required.
result = solver.friendly_captcha(
sitekey="YOUR_SITEKEY",
url="https://example.com",
version="v1", # optional: "v1" or "v2"
)
print(result.solution)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"])CaptchaAI is thread-based. Check current usage:
info = solver.threads_info()
# {"threads": 10, "working_threads": 3}Submit now and poll later:
task_id = solver.send(
"recaptcha_v2",
googlekey="YOUR_SITEKEY",
pageurl="https://example.com",
)
result = solver.get_result("recaptcha_v2", task_id)
print(result.solution)solver.close()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
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 errorProxies 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",
)Build the async client with await AsyncCaptchaAI.create(...):
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())- π Official Website
- π API Documentation
- π PyPI Package
- π§© Chrome Extension
This project is licensed under the MIT License.
Copyright (c) 2026 Dev@Captchaai