Use Cases

使用 CaptchaAI 的验证码自动化脚本

验证码自动化脚本好不好用,关键不在于能不能跑通一次,而在于能不能塞进你现有的流程:提交任务、轮询结果、拿到 token,超时或报错时自动处理而不是卡死。下面 6 段脚本覆盖 reCAPTCHA v2、Turnstile、图片验证码、批量并发和 Node.js,基于 CaptchaAI API,改两个参数就能用。

验证码类型跟你要解决的网站在哪有关:

  • 国内站点:常见的是 GeeTest(极验)、网易易盾等本土验证码。
  • 出海或访问海外站点:以 reCAPTCHA、Cloudflare Turnstile 为主,这份脚本合集主要覆盖这类场景。reCAPTCHA 挂件依赖 Google 资源,国内网络下加载可能不稳定,跟脚本逻辑无关,建议先在能正常加载的环境里跑通再排查。

开始前需要准备什么

跑通这些脚本只需要三步:

  • Python 版本依赖 requestspip install requests(国内慢可加清华镜像 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests)。
  • Node.js 版本依赖 axios,把 API_KEY 换成你自己的即可运行。
  • 生产环境建议放进环境变量,不要硬编码在脚本里。

脚本 1:识别 reCAPTCHA v2 拿 token

提交与轮询逻辑

这段脚本把 site_key 和目标页面地址提交给 CaptchaAI,然后每 5 秒轮询一次结果,最多等 5 分钟(60 次),拿到 token 后打印出来,方便你接到后续的表单提交逻辑里。

#!/usr/bin/env python3
"""Solve reCAPTCHA v2 and print the token."""
import requests
import time
import sys

API_KEY = "YOUR_API_KEY"

def solve_recaptcha_v2(site_key, page_url):
    resp = requests.get("https://ocr.captchaai.com/in.php", params={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": site_key,
        "pageurl": page_url
    })
    if not resp.text.startswith("OK|"):
        print(f"Error: {resp.text}", file=sys.stderr)
        sys.exit(1)

    task_id = resp.text.split("|")[1]
    print(f"Task ID: {task_id}")

    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY, "action": "get", "id": task_id
        })
        if result.text == "CAPCHA_NOT_READY":
            print(".", end="", flush=True)
            continue
        if result.text.startswith("OK|"):
            print()
            return result.text.split("|")[1]
        print(f"\nError: {result.text}", file=sys.stderr)
        sys.exit(1)

    print("\nTimeout", file=sys.stderr)
    sys.exit(1)

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(f"Usage: {sys.argv[0]} <site_key> <page_url>")
        sys.exit(1)
    token = solve_recaptcha_v2(sys.argv[1], sys.argv[2])
    print(token)

跑起来:

python solve_recaptcha.py "6Le-wvkS..." "https://example.com/form"

脚本 2:识别 Cloudflare Turnstile

和脚本 1 的区别

逻辑跟脚本 1 几乎一样,只是把 method 换成 turnstile、参数名从 googlekey 换成 sitekey——这也是 CaptchaAI 区分验证码类型最直接的方式:不同验证码类型对应不同的 method 和参数组合。

#!/usr/bin/env python3
"""Solve Cloudflare Turnstile and print the token."""
import requests
import time

API_KEY = "YOUR_API_KEY"

def solve_turnstile(site_key, page_url):
    resp = requests.get("https://ocr.captchaai.com/in.php", params={
        "key": API_KEY,
        "method": "turnstile",
        "sitekey": site_key,
        "pageurl": page_url
    })
    task_id = resp.text.split("|")[1]

    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY, "action": "get", "id": task_id
        })
        if result.text == "CAPCHA_NOT_READY": continue
        if result.text.startswith("OK|"): return result.text.split("|")[1]
        raise Exception(result.text)
    raise TimeoutError()

token = solve_turnstile("0x4AAAAA...", "https://example.com")
print(token)

脚本 3:识别图片验证码(OCR)

两种图片来源

图片验证码不需要 site_key,直接把图片转成 base64 提交即可;脚本同时支持本地文件路径和图片 URL 两种输入,方便接入不同来源的图片。

#!/usr/bin/env python3
"""Solve an image CAPTCHA from a file or URL."""
import requests
import base64
import time
import sys

API_KEY = "YOUR_API_KEY"

def solve_image(image_source):
    # Load image
    if image_source.startswith("http"):
        img_data = requests.get(image_source).content
    else:
        with open(image_source, "rb") as f:
            img_data = f.read()

    img_b64 = base64.b64encode(img_data).decode()

    resp = requests.get("https://ocr.captchaai.com/in.php", params={
        "key": API_KEY,
        "method": "base64",
        "body": img_b64
    })
    task_id = resp.text.split("|")[1]

    for _ in range(30):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY, "action": "get", "id": task_id
        })
        if result.text == "CAPCHA_NOT_READY": continue
        if result.text.startswith("OK|"): return result.text.split("|")[1]
        raise Exception(result.text)
    raise TimeoutError()

if __name__ == "__main__":
    text = solve_image(sys.argv[1])
    print(text)

跑起来:

python solve_image.py captcha.png
python solve_image.py "https://example.com/captcha.jpg"

脚本 4:批量并发识别验证码

线程池和账号线程套餐是两回事

