Python SDK
使用官方 CaptchaSonic SDK 从 Python 中解决验证码 —— 支持 gRPC + HTTP 传输、异步就绪、完整类型提示。
官方 CaptchaSonic Python SDK 将每一种受支持的验证码都变成一次函数调用。它同时提供同步客户端(CaptchaSonic)和异步客户端(AsyncCaptchaSonic),默认通过 gRPC 与我们的基础设施通信(并提供可选的 HTTP 传输),并包含完整的类型提示、针对瞬时错误的自动重试,以及针对令牌类挑战的内置轮询。
安装
pip install captchasonic
默认会安装 gRPC 传输。若还需使用可选的 HTTP/JSON 传输,请安装 extra:
pip install "captchasonic[http]"
TIP
该 SDK 支持 Python 3.10、3.11、3.12 和 3.13,并以 MIT 许可证发布。
身份验证
你需要一个 CaptchaSonic API 密钥。创建账户后,在控制台中获取你的密钥,然后在充值页面为余额充值。
将密钥作为客户端的第一个位置参数传入:
from captchasonic import CaptchaSonic
solver = CaptchaSonic("YOUR_API_KEY")
WARNING
请像对待密码一样对待你的 API 密钥。不要将其提交到版本控制系统 —— 应从环境变量或密钥管理工具中加载,而不要硬编码在代码中。
import os
from captchasonic import CaptchaSonic
solver = CaptchaSonic(os.environ["CAPTCHASONIC_API_KEY"])
快速开始
大多数令牌类验证码(reCAPTCHA、Turnstile、hCaptcha)只需一次调用即可解决。客户端会自动为你轮询,并在任务就绪后返回令牌。
from captchasonic import CaptchaSonic
solver = CaptchaSonic("YOUR_API_KEY")
result = solver.solve_recaptcha_v2_token(
website_url="https://example.com/login",
website_key="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
)
print(result["token"])
# 03AGdBq25SxXT... ← 将其填入 g-recaptcha-response 字段
返回
result["token"]—— 将其作为页面的g-recaptcha-response提交。
令牌类方法默认最多轮询 120 秒后才会超时(参见配置)。
受支持的验证码类型
SDK 将方法分为两个系列:
- 令牌方法(
*_token、solve_turnstile、solve_cloudflare)—— 你提供website_url/website_key,SDK 轮询我们的基础设施并返回可直接提交的result["token"]。 - 图像 / 交互方法 —— 你自行提供挑战图像,SDK 返回
result["typed_solution"],描述需要点击、拖动或输入的内容。
所有图像参数都接受灵活的 ImageInput 类型 —— 文件路径(str)、pathlib.Path、原始 bytes,或一个已打开的二进制文件对象。
from pathlib import Path
# 以下任意一种都可作为 `images=[...]` 列表中的元素:
Path("captcha.png") # pathlib.Path
"./captcha.png" # str 路径
open("captcha.png", "rb").read() # bytes
reCAPTCHA v2(令牌)
result = solver.solve_recaptcha_v2_token(
website_url="https://example.com",
website_key="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
proxy="http://user:pass@host:port", # 可选
)
token = result["token"]
返回
result["token"]—— 将其作为页面的g-recaptcha-response提交。
reCAPTCHA v3(令牌)
result = solver.solve_recaptcha_v3_token(
website_url="https://example.com",
website_key="6Lc_aCMTAAAAAB...",
proxy="http://user:pass@host:port", # 可选
)
token = result["token"]
返回
result["token"]—— 将其作为页面的g-recaptcha-response提交。
reCAPTCHA v2(图像网格)
当你已经拿到挑战图块时,可直接解决网格并获取需要点击的索引。
result = solver.solve_recaptcha_v2(
images=[Path("tile.png")], # ImageInput 列表
question="traffic lights", # 标签或 /m/... 实体 ID
question_type="44", # "split_33" | "33" | "44"
)
to_click = result["typed_solution"]["grid"]["objects"] # list[int]
返回
result["typed_solution"]["grid"]["objects"]—— 需要点击的图块索引列表。
Cloudflare Turnstile
result = solver.solve_turnstile(
website_url="https://example.com",
website_key="0x4AAAAAAA...",
proxy="http://user:pass@host:port", # 可选
)
token = result["token"]
返回
result["token"]—— 将其作为表单的cf-turnstile-response提交。
Cloudflare Challenge
完整的 Cloudflare Challenge 必须提供代理。
result = solver.solve_cloudflare(
website_url="https://example.com",
website_key="0x4AAAAAAA...",
proxy="http://user:pass@host:port", # 必填
)
token = result["token"]
返回
result["token"]—— 用于受保护请求的通行令牌。
Popular CAPTCHA(hCaptcha 风格的图像挑战)
solve_popular_captcha 处理交互式图像变体;solve_popular_captcha_token 直接返回令牌。
# 图像 / 交互变体
result = solver.solve_popular_captcha(
images=[Path("challenge.png")],
question="Select all traffic lights",
question_type="grid", # "objectClassify" | "objectClick" | "objectDrag" | "grid"
)
to_click = result["typed_solution"]["grid"]["objects"] # list[int]
# 令牌变体
result = solver.solve_popular_captcha_token(
website_url="https://example.com",
website_key="00000000-0000-0000-0000-000000000000",
proxy="http://user:pass@host:port", # 可选
)
token = result["token"]
图像变体返回
result["typed_solution"]["grid"]["objects"](需要点击的图块索引);令牌变体返回result["token"]。
GeeTest(极验)
result = solver.solve_geetest(
geetest_type="nine", # "nine" | "click" | "slide" | "match" | "winlinze"
question="Select all bicycles", # "nine" 和 "click" 必填
images=[Path("tile.png")], # "nine"、"click"、"slide" 必填
)
solution = result["typed_solution"] # 结构因 geetest_type 而异
返回
result["typed_solution"]—— 需要执行的操作,其结构由geetest_type决定。
AWS WAF
result = solver.solve_aws_waf(
images=[Path("grid.png")],
question="grid:vehicles:cars",
)
to_click = result["typed_solution"]["grid"]["objects"] # list[int]
返回
result["typed_solution"]["grid"]["objects"]—— 需要点击的图块索引列表。
图像转文字(OCR)
result = solver.solve_ocr(
images=[Path("captcha.png")],
module="common", # "common" | "mtcaptcha" | "bls" | "morocco"
numeric=False, # 仅期望数字
case_sensitive=True, # 保留字母大小写
min_length=4,
max_length=8,
)
text = result["typed_solution"]["text"]["texts"][0] # str
返回
result["typed_solution"]["text"]["texts"][0]—— 需要填入的识别文本。
滑块拼图
传入背景图和拼图块;返回需要滑动的水平像素偏移量。
result = solver.solve_slide_image(
images=[Path("background.png"), Path("piece.png")],
)
offset_x = result["typed_solution"]["slide"]["x"] # float(像素)
返回
result["typed_solution"]["slide"]["x"]—— 拖动拼图块所需的水平像素偏移量。
TikTok
result = solver.solve_tiktok(
type="whirl", # "click" | "whirl" | "slide"
images=[Path("outer.png")],
examples=[Path("inner.png")], # "whirl" 和 "slide" 必填
)
solution = result["typed_solution"]
返回
result["typed_solution"]—— 需要执行的操作,其结构由type决定。
Binance(币安)
result = solver.solve_binance(
type="grid", # "grid" | "slide"
question="Select all bicycles", # "grid" 必填
images=[Path("grid.png")],
)
solution = result["typed_solution"]
返回
result["typed_solution"]—— 需要执行的操作,其结构由type决定。
异步用法
对于高并发场景(FastAPI 处理函数、Scrapy 爬虫、asyncio 管道),请使用 AsyncCaptchaSonic。它与同步 API 完全一致,但每个解决方法都是可 await 的。请将其用作异步上下文管理器,以便底层通道被自动清理。
import asyncio
from captchasonic import AsyncCaptchaSonic
async def main():
async with AsyncCaptchaSonic("YOUR_API_KEY") as solver:
result = await solver.solve_turnstile(
website_url="https://example.com",
website_key="0x4AAAAAAA...",
)
print(result["token"])
asyncio.run(main())
同步客户端同样支持上下文管理器协议:
with CaptchaSonic("YOUR_API_KEY") as solver:
result = solver.solve_ocr(images=[Path("captcha.png")])
print(result["typed_solution"]["text"]["texts"][0])
代理支持
令牌方法接受可选的 proxy 参数(solve_cloudflare 为必填)。使用标准的代理 URL:
proxy = "http://user:pass@host:port"
result = solver.solve_recaptcha_v2_token(
website_url="https://example.com",
website_key="6Le-...",
proxy=proxy,
)
TIP
提供代理可让我们的求解器还原你请求的地理位置和 IP 信誉,从而提高在具有严格反机器人规则的站点上的成功率。
配置
所有选项都传递给客户端构造函数,并同时适用于同步和异步客户端。
solver = CaptchaSonic(
"YOUR_API_KEY",
transport="grpc", # "grpc"(默认)或 "http"
url="api.captchasonic.com:443", # 覆盖端点(可选)
timeout=30.0, # 单次调用超时,单位秒
polling_interval=2.0, # 任务轮询间隔,单位秒
polling_timeout=120.0, # 令牌任务的最长等待时间,单位秒
secure=True, # 为 gRPC 使用 TLS
)
| 选项 | 默认值 | 说明 |
|---|---|---|
transport | "grpc" | 传输协议。"grpc" 发送图像时无 base64 开销;"http"(需要 [http] extra)以 REST/JSON 发送,图像采用 base64 编码。 |
url | api.captchasonic.com:443 | 覆盖 API 端点(例如用于自托管或 staging)。 |
timeout | 30.0 | 单次调用的网络超时,单位秒。 |
polling_interval | 2.0 | 等待令牌任务时的轮询间隔,单位秒。 |
polling_timeout | 120.0 | 令牌任务抛出异常前的最长等待时间,单位秒。 |
secure | True | 为 gRPC 通道使用 TLS。 |
瞬时 gRPC 错误会自动重试(最多 3 次)并采用指数退避,因此你只需处理真正的业务错误。
错误处理
所有 SDK 错误都继承自 SonicError,因此你可以用一个 except 子句捕获全部错误,或针对具体子类分别处理。每个错误还携带一个数字 error_id。
from captchasonic.exceptions import (
SonicError,
InvalidApiKeyError,
InsufficientBalanceError,
)
try:
result = solver.solve_turnstile(
website_url="https://example.com",
website_key="0x4AAAAAAA...",
)
except InsufficientBalanceError:
print("Top up your balance to continue.")
except InvalidApiKeyError:
print("Check your API key.")
except SonicError as err:
print(f"Solve failed (error_id={err.error_id}): {err}")
error_id | 异常 | 原因 | 操作 |
|---|---|---|---|
| 1 | InvalidApiKeyError | API 密钥缺失或无效。 | 在控制台中核实密钥。 |
| 2 | InsufficientBalanceError | 账户余额不足以支付该任务。 | 充值。 |
| 3 | DailyLimitExceededError | 每日配额已用尽。 | 等待每日重置或升级套餐。 |
| 4 | MinuteLimitExceededError | 达到每分钟速率限制。 | 降低请求速率 / 增加退避。 |
| 5 | QuotaExceededError | 套餐配额已用尽。 | 升级套餐。 |
| 6 | PlanExpiredError | 订阅已过期。 | 续订订阅。 |
账户辅助方法
balance = solver.get_balance() # 当前余额,单位 USD(float)
print(f"Balance: ${balance:.2f}")
health = solver.health_check() # HealthCheckResponse —— 验证连接性
可将 health_check() 用作服务中的轻量级就绪探针,并用 get_balance() 在开始消耗额度前对任务进行门控。
故障排查
TIP
使用 HTTP 传输时出现 ModuleNotFoundError。 HTTP 客户端依赖 httpx,它是一个可选 extra。请使用 pip install "captchasonic[http]" 安装它,并设置 transport="http"。
- 令牌任务在约 120 秒后抛出异常。 这是
polling_timeout。对于较慢的目标可增大它,例如CaptchaSonic(key, polling_timeout=240.0)。 solve_cloudflare立即失败。 Cloudflare Challenge 必须提供proxy参数 —— 请提供一个可用的代理 URL。- 在企业代理 / 防火墙后出现 gRPC 连接错误。 gRPC 需要通过 443 端口使用 HTTP/2。如果你的网络封锁了它,请切换到
transport="http"。 - 图像方法返回的是索引而非令牌。 交互式方法(
solve_recaptcha_v2、solve_popular_captcha、solve_aws_waf、solve_geetest等)返回result["typed_solution"],描述需要执行的操作;只有*_token、solve_turnstile和solve_cloudflare返回result["token"]。