reCAPTCHA 识别 API 的接入可以分成四步:
- 在页面上确认 reCAPTCHA 版本,取出 sitekey 等参数。
- 向识别服务提交一个异步任务。
- 通过轮询或回调拿到 token。
- 在 2 分钟内,在同一个浏览器会话里把 token 交给目标页面。
验证是否通过,由目标站点的后端校验决定。识别接口返回了 token,只代表第一个环节完成。下面按这个顺序说明每一步要准备什么,以及常见的出错位置。
先确认是否真的需要识别 API
如果测试的是自有系统或已获授权的系统,CI 回归可以直接使用 Google 官方提供的测试密钥对。测试密钥会稳定返回预设结果,不依赖外部服务,也不产生额外费用。
识别 API 主要用在三类场景:
- 真实生产环境的端到端验收
- 无障碍辅助工具
- 允许范围内的公开数据工作流
测试环境的搭建方法可参考Playwright 验证码测试怎么做。
第一步:判断版本
reCAPTCHA 各版本的前端触发方式和后端校验机制差别很大。识别服务一般为每个版本设计单独的任务类型,类型选错了,后面的参数填得再对也不会通过。常见的判断依据如下:
- v2 复选框:页面上有“进行人机身份验证”的勾选框,可能继续弹出图片挑战。
- v2 隐式(Invisible):页面上没有勾选框,通常在点击提交按钮时触发,只在系统认为有必要时才弹出挑战。提交任务时一般要标明这是隐式版本。
- v3:全程没有交互。页面脚本调用
grecaptcha.execute(siteKey, {action: '...'})获取 token,站点后端会拿到一个 0.0 到 1.0 之间的风险分。Google 建议的默认阈值是 0.5,但每个站点可以自行设定,也可以对不同 action 设不同的阈值。 - Enterprise:页面通常加载
enterprise.js并调用grecaptcha.enterprise下的方法。后端通过 Assessment 接口拿到分数和原因代码,还可能结合 Account Defender 等风控能力。Enterprise 同时提供复选框型和评分型两种密钥。
两个版本的差异细节见reCAPTCHA v2 和 v3 区别。
第二步:准备请求参数
下表列出常见的参数命名。不同平台的字段名、大小写和嵌套结构并不完全一致,请以所用服务当前的官方文档为准。
| 参数(常见命名) | 适用版本 | 从哪里取 | 常见错误 |
|---|---|---|---|
| websiteURL | 全部 | 出现验证码的完整页面地址 | 填了首页或跳转前的地址 |
| websiteKey | 全部 | data-sitekey、api.js 的 render 参数,或 execute 的第一个参数 | 页面有多个 sitekey 时取错 |
| pageAction | v3、评分型 Enterprise | execute 调用中的 action 值 | 大小写不一致,或直接用了默认值 |
| enterprisePayload / s(data-s) | Enterprise、部分 v2 | 页面或网络请求中的动态参数 | 沿用旧值,没有每次从当前页面读取 |
| apiDomain | 按需 | 脚本实际从 www.google.com 还是 www.recaptcha.net 加载 | 默认值与实际域名不一致 |
| 代理信息 | 代理模式任务 | 自动化环境实际使用的出口 | 与浏览器的出口不一致 |
有些复杂站点在 Enterprise 校验中还会要求特定的上下文 Cookie。这类要求属于站点的非公开实现,只能针对具体目标抓包确认。
选择无代理还是代理模式。 无代理(Proxyless)模式由服务商的节点完成任务。代理模式则使用你提供的代理。Google 自家服务、SERP 等场景对 IP 和会话绑定较严,如果生成 token 的网络与浏览器所在网络的 IP 或 ASN 不一致,请求可能被判定为风险请求。不过并不是所有站点都会这样校验。比较稳妥的顺序是:
- 先用无代理模式测试,确认参数正确。
- 如果被拒,先排除其他原因。
- 仍然被拒时,再改用代理模式,并让代理与浏览器使用同一个出口。
第三步:提交任务并取回结果
主流识别服务都采用异步任务模型:
- 调用
createTask提交任务配置,换取一个 taskId。 - 调用
getTaskResult定期查询任务状态。 - 状态变为完成后,从
solution中取出gRecaptchaResponse。