一次要处理几十上百个页面,逐个串行轮询会很慢。这段脚本用 ThreadPoolExecutor 并发提交任务,每个任务的成败单独记录,一个任务出错不会拖垮整批。

max_workers 是脚本进程内的线程池,跟 CaptchaAI 账号线程套餐是两回事——并发数超过账号线程上限时,多出来的请求只是排队等待。

#!/usr/bin/env python3
"""Solve multiple CAPTCHAs concurrently."""
import requests
import time
from concurrent.futures import ThreadPoolExecutor, as_completed

API_KEY = "YOUR_API_KEY"

def solve_one(site_key, page_url):
    resp = requests.get("https://ocr.captchaai.com/in.php", params={
        "key": API_KEY, "method": "userrecaptcha",
        "googlekey": site_key, "pageurl": page_url
    })
    task_id = resp.text.split("|")[1]

    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY, "action": "get", "id": task_id
        })
        if result.text == "CAPCHA_NOT_READY": continue
        if result.text.startswith("OK|"): return result.text.split("|")[1]
        raise Exception(result.text)
    raise TimeoutError()

def solve_batch(tasks, max_workers=5):
    """
    tasks: list of (site_key, page_url) tuples
    Returns: list of tokens
    """
    results = []
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = {
            executor.submit(solve_one, sk, url): (sk, url)
            for sk, url in tasks
        }
        for future in as_completed(futures):
            sk, url = futures[future]
            try:
                token = future.result()
                results.append({"url": url, "token": token, "status": "ok"})
            except Exception as e:
                results.append({"url": url, "error": str(e), "status": "failed"})
    return results

# Example
tasks = [
    ("6Le-wvkS...", "https://example.com/page1"),
    ("6Le-wvkS...", "https://example.com/page2"),
    ("6Le-wvkS...", "https://example.com/page3"),
]
results = solve_batch(tasks)
for r in results:
    print(f"{r['url']}: {r['status']}")

脚本 5:Node.js 通用识别脚本

什么时候选 Node.js 版本

Python 之外的通用 Node.js 实现:同一个 solve 函数靠 params 里的 method 字段切换验证码类型,reCAPTCHA、Turnstile 都能复用同一套提交轮询逻辑,不用为每种验证码单独写代码。

#!/usr/bin/env node
// Solve any CAPTCHA type from the command line
const axios = require("axios");

const API_KEY = "YOUR_API_KEY";

async function solve(params) {
  params.key = API_KEY;
  const submit = await axios.get("https://ocr.captchaai.com/in.php", {
    params,
  });
  if (!submit.data.startsWith("OK|")) throw new Error(submit.data);
  const taskId = submit.data.split("|")[1];

  while (true) {
    await new Promise((r) => setTimeout(r, 5000));
    const result = await axios.get("https://ocr.captchaai.com/res.php", {
      params: { key: API_KEY, action: "get", id: taskId },
    });
    if (result.data === "CAPCHA_NOT_READY") continue;
    if (result.data.startsWith("OK|")) return result.data.split("|")[1];
    throw new Error(result.data);
  }
}

// Usage examples:
// Solve reCAPTCHA v2
// solve({ method: "userrecaptcha", googlekey: "SITE_KEY", pageurl: "URL" })

// Solve Turnstile
// solve({ method: "turnstile", sitekey: "SITE_KEY", pageurl: "URL" })

module.exports = { solve };

查询余额脚本

为什么要先查余额

跑批量任务前,先确认账户余额够用;这段脚本直接调用 getbalance,一行就能看到当前余额。

#!/usr/bin/env python3
"""Check CaptchaAI account balance."""
import requests

API_KEY = "YOUR_API_KEY"

resp = requests.get("https://ocr.captchaai.com/res.php", params={
    "key": API_KEY,
    "action": "getbalance"
})
print(f"Balance: ${resp.text}")

常见问题

轮询一直返回 CAPCHA_NOT_READY 或者超时了怎么办?

这不是报错,说明任务还在排队或处理中,脚本按 5 秒自动重试,等待即可。长时间拿不到结果,多半是参数填错(site_key/pageurl 对应不上目标页面);in.php 直接返回错误而不是 OK|task_id,先查 API_KEY 或余额。

这几个脚本支持哪些验证码类型?能跑 GeeTest 吗?

脚本按 method 参数切换类型:userrecaptcha 覆盖 reCAPTCHA v2/v3,turnstile 对应 Turnstile,base64 对应图片/OCR 验证码;GeeTest v3 走 geetest 方法(参考 GeeTest v3 识别指南)。hCaptcha、FunCaptcha 目前不支持,不要在脚本里传这两类参数。

这些脚本能直接用在生产环境吗?

可以,但建议补充日志和重试策略;批量脚本已内置每个任务级别的错误处理,单个任务失败不会拖垮整批,方便定位问题。

运行这些脚本大概要花多少钱?

CaptchaAI 按线程数(并发)计费,不是按次收费——同一线程内解锁次数不限。BASIC 每月 $15 含 5 个线程,ENTERPRISE 每月 $300 含 200 个线程,具体以官方定价页为准。用上面的余额脚本随时看剩余额度。

相关指南

场景还涉及登录页验证码、机器人流水线,或者规模更大,可以接着看:

该文章已禁用评论。