如何用 Node.js 识别 reCAPTCHA v2(含隐形版)

reCAPTCHA v2 有三种变体,它们都对应同一个 Node.js 方法。复选框是最简单的调用,隐形和 Enterprise 是第三个参数中的选项,两者可以组合。该包还自带 TypeScript 定义,因此这一切都不需要单独安装 @types 安装。
设置
npm install capskip
CapSkip 在你自己的机器上识别,因此必须先运行桌面应用。然后将客户端指向其设置中显示的端口:
const { CapSkip } = require('capskip');
const solver = new CapSkip({
apiKey: 'capskip', // any string when key validation is off
host: '127.0.0.1',
port: 8080,
recaptchaTimeout: 300, // seconds
});在生产环境中,从环境变量读取连接信息:
const solver = new CapSkip({
apiKey: process.env.CAPSKIP_API_KEY || 'capskip',
host: process.env.CAPSKIP_HOST || '127.0.0.1',
port: parseInt(process.env.CAPSKIP_PORT || '8080', 10),
});三种变体
| 变体 | 需添加的选项 |
|---|---|
| 复选框 | 无 |
| 隐形 | { invisible: 1 } |
| Enterprise | { enterprise: 1 } |
| 隐形 Enterprise | 两个键都加 |
// Checkbox: sitekey and page URL, nothing else.
const result = await solver.recaptcha(
'6Lc...YOUR_SITEKEY',
'https://example.com/login',
);
console.log(result.code); // g-recaptcha-response token
// Invisible.
await solver.recaptcha(sitekey, pageUrl, { invisible: 1 });
// Enterprise, and both at once.
await solver.recaptcha(sitekey, pageUrl, { enterprise: 1 });
await solver.recaptcha(sitekey, pageUrl, { enterprise: 1, invisible: 1 });注意参数的写法。Node 按位置传入 sitekey 和 URL,这与使用关键字的 Python SDK 不同。在两者之间移植代码时最容易出错。
TypeScript
类型定义随包一起提供,因此无需额外安装即可使用:
import { CapSkip, SolveResult } from 'capskip';
const solver = new CapSkip({ host: '127.0.0.1', port: 8080 });
const result: SolveResult = await solver.recaptcha(sitekey, pageUrl);SolveResult 带有 captchaId 和 code (适用于每种类型), userAgent 用于 Turnstile 的字段,以及三个 极验(GeeTest)字段。对于 reCAPTCHA,只有 code 才重要。
正确获取 sitekey
它是 data-sitekey 小组件容器上的属性,或者是传给 grecaptcha.render 的第一个参数——在隐形模式下没有可见容器时。它始终以 6L 开头,且是公开的。
URL 必须是小组件实际渲染所在的页面。传入表单处理程序或登录后的重定向,是 token 识别顺利却随后验证失败的常见原因。
提交 token
const body = new URLSearchParams({
'g-recaptcha-response': result.code,
username: '...',
password: '...',
});
const response = await fetch('https://example.com/login', {
method: 'POST',
body,
});token 只能使用一次,有效期约两分钟,因此请尽可能晚地识别。如果网站把 token 传给 JavaScript 回调而不是表单字段,识别方式相同但提交方式不同,我们的 reCAPTCHA v2 回调识别工具 页面有说明。
同时识别多个
const [a, b] = await Promise.all([ solver.recaptcha(sitekeyA, 'https://a.example.com'), solver.recaptcha(sitekeyB, 'https://b.example.com'), ]); console.log(a.code, b.code);
该包还导出了 AsyncCapSkip,但在 Node 中它只是 CapSkip的别名。Node 的 I/O 本就是异步的,每个方法都已返回 Promise,因此它的存在纯粹是为了让从 Python SDK 移植的代码继续工作。切换到它没有任何好处。
错误
const {
ValidationException, NetworkException, ApiException, TimeoutException,
} = require('capskip');
try {
const result = await solver.recaptcha(sitekey, pageUrl);
} catch (err) {
if (err instanceof ValidationException) { /* bad arguments */ }
else if (err instanceof NetworkException) { /* CapSkip not running */ }
else if (err instanceof ApiException) { /* bad sitekey or url */ }
else if (err instanceof TimeoutException) { /* polling timed out */ }
else throw err;
}这四个都继承自同一个基类,因此捕获 CapSkipError 即可在一个分支中处理全部情况,如果你更喜欢这样。
常见问题
我需要轮询结果吗?
不需要。客户端会在内部轮询,Promise 会在 token 完成时被解析。它在 250 毫秒后开始检查,并逐渐退避到 pollingInterval,这通常比手写的循环更快。
它支持 ESM 和 import 语法吗?
可以。这里的示例使用 require 以求简洁,但 import { CapSkip } from 'capskip' 同样可用,随附的 TypeScript 定义也会一起提供。
我可以将它与 Puppeteer 或 Playwright 一起使用吗?
可以。用此 SDK 识别出 token,然后用 page.evaluate 在提交前将其注入页面。我们的 Node.js 验证码识别 页面介绍了浏览器自动化方面的内容。
小结
一个方法、三种变体,通过 invisible 和 enterprise选择。参数是按位置传递的,token 会落在 result.code,以及 Promise.all 就是并发所需的全部,因为 AsyncCapSkip 在这里只是一个别名。
更完整的 Node 接口见 Node.js 验证码识别 页面,其他语言见 reCAPTCHA v2 识别 页面,还有一个 在线 v2 演示 可供测试。CapSkip 采用 本地验证码识别工具,因此不会按次识别收费。