下面是说明流程的伪代码,不能直接在任何平台上运行:
// 伪代码:仅说明流程,字段名以所用服务文档为准
resp = POST /createTask {
clientKey: <从环境变量读取>,
task: { type: <对应版本的任务类型>, websiteURL, websiteKey, pageAction?, 其他按需参数 }
}
taskId = resp.taskId
循环,直到超过总超时:
等待几秒
r = POST /getTaskResult { clientKey, taskId }
如果 r 表示仍在处理:继续等待
如果 r 表示已完成:token = r.solution.gRecaptchaResponse,结束循环
如果 r 返回错误:记录错误码,按错误类型决定重试或止损实现时注意三点:
- 轮询间隔和总超时要分开设置。 总超时应当给后续提交 token 留出时间,不要把 2 分钟的有效期全部耗在等待结果上。
- 错误码要分类处理。 参数错误、余额不足这类问题重试也不会成功,应直接止损。
- 密钥只放在服务端环境变量里。 不要写进前端代码,也不要出现在日志中。
轮询和回调怎么选,可参考验证码API轮询和回调有什么区别。任务长时间停在处理中,可参考验证码任务一直 processing 怎么办。
第四步:拿到 token 后立刻使用
Google 明确说明 reCAPTCHA token 在 2 分钟后过期。因此不要提前批量生成 token 放进池子里备用,最好的做法是拿到一个就马上提交一个。
注入方式取决于页面的实现:
- v2:通常把 token 填入
g-recaptcha-response字段。如果页面定义了data-callback,还需要触发对应的回调函数。 - v3 和 Enterprise:token 往往由页面脚本连同表单一起发给后端,需要按页面实际的请求路径把 token 送达。
具体做法见Puppeteer 验证码接口怎么接。
token 返回了,目标站还是拒绝:按顺序排查
识别接口返回 token,只说明 challenge 环节已经完成。目标站点的后端(/siteverify 或 Enterprise Assessment)还会检查以下几项:
- token 是否过期
- 绑定的域名是否一致
- action 是否匹配
- 分数是否达到阈值
- 请求的会话状态、Cookie 和指纹是否正常

建议按从便宜到昂贵的顺序逐项排查:
- 时效:从拿到 token 到提交,是否超过 2 分钟。排队、页面跳转和重试都会消耗时间。
- 任务类型:是否把隐式 v2 当成了复选框版本,或者把 Enterprise 当成了普通版。
- 参数:把 sitekey、URL、action 与页面上的实际值逐字比对,同时确认 apiDomain。
- Enterprise 附加数据:payload 或 s 参数是否是当次从页面读取的,站点是否要求私有 Cookie。
- v3 分数:站点的阈值可能高于 0.5,分数偏低不一定是参数填错了。
- 会话与网络:代理出口、Cookie、浏览器指纹是否与生成 token 的环境一致。
- 业务层:验证码已经通过,但被站点的其他风控规则拦截。到这一步,问题已经不在验证码本身。
每一层的详细定位方法见验证码 token 返回后验证失败怎么排查。
建议在日志中分开记录三个数字:任务成功返回数、目标站接受数、业务完成数。只看第一个数字,会把很多问题误判为识别服务的问题。
选 reCAPTCHA 识别服务时看什么
- 版本覆盖:v2 复选框、隐式、v3、Enterprise 是否分别支持,Enterprise 附加参数和代理模式能否传入。
- 计费口径:按成功计费还是按提交计费,失败是否退款。不同类型的单价可能不同,应按自己的任务组合计算成本。
- 延迟:看 P50 和 P95,不要只看平均值,还要结合 2 分钟的有效期来判断。
- 接受率:用自己的目标页面做小流量对照测试,分母按“目标站接受”计算。
成本算法可参考打码平台费用对比。
关于 NexCaptcha。 根据官网首页的公开说明,NexCaptcha 通过统一的 REST 接口处理 reCAPTCHA v2、v3 和 Enterprise:
- 采用
createTask、getTaskResult的任务模式,支持轮询和 webhook 回调。 - 密钥以
clientKey字段放在请求体中传递。 - 计费口径为按千次成功识别计费,失败退款,并提供测试额度。
- 官网称部分兼容 2Captcha、Anti-Captcha、CapSolver、CapMonster 的任务格式。
如果要从这些平台迁移,请逐项核对任务类型名、字段、回调和错误码,不要假设只换域名就能直接使用。官网展示的延迟和接受率是站方的统计口径,建议用自己的目标页面做一轮小流量对照后再做决定。各类型的支持情况、价格以及工程师联系方式,可以在 NexCaptcha 官网 查看。