API Tutorials

使用 API 解决 reCAPTCHA v2:分步实战指南

自动化脚本卡在 reCAPTCHA v2 挑战前,最快的处理方式是调用 API:提取 sitekeypageurl,提交给 CaptchaAI 的 reCAPTCHA v2 求解器,轮询拿到 token 后写回页面——全程不需要人工介入。

典型场景:

  • 跨境电商自动化:海外站点比国内站点更常见 reCAPTCHA v2,国内多用 GeeTest(极验)。
  • SaaS 出海测试:登录/注册回归脚本卡在验证码,CI 跑不完整条链路。
  • 数据采集流水线:抓取任务被表单前的验证码拦截,需要脚本自动过关。

不确定页面用的是哪个版本的 reCAPTCHA? 先看 如何识别 reCAPTCHA 版本 再继续。


准备工作清单

必备项 说明
CaptchaAI API Key captchaai.com/api.php 申请,32 位字符串
目标页面 URL 加载控件的完整地址,带协议头
reCAPTCHA v2 sitekey 该控件实例对应的公开站点密钥
运行环境 Python 3.7+(requests)或 Node.js 18+(内置 fetch
token 提交方式 Selenium/Puppeteer/Playwright 或 HTTP 请求代码路径

小提示: reCAPTCHA 依赖 Google 托管脚本,国内网络直接请求有时不稳定——这是网络可达性问题,不是 API 故障,测试环境建议放在海外服务器或 CI 节点。


提取 sitekey 和 pageurl 这两个必传参数

sitekeypageurl 是仅有的两个必传输入,任意一个填错都是提交失败最常见的原因。

找到 sitekey 的三种方式

sitekey 是 Google 给该页面 reCAPTCHA 控件分配的公开密钥,通常出现在三处:

方式一 —— 控件容器上的 data-sitekey 属性:

<div class="g-recaptcha" data-sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"></div>

方式二 —— reCAPTCHA iframe 加载的 anchor URL:

https://www.google.com/recaptcha/api2/anchor?k=6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-&...

URL 中 k 参数的值就是 sitekey。

方式三 —— 页面 JavaScript 里的 grecaptcha.render() 调用:

grecaptcha.render('captcha-container', {
  sitekey: '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
  callback: onSuccess
});

pageurl 要填哪个地址

pageurl 必须是包含协议头的完整地址,例如:

https://staging.example.com/qa-login
  • 普通情况:控件和页面同域,直接用当前页面地址。
  • iframe 情况(最容易踩的坑):控件加载在另一个子域名的 iframe 里时,pageurl 要填 iframe 本身的 URL,不是父页面地址。

关键提示: sitekeypageurl 配对错误时,CaptchaAI 会返回 ERROR_BAD_TOKEN_OR_PAGEURL。排查任何其他问题之前,先确认这两个值。


四步搞定:提交 → 等待 → 轮询 → 注入

页面 → 提取 sitekey + pageurl
              ↓
   POST in.php(method=userrecaptcha)
              ↓
        拿到 captcha id
              ↓
        等待 15–20 秒
              ↓
   GET res.php(action=get, id=…)
        ↓                  ↓
  CAPCHA_NOT_READY     status=1 → token
   (等 5 秒重试)           ↓
                  注入到 g-recaptcha-response
                            ↓
                   触发表单提交 / callback
  1. 提交 —— POSThttps://ocr.captchaai.com/in.php,带 method=userrecaptchakeygooglekey(sitekey)、pageurl,返回 captcha id。
  2. 等待 —— 暂停 15–20 秒。reCAPTCHA v2 通常 60 秒内完成,成功率超过 99.5%。
  3. 轮询 —— GET https://ocr.captchaai.com/res.php,参数 action=getid=<captcha id>CAPCHA_NOT_READY 是正常状态,等 5 秒再试。
  4. 接收 —— 求解成功后返回较长的 reCAPTCHA 响应 token。
  5. 注入 —— 把 token 写入 g-recaptcha-response 文本域,或调用页面 callback。
  6. 提交 —— 触发目标页面期望的后续动作。

Python 代码:完整实现

import time
import requests

API_KEY = "YOUR_CAPTCHAAI_API_KEY"
SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
PAGE_URL = "https://staging.example.com/qa-login"

SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"


def solve_recaptcha_v2(api_key, sitekey, pageurl):
    """Submit a reCAPTCHA v2 challenge and return the solved token."""

    submit_resp = requests.post(
        SUBMIT_URL,
        data={
            "key": api_key,
            "method": "userrecaptcha",
            "googlekey": sitekey,
            "pageurl": pageurl,
            "json": 1,
        },
        timeout=30,
    )
    submit_resp.raise_for_status()
    submit_data = submit_resp.json()

    if submit_data.get("status") != 1:
        raise RuntimeError(f"Submit failed: {submit_data}")

    captcha_id = submit_data["request"]
    print(f"Task created - captcha id: {captcha_id}")

    time.sleep(15)

    for _ in range(60):  # 最多约 5 分钟轮询
        result_resp = requests.get(
            RESULT_URL,
            params={
                "key": api_key,
                "action": "get",
                "id": captcha_id,
                "json": 1,
            },
            timeout=30,
        )
        result_resp.raise_for_status()
        result_data = result_resp.json()

        if result_data.get("request") == "CAPCHA_NOT_READY":
            time.sleep(5)
            continue

        if result_data.get("status") == 1:
            return result_data["request"]

        raise RuntimeError(f"Polling error: {result_data}")

    raise TimeoutError("reCAPTCHA v2 solve timed out")


token = solve_recaptcha_v2(API_KEY, SITEKEY, PAGE_URL)
print(f"Solved token: {token[:80]}...")

这段代码做了什么:

  • method=userrecaptcha 提交 sitekey、pageurl 到 in.php
  • 等 15 秒再轮询,之后每 5 秒查一次 res.php
  • 求解完成返回 token 字符串,可直接注入。
  • 60 次轮询上限,避免死循环。

Node.js 代码:完整实现

const API_KEY = "YOUR_CAPTCHAAI_API_KEY";
const SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-";
const PAGE_URL = "https://staging.example.com/qa-login";

const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function solveRecaptchaV2(apiKey, sitekey, pageurl) {
  const submitResp = await fetch(SUBMIT_URL, {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
      key: apiKey,
      method: "userrecaptcha",
      googlekey: sitekey,
      pageurl: pageurl,
      json: "1",
    }),
  });

  const submitData = await submitResp.json();
  if (submitData.status !== 1) {
    throw new Error(`Submit failed: ${JSON.stringify(submitData)}`);
  }

  const captchaId = submitData.request;
  await sleep(15_000);

  for (let i = 0; i < 60; i++) {
    const resp = await fetch(
      `${RESULT_URL}?${new URLSearchParams({
        key: apiKey,
        action: "get",
        id: captchaId,
        json: "1",
      })}`,
    );
    const data = await resp.json();

    if (data.request === "CAPCHA_NOT_READY") {
      await sleep(5_000);
      continue;
    }
    if (data.status === 1) return data.request;
    throw new Error(`Polling error: ${JSON.stringify(data)}`);
  }
  throw new Error("reCAPTCHA v2 solve timed out");
}

