API — 验证码识别
一个使用 anti-captcha.com 协议的独立监听器:将第三方软件指向它,即可通过您自己的代理求解图片、访问 Cookie、RCv2、CFt、GT 和 AW。
这是什么
BlankTrail Proxy 可以通过 anti-captcha.com 协议接收验证码识别任务。它是一个独立端口上的独立监听器:已经支持该协议的第三方软件,只需把地址指向您的服务器,而不是识别服务的地址。
之所以采用独立监听器而非面板端口上的路由,有两个原因。协议的官方客户端请求主机根路径,即完全占用根路径。而且验证码 API 可能需要在局域网中使用,但管理面板不应对任何人可见。
如何开启
配置文件 captcha_api 段中的三个字段。开关和地址也可以在面板中修改:设置 → “验证码 API”卡片。
captcha_api:
enabled: true
addr: ":8892"
allow_lan: false
max_concurrent: 10
task_ttl: "5m"
port_idle_timeout: "10m"
| 字段 | 作用 |
|---|---|
| enabled | 是否启动监听器。默认关闭。 |
| addr | 监听地址。在允许局域网访问之前,空主机表示仅回环地址。 |
| allow_lan | 即使面板通用的“允许局域网”关闭,也接受来自其他机器的请求。验证码 API 遵循面板的这一通用设置,本字段在其基础上额外开放它——与代理端口分开。在 Docker 镜像中已开启。 |
| max_concurrent | 并发任务上限。零表示完全没有上限。 |
| task_ttl | 任务完成后保留结果的时长。 |
| port_idle_timeout | 为任务代理打开的端口在空闲多久后关闭。 |
在容器中
除开关外,镜像中的其余部分都已配置妥当:8892 端口已声明,随镜像提供的 compose 文件将其发布到 127.0.0.1,镜像配置也已允许监听器绑定到回环地址以外。剩下的只是开启——用环境变量,或直接在面板中操作。覆盖是单向的:变量只能开启和设置,不能关闭配置中已启用的项。
docker run -d \
-e BT_CAPTCHA_API_ENABLED=1 \
-p 127.0.0.1:8892:8892 \
... blanktrail-proxy
密钥与访问
clientKey 就是您面板的 API 密钥,完全相同。验证码 API 没有独立密钥:为一个接口引入另一个需要独立存储和轮换的密钥并不值得。
- 密钥按协议要求放在请求体中,而不是请求头。
- 密钥爆破受到限制:连续失败后,无论下一个密钥是否正确,该地址都会被拒绝。
- 在允许局域网访问之前(通过通用的“允许局域网”设置或 allow_lan 字段),来自其他机器的请求会被拒绝——包括 getQueueStats 和 test。
支持的任务类型
| 类型 | 作用 |
|---|---|
| ImageToTextTask | 使用本地模型识别图片上的文字。 |
| AntiGateTask | 通过站点防护并返回访问 Cookie。 |
| RecaptchaV2Task | 根据页面地址和站点密钥求解 RCv2,并通过您的代理。 |
| RecaptchaV2TaskProxyless | 同样的功能,但不使用您的代理——直接出口。 |
| TurnstileTask | 根据页面地址和站点密钥获取 CFt 令牌,并通过您的代理。 |
| TurnstileTaskProxyless | 同样的功能,但不使用您的代理。 |
| GeeTestTask | 根据站点参数求解 GTv3 或 GTv4,并通过您的代理。 |
| GeeTestTaskProxyless | 同样的功能,但不使用您的代理。 |
| AmazonTask | 通过 AW 拦截页并返回其令牌,并通过您的代理。 |
| AmazonTaskProxyless | 同样的功能,但不使用您的代理。 |
其他协议类型会返回 ERROR_TASK_NOT_SUPPORTED。这是正常响应而非故障:客户端在创建任务时立即看到它,可以直接改用其他服务,无需等待。
Proxyless 变体从安装本身的出口求解——即运行 BlankTrail Proxy 的机器的直接地址。即使发送了代理字段,这类任务也不会使用。
工作方式
- 通过 createTask 创建任务,获得数字 taskId。
- 轮询 getTaskResult,直到响应不再是 processing。
- 收到 ready 和解答对象——其内容取决于任务类型。
出口与配置
除 ImageToTextTask 外,所有任务都由求解器的浏览器完成,它通过为任务代理打开的产品端口访问网络。这与代理端口上的自动求解是同一条路径:浏览器的请求从您代理的出口发出(Proxyless 变体则从安装本身的出口发出),使用该端口配置的 TLS 与 HTTP/2 指纹和 user-agent。令牌或 Cookie 是在端口向站点呈现的同一身份下获得的。
端口按“代理 + 配置”组合打开,并持续到 port_idle_timeout 设定的空闲时间。之后使用相同代理和相同配置的任务会通过同一个端口。
如何选择配置
您发送的 userAgent 不会出现在网络流量中。它按浏览器系列、主版本号和操作系统选择最接近的配置,实际发送的是该配置自身的 user-agent——以及与之匹配的 TLS 和 HTTP/2 指纹。
如果未发送 userAgent 或无法识别(Opera、Yandex 浏览器、不带 Version/ 标记的 Safari),端口将使用配置库中最新版本的 Windows 版 Chrome——与未指定版本的 Chrome 配置端口相同。AntiGateTask 和 AmazonTask 没有 userAgent 字段,始终使用该配置。
每个此类任务都会计入仪表盘 Challenge Breaker 卡片的一次尝试,与代理端口上的求解一并统计。
图片识别
图片以 base64 传递。响应在 text 字段中携带识别出的文字。
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "ImageToTextTask",
"body": "iVBORw0KGgoAAAANSUhEUg..."
}
}
访问 Cookie
AntiGateTask 通过站点防护并返回 Cookie。响应中还会带回一个端口地址,这些 Cookie 必须通过该端口出示。
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "AntiGateTask",
"websiteURL": "https://example.com/",
"proxyType": "http",
"proxyAddress": "203.0.113.7",
"proxyPort": 8080,
"proxyLogin": "user",
"proxyPassword": "pass"
}
}
RCv2
该任务需要页面地址和站点公钥。不使用您代理的变体名为 RecaptchaV2TaskProxyless,无需代理字段。
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "RecaptchaV2Task",
"websiteURL": "https://example.com/login",
"websiteKey": "6Lc_aCMTAAAAA...",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
"proxyType": "http",
"proxyAddress": "203.0.113.7",
"proxyPort": 8080
}
}
响应为 gRecaptchaResponse 和 userAgent(示例见下方 getTaskResult 方法)。
CFt
该任务需要页面地址和站点密钥(websiteKey,形如 0x4AAAA… 的字符串)。可选的 action、cData 和 chlPageData 会原样传给组件。不使用您代理的变体为 TurnstileTaskProxyless。
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "TurnstileTaskProxyless",
"websiteURL": "https://example.com/login",
"websiteKey": "0x4AAAAAAA...",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."
}
}
响应为 token 和 userAgent。令牌放入表单的 cf-turnstile-response 字段,或交给组件的回调;携带它的请求请使用响应中的 userAgent。
{
"errorId": 0,
"status": "ready",
"solution": {
"token": "0.Zk3bE8...",
"userAgent": "Mozilla/5.0 ..."
}
}
GT
支持 GTv3 和 GTv4;version 字段指定版本(3 或 4,默认 3)。不使用您代理的变体为 GeeTestTaskProxyless。
- v3:需要站点的 gt 和 challenge。challenge 只能使用一次——请在创建任务前立即从站点获取。可选的 geetestApiServerSubdomain 用于在站点不使用 GT 默认服务器时指定 API 服务器。
- v4:需要 captchaId——放在 gt 字段或 initParameters.captcha_id 中。其余 initParameters 会原样传给 initGeetest4。
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "GeeTestTaskProxyless",
"websiteURL": "https://example.com/login",
"gt": "0f1e2d3c4b5a69788796a5b4c3d2e1f0",
"version": 4,
"initParameters": {"riskType": "slide"},
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."
}
}
v3 的响应为 challenge、validate 和 seccode;v4 的响应为 captcha_id、lot_number、pass_token、gen_time 和 captcha_output,并附带 userAgent。您的请求把这些字段发送给站点,站点再向 GT 校验。
{
"errorId": 0,
"status": "ready",
"solution": {
"captcha_id": "0f1e2d3c4b5a69788796a5b4c3d2e1f0",
"lot_number": "7c1b2a...",
"pass_token": "a8d9...",
"gen_time": "1790770800",
"captcha_output": "Qx3k...",
"userAgent": "Mozilla/5.0 ..."
}
}
AW
该任务需要站点显示 AW 拦截页的页面地址。websiteKey、iv、context、challengeScript 和 captchaScript 字段为兼容性而接受,但并不需要:求解器会自行从页面获取这些信息。不使用您代理的变体为 AmazonTaskProxyless。
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "AmazonTask",
"websiteURL": "https://example.com/",
"proxyType": "http",
"proxyAddress": "203.0.113.7",
"proxyPort": 8080,
"proxyLogin": "user",
"proxyPassword": "pass"
}
}
响应为 token 和 userAgent。token 是 aws-waf-token Cookie 的值:在您的请求中以该名称设置它,并使用响应中的 userAgent 发送请求。getTaskResult 响应中的 ip 字段是获取令牌时使用的出口地址。
{
"errorId": 0,
"status": "ready",
"solution": {
"token": "a1b2c3d4-...:AAABk...",
"userAgent": "Mozilla/5.0 ..."
},
"ip": "203.0.113.7"
}
方法
/createTask需要 clientKey创建任务并返回数字 taskId。
{
"errorId": 0,
"taskId": 12
}/getTaskResult需要 clientKey返回任务状态,就绪后返回解答对象。
{
"clientKey": "YOUR_API_KEY",
"taskId": 12
}{
"errorId": 0,
"status": "ready",
"solution": {
"gRecaptchaResponse": "03AGdBq26...",
"userAgent": "Mozilla/5.0 ..."
}
}/getBalance需要 clientKey返回余额。本产品没有计费,因此该值是固定的;为零表示许可证未激活。
/getQueueStats无需密钥负载情况:有多少任务在执行,求解器池的繁忙程度。
/reportIncorrectImageCaptcha需要 clientKey为兼容性而接受:本产品无法根据反馈进行学习。
/reportIncorrectRecaptcha需要 clientKeyRC 的同类接口。
/reportCorrectRecaptcha需要 clientKey用于确认正确解答的同类接口。
/test无需密钥返回解析后的请求体。当第三方客户端发送的内容有误时很有用。
错误码
错误码及其名称遵循协议:客户端库比较的正是 errorCode 字符串。下面是本服务会返回的错误码。
| errorId | errorCode | 何时出现 |
|---|---|---|
| 1 | ERROR_KEY_DOES_NOT_EXIST | 密钥错误,或该地址因爆破尝试被临时封锁。 |
| 2 | ERROR_NO_SLOT_AVAILABLE | 当前没有空闲的求解器,或已达到 max_concurrent 上限。 |
| 10 | ERROR_ZERO_BALANCE | 许可证未激活:请续期,任务不会被受理。 |
| 11 | ERROR_IP_NOT_ALLOWED | 请求来自其他机器,而局域网访问未被允许——通用的“允许局域网”和 allow_lan 均未开启。 |
| 12 | ERROR_CAPTCHA_UNSOLVABLE | 求解失败。可以重试,但在端口因空闲关闭之前配置不会改变;若反复失败,请检查页面地址和站点参数:密钥、gt、challenge。 |
| 16 | ERROR_NO_SUCH_CAPCHA_ID | 不存在该 taskId 的任务:它已完成并在 task_ttl 到期后被清除,或属于其他密钥。 |
| 23 | ERROR_TASK_NOT_SUPPORTED | 任务类型不受支持、所需模型未安装,或任务种类不对——例如表单内的 AWS 验证码(wafType: widget)。 |
| 25 | ERROR_PROXY_CONNECT_REFUSED | 您的代理拒绝了连接。请修复代理,重试任务没有意义。 |
| 26 | ERROR_PROXY_CONNECT_TIMEOUT | 在规定时间内无法连接到您的代理。 |
| 27 | ERROR_PROXY_READ_TIMEOUT | 您的代理接受了连接但没有响应。 |
| 49 | ERROR_PROXY_NOT_AUTHORISED | 您的代理拒绝了用户名或密码。 |
限制
- 任务保存在内存中,重启后不会保留:重启后旧的 taskId 会返回 ERROR_NO_SUCH_CAPCHA_ID。
- 在预算时间内未完成的任务会被判定为失败,并释放其在上限中的名额。
- 不支持回调:callbackUrl 字段会被接受但忽略,结果需通过轮询获取。
- 同一站点、同一代理的任务会依次执行——这是防重放机制的特性,而非配置上限。