Troubleshooting

为什么 reCAPTCHA v3 返回低分

先说结论:分数低通常不是“被识破了”,而是提交的 token 与页面期望的上下文对不上——action 写错、token 超过两分钟才用、同一会话几秒内连打十几次 grecaptcha.execute()。这三类占了大多数,都不用改浏览器,改调用顺序就行。

安全范围: 本指南仅适用于你自有或经授权的 QA、staging 与预发布环境。内容覆盖针对你自己 CAPTCHA 集成的诊断、测试与可观测性模式 — 不涉及第三方站点或未授权流程。

reCAPTCHA v3 不弹挑战框,只给每次调用打一个 0.0(机器人)到 1.0(真人)的分数,阈值由站点自己设。所以低分永远表现为“静默失败”。


reCAPTCHA v3 的分数由哪些信号决定

Google 打分前采集的特征分这几类。

信号类别 具体采集什么
交互行为 光标轨迹、滚动与击键节奏
浏览器特征 Canvas、WebGL、字体、插件
cookie 与会话 Google 域下的 cookie 与访问历史
IP 信誉 机房 IP 还是家宽 IP、网段记录

国内开发者还有个前置坑:reCAPTCHA 的脚本托管在 Google 域名下,大陆网络访问并不稳定——本地调试时脚本没加载出来,那是资源加载失败,不是分数问题。国内站点更多用 GeeTest(极验)、腾讯防水墙、网易易盾,reCAPTCHA v3 主要出现在海外站点上。


七类常见成因,按排查性价比排序

1. action 参数对不上

action 会编码进 token,站点在后端比对。你传 submit、页面实际用 login,分数再高也没用。

处理方式: 在页面源码或 DevTools 里搜 grecaptcha.execute,把 action 原样抄下来。大小写敏感。

2. token 用得太晚

token 有效期是 2 分钟。常见写法是页面一加载就取 token,填完二十个字段才提交,超时就废了。

处理方式: 先填字段,最后取 token 并立即提交。

3. 同一会话请求过密

同一会话短时间内反复调用 grecaptcha.execute(),后续每次分数逐级走低。

处理方式: 间隔至少 15–30 秒;按业务粒度切分会话;QA 场景用队列限流。

4. sitekey 取错了版本

同一域名下可能同时挂着 v2 和 v3 两套 key。典型症状是分数稳定地低,换 IP 换环境都没变化。

处理方式: 确认取的是 render 参数里的 v3 sitekey,提交时 versionv3

5. 机房 IP 与信誉记录

机房 IP 段普遍比家宽 IP 段分数低,被大量脚本用过的公开出口更是如此。

处理方式: 测试流量走自有服务器基础设施,出口稳定可追溯——出口一直在变,分数波动就没法归因。

6. 浏览器信号不完整

默认配置的 headless 浏览器信号残缺:没有鼠标轨迹、没有滚动历史、也没有 cookie。

处理方式: 设置真实的视口尺寸和 User-Agent;让 QA 脚本真实走完流程(滚动、聚焦、正常速度填写);复用持久化的浏览器配置目录。

带 Google 账号 cookie(NIDSIDHSID)的浏览器分数通常更高,全新配置起点天然偏低。

处理方式: QA 环境用一个已登录 Google 服务的配置目录,让它持续存在。


一个真实场景:跨境电商的登录回归测试

一家深圳的跨境电商团队,站点在新加坡,登录页阈值 0.5。回归测试本地好好的,一上 CI 就全线失败。

两个问题叠加:CI runner 在机房网络里,IP 信誉本就不占优;更关键的是脚本把并发拉到 20,同一会话十几秒内打了二十次 grecaptcha.execute()——第一个 token 勉强过线,后面十九个全掉到 0.1 以下。

改法很朴素:并发降到 4,每个 worker 独立会话,间隔 20 秒。整轮测试从 3 分钟变成 11 分钟,通过率回到可用水平——v3 上吞吐与分数此消彼长


用 CaptchaAI 提交 reCAPTCHA v3 任务

CaptchaAI 在真实浏览器环境中处理 reCAPTCHA v3,返回的 token 分数通常在 0.3 附近,能过阈值不高的站点,过不了 0.5 以上的关键页面——分数由 Google 给出。

Python 示例:提交任务后每 5 秒轮询结果。

import requests
import time

response = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "version": "v3",
    "googlekey": "SITE_KEY",
    "action": "login",
    "pageurl": "https://staging.example.com/qa-login",
    "json": 1
})

task_id = response.json()["request"]

for _ in range(30):
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": "YOUR_API_KEY", "action": "get", "id": task_id, "json": 1
    }).json()
    if result.get("status") == 1:
        token = result["request"]
        print(f"Token received: {token[:50]}...")
        break

Node.js 版本逻辑相同,action 必须与页面里的字符串一致:

const axios = require('axios');

async function solveV3(sitekey, pageurl, action) {
  const { data } = await axios.get('https://ocr.captchaai.com/in.php', {
    params: {
      key: 'YOUR_API_KEY', method: 'userrecaptcha', version: 'v3',
      googlekey: sitekey, action, pageurl, json: 1
    }
  });

  const taskId = data.request;
  for (let i = 0; i < 30; i++) {
    await new Promise(r => setTimeout(r, 5000));
    const res = await axios.get('https://ocr.captchaai.com/res.php', {
      params: { key: 'YOUR_API_KEY', action: 'get', id: taskId, json: 1 }
    });
    if (res.data.status === 1) return res.data.request;
  }
  throw new Error('Timeout');
}

拿到 token 后写进页面的 g-recaptcha-response 字段并提交表单。并发取决于线程数:CaptchaAI 按并发线程计费,套餐内识别次数不限。BASIC($15/月,5 线程)够单人调试,ADVANCE($90/月,50 线程)适合持续跑回归测试的团队。任务完成线程即释放。


常见问题

reCAPTCHA v3 要多少分才算通过?

阈值由站点自己定:低风险页面常见 0.3,默认 0.5,支付和账号变更这类关键操作 0.7。这个值从外部读不到,只能靠“哪些分数被接受了”反推。

CaptchaAI 返回的 token 分数大概是多少?

通常在 0.3 左右。分数由 Google 的风险模型给出,识别服务只能把 token 取回来,不能决定它值几分。阈值高于 0.3 的站点,靠识别质量解决不了。

怎么确认目标站点用的是 v3 而不是 v2?

看页面加载的脚本地址:带 render= 参数、且没有可见勾选框的是 v3。同一域名下两套 key 并存很常见,取错版本会表现为分数稳定偏低,换环境也不变。

分数低的时候,为什么后端没有任何报错?

分数由 Google 给出,接受还是拒绝则由站点自己的后端代码决定。多数实现直接返回 200 加一个通用失败态,日志里自然看不到验证码相关的错误。排查要从后端的分数判定逻辑入手。

国内网络环境下怎么测 reCAPTCHA v3?

大陆网络访问 Google 域名不稳定,本地调试容易连基线都跑不出来。可行的做法是把 QA 环境部署在海外节点——这是环境选型问题,本文不涉及任何绕开网络限制的操作。


相关指南

该文章已禁用评论。