const token = await solveRecaptchaV2(API_KEY, SITEKEY, PAGE_URL);
console.log("Token:", token.slice(0, 80) + "...");

拿到 token 之后怎么提交

拿到 token 只是一半,还要让页面确认 reCAPTCHA 已通过,常见做法有三种:

方式一 —— 直接写入 textarea:

document.getElementById("g-recaptcha-response").innerHTML = token;

方式二 —— 调用 reCAPTCHA 回调函数:

// 如果页面在 grecaptcha.render() 时设置了 callback
window.onCaptchaSolved(token);

方式三 —— 把 token 作为表单字段提交:

session.post(
    "https://staging.example.com/qa-login",
    data={
        "username": "...",
        "password": "...",
        "g-recaptcha-response": token,
    },
)

data-callback 用方式二,纯表单提交用方式一或方式三。


报错排查:5 个常见错误码

错误 含义 解决办法
ERROR_KEY_DOES_NOT_EXIST API Key 无效或拼写错误 captchaai.com/api.php 核对 Key
ERROR_ZERO_BALANCE 账户余额不足 在控制台充值或升级套餐
ERROR_BAD_TOKEN_OR_PAGEURL sitekey 或 pageurl 错误 重新核对两者,留意 iframe 场景
CAPCHA_NOT_READY 求解还在进行中 不是错误,等 5 秒再轮询
ERROR_NO_SLOT_AVAILABLE 当前线程已经用完 等队列释放,或升级到线程数更高的套餐

更多错误见 reCAPTCHA v2 常见求解错误


轮询节奏和并发怎么配置

配置项 建议值 原因
首次轮询等待 15 秒 太早查询只会拿到 CAPCHA_NOT_READY
轮询间隔 5 秒 间隔更短不会更快出结果
并发上限 按套餐线程数:BASIC 5、STANDARD 15、ADVANCE 50 超出线程数的任务排队等待
超时熔断 120 秒 避免任务卡住占线程

常见问题

CaptchaAI 支持 reCAPTCHA v3 或 Enterprise 版本吗?

支持,同样用 method=userrecaptcha,多传 version=v3+action(v3)或 enterprise=1(Enterprise),提交 → 轮询 → 注入流程不变。

为什么一直收到 ERROR_BAD_TOKEN_OR_PAGEURL?

最常见原因是 pageurl 填成了父页面地址,而控件实际在子域名 iframe 里——换成 iframe 自身的 URL 通常就能解决。

token 能存起来重复用吗?

不能。有效期约 2 分钟,多数站点一次性校验,拿到后要立刻注入并提交。

最低多少钱能测试完整流程?

BASIC 套餐每月 $15、5 线程,足够跑通本文测试;线程数决定并发量,接入量上来了再升级 STANDARD。


接下来

场景 参考文章
不确定版本 如何识别 reCAPTCHA 版本
排查报错 reCAPTCHA v2 常见求解错误
换类型接入 使用 API 解决 Cloudflare Turnstile使用 API 解决 GeeTest v3

现在就去 captchaai.com/api.php 申请 API Key,跑一遍上面的代码,几分钟拿到第一个 token。

该文章已禁用评论。