Cloudflare Turnstile 是一种广泛使用的验证码替代方案,覆盖数百万网站。如果您使用 Node.js 并需要以编程方式绕过 Turnstile,本指南将展示如何通过 NSLSolver API 实现。
无需 puppeteer,无需无头浏览器,除了 Node.js 18+ 内置的 fetch() 外无需任何依赖。
前置条件
- •Node.js 18+(支持原生 fetch)
- •NSLSolver API 密钥(在 nslsolver.com 免费注册)
第一步:创建项目
创建新目录并初始化 Node.js 项目:
mkdir turnstile-solver && cd turnstile-solver
npm init -y无需安装额外包——我们使用内置的 fetch() API。
第二步:解决 Turnstile 质询
向 NSLSolver API 发送 POST 请求,包含目标站点的 Turnstile sitekey 和 URL:
const response = await fetch('https://api.nslsolver.com/solve', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.NSLSOLVER_API_KEY,
},
body: JSON.stringify({
type: 'turnstile',
site_key: '0x4AAAAAAXXXXXXXXXXXXXXX',
url: 'https://example.com/login',
}),
});
const data = await response.json();
console.log('Token:', data.token);API 同步响应,无需轮询。平均响应时间约 250ms。
第三步:使用令牌
将返回的令牌传入您向目标站点提交的表单或 API 调用中:
// Use the token in your form submission or API call
const result = await fetch('https://example.com/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: process.env.LOGIN_EMAIL,
password: process.env.LOGIN_PASSWORD,
'cf-turnstile-response': data.token,
}),
});完整示例
以下是一个独立脚本,可以直接保存并运行:
// solve-turnstile.mjs
// Run: NSLSOLVER_API_KEY=nsl_... node solve-turnstile.mjs
const API_KEY = process.env.NSLSOLVER_API_KEY;
const SITE_KEY = '0x4AAAAAAXXXXXXXXXXXXXXX';
const TARGET_URL = 'https://example.com/login';
async function solveTurnstile() {
const res = await fetch('https://api.nslsolver.com/solve', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY,
},
body: JSON.stringify({
type: 'turnstile',
site_key: SITE_KEY,
url: TARGET_URL,
}),
});
if (!res.ok) {
throw new Error(`Solve failed: ${res.status} ${await res.text()}`);
}
const { token } = await res.json();
console.log('Solved! Token:', token.slice(0, 40) + '...');
return token;
}
solveTurnstile().catch(console.error);Async/Await 辅助模式
将解决逻辑封装在可复用函数中,使代码更简洁:
async function withTurnstileToken(siteKey, url, callback) {
const res = await fetch('https://api.nslsolver.com/solve', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.NSLSOLVER_API_KEY,
},
body: JSON.stringify({ type: 'turnstile', site_key: siteKey, url }),
});
const { token } = await res.json();
return callback(token);
}
// Usage
await withTurnstileToken(
'0x4AAAAAAXXXXXXXXXXXXXXX',
'https://example.com/login',
async (token) => {
// your logic here
console.log('Got token, submitting form...');
}
);理解请求参数
/solve 接口接受一个简单的 JSON 请求体。对于 Turnstile,有三个字段需要关注:
site_key— 目标页面 HTML 中渲染的公开 Turnstile sitekey(以 0x4... 开头的值)。从 .cf-turnstile 元素的 data-sitekey 属性读取它。url— 小部件所在页面的完整 URL。Turnstile 会将令牌绑定到该主机,因此必须与您提交令牌的位置一致。action/cdata— 可选。如果网站为其小部件设置了自定义 action 或 cData,请传入相同的值,以便返回的令牌能在服务端通过校验。
Turnstile 检测的工作原理
Turnstile 运行一个轻量级、隐形的浏览器质询,对客户端进行指纹识别(canvas、时序和 JS 执行信号),并返回一个一次性令牌。由于这些检查在真实浏览器环境中运行,简单的 HTTP 客户端和大多数无头浏览器隐身补丁都会间歇性失败。NSLSolver 在受管浏览器集群中执行质询,只返回最终令牌,因此您的 Node.js 代码保持为一次普通的 fetch() 调用。
令牌是短期有效的——通常约 300 秒(5 分钟)且仅可使用一次。请在提交表单前立即解决小部件,并为每次尝试请求新的令牌,而不要跨请求缓存。
更喜欢 Python?同样的流程也适用于 requests 库—— 阅读 Python 教程.