Skip to main content

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


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_challenge
  • captchafox

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, then async 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

captchaai-1.0.0.tar.gz (39.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

captchaai-1.0.0-py3-none-any.whl (42.0 kB view details)

Uploaded Python 3

File details

Details for the file captchaai-1.0.0.tar.gz.

File metadata

  • Download URL: captchaai-1.0.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

Hashes for captchaai-1.0.0.tar.gz
Algorithm Hash digest
SHA256 bd0b766a91ff26cb24efa5582d6f718870330a9fd2b5bf6e2f25272fca9d42bd
MD5 81283c917fbdf8230f708697a9a85af4
BLAKE2b-256 24533bb0eb088c2fcdaf0b392afa59c1ea364109947d3700eaf104d454e42cd1

See more details on using hashes here.

Provenance

The following attestation bundles were made for captchaai-1.0.0.tar.gz:

Publisher: publish.yml on CaptchaAI/captchaai-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file captchaai-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: captchaai-1.0.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

Hashes for captchaai-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 32167cd6878a6a71dc8b3f694428b63064f94faae32a5b3050a522be5bfcc911
MD5 a7c47de255da59c4045927c2cd7dd81a
BLAKE2b-256 56fa70b782c796cbf346eccecad8183a111c83543ffa27bfd9711d3591d1ea80

See more details on using hashes here.

Provenance

The following attestation bundles were made for captchaai-1.0.0-py3-none-any.whl:

Publisher: publish.yml on CaptchaAI/captchaai-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page