跳转到内容

并发限制与自动暂停

为了让所有用户的识别都保持速度,YesCaptcha 有三条保护规则:按账号限制同时处理中的任务数(并发限制);同一个 clientKey 短时间内错误太多会被暂停几分钟(自动暂停);已经判定无效的参数在一段时间内直接返回原错误(无效参数缓存)。这三种情况都不扣点。

我们按账号、按任务类型限制同一时刻正在处理中的任务数,限制的是并发数,不是每分钟的请求数。

  • 从调用 createTask 开始到这次调用返回为止,任务算“处理中”。图像识别类型在 createTask 里直接返回结果,所以 并发数 ≈ 每秒发出的任务数 × 每个任务的耗时。例如每个任务 0.5 秒、每秒发 40 个,并发约为 20。
  • 同一账号下的请求合并计算;不同任务类型各算各的。
  • 超出额度的请求立即返回 ERROR_THREADS_MAXIMUM,响应里的 limit 是你当前的上限。不扣点,也不计入自动暂停。
  • 识别服务器忙不过来时,占用识别时间最多的账号,这种任务的上限会临时减半,10 分钟后自动恢复。只是限速,不会暂停账号。
  • 需要更高的额度,请 联系客服。各类型的默认额度定下来后会在本页和 服务更新记录 公布。
{
"errorId": 1,
"errorCode": "ERROR_THREADS_MAXIMUM",
"errorDescription": "这个账号这种任务同时处理中的请求已达上限 30。请降低并发、等已发出的请求返回后再发;超额的请求不扣点,也不会导致封禁。",
"limit": 30
}

(例子里的数字只是示意。)

  1. 在程序里限制“同时在等结果的请求数”,例如用信号量(Semaphore)或固定大小的线程池,而不是只控制每秒发多少个。
  2. 收到 ERROR_THREADS_MAXIMUM 后,等已发出的请求返回再发新的,或者等 1 到 2 秒再试,不要立即循环重试。
  3. 批量任务均匀地发,不要一次把成千上万个任务同时发出去。

Python(asyncio)的例子:

import asyncio
import os
import aiohttp
CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"]
LIMIT = 15 # 小于你的并发上限
sem = asyncio.Semaphore(LIMIT)
async def solve(session, task):
async with sem: # 同时最多 LIMIT 个请求在处理中
result = {}
for attempt in range(5):
async with session.post(
"https://api.yescaptcha.com/createTask",
json={"clientKey": CLIENT_KEY, "task": task},
) as resp:
result = await resp.json()
if result.get("errorCode") != "ERROR_THREADS_MAXIMUM":
return result
await asyncio.sleep(1 + attempt) # 超出额度:稍等再试
return result

同一个 clientKey 短时间内产生大量错误请求时,会被自动暂停创建任务:

触发条件 暂停时长
同一自然分钟内,下面列出的错误累计 100 次 5 分钟
ERROR_IMAGE_TYPE_NOT_SUPPORTED 出现 1 次 30 分钟
同一自然分钟内,命中“无效参数缓存”1000 次 5 分钟

计入暂停的错误:

账号并发超额返回的 ERROR_THREADS_MAXIMUM(带 limit 字段)不计入;识别服务繁忙时返回的同名错误(不带 limit)计入。识别失败(ERROR_CAPTCHA_UNSOLVABLE)、余额不足(ERROR_ZERO_BALANCE)、缺少字段(ERROR_REQUIRED_FIELDS)、题目不支持(ERROR_UNKNOWN_QUESTION)等不计入。

暂停期间:

  • 只影响 createTask 和 getBalance,返回 ERROR_IP_BLOCKED_5MIN。getTaskResult 不受影响,暂停前创建的任务照常可以查结果。
  • 响应带 retryAfter(还剩多少秒)、blockReason(触发暂停的错误码)和 blockDetail(那类请求的类型、网址、sitekey),按它们修正程序。
  • 继续发送不会延长暂停时间,到期自动恢复,不需要联系客服。
  • 在 yescaptcha.com 后台的仪表盘能看到最近 24 小时的暂停记录。
{
"errorId": 1,
"errorCode": "ERROR_IP_BLOCKED_5MIN",
"errorDescription": "这个 clientKey 短时间内产生了 100 次 ERROR_TASK_NOT_SUPPORTED 错误,为保护服务已暂停创建任务,182 秒后自动恢复。",
"retryAfter": 182,
"blockReason": "ERROR_TASK_NOT_SUPPORTED"
}

有些错误由请求参数决定,同样的参数重发结果也不会变:

这些错误不计入自动暂停,而是在全站缓存:第一次判定后缓存 2 分钟,1 小时内再次被确认则缓存 10 分钟。缓存期内同样的请求(同样的任务类型和 websiteKey,或同样的网站域名)直接返回原错误,不扣点,响应带 "cached": true、retryAfter(缓存剩余秒数)和 badRequest(命中的参数)。改正 websiteKey 或换任务类型后立即生效。

并发限制 自动暂停
原因 同时处理中的任务太多 短时间内错误请求太多
表现 只拒绝超出的那部分请求,ERROR_THREADS_MAXIMUM 这个 clientKey 暂停创建任务,ERROR_IP_BLOCKED_5MIN
恢复 有请求处理完就能发新的;临时减半 10 分钟后恢复 到期自动恢复
扣点 不扣 不扣