如何处理 CAPTCHA 的动态参数:完整指南
了解什么是 CAPTCHA 动态参数,如何识别和提取它们,以及如何处理带有变化数据的验证码。

如今,现代网站几乎离不开各种安全防护机制,例如 验证码(CAPTCHA)——用于验证访问者是否为真实用户,而非可能带来威胁的机器人。早期主要是文本验证码,需要在输入框中输入图片中的字符或回答简单问题。随着时间推移,用户验证与网站安全系统变得越来越复杂,使自动化程序更难以绕过。同时,开发者也尽量减少对真实用户的干扰,因此很多验证过程在后台自动完成,用户甚至不会察觉。
目前的验证方式不仅仅依赖单一测试,而是基于多种因素的综合分析:用户行为、浏览器特征、网络请求等。网站可能会检查 cookies、设备指纹、JavaScript 执行情况,并在检测到可疑行为时额外展示验证码。
另一层安全防护由所谓的 动态参数 提供。这些参数会在每次验证码请求时生成并变化。它们作为每次验证会话的唯一标识符,与静态参数(例如 sitekey)不同,静态参数保持不变,而动态参数会在每次请求时更新。这意味着自动化系统无法简单地重复使用之前获取的参数来通过验证。
每当用户请求验证码时,服务器都会生成一组新的数据(例如 challenge, context, token 等),这些数据对当前会话是唯一的。
这些参数可以防止答案被重复使用,并可能包含用户信息、会话信息以及时间戳。即使机器人能够解决一次验证码,也很难在不同动态参数的情况下重复该过程,这通常需要大量计算资源。
基于对会话数据和行为数据的分析,网站还可以识别机器人行为,并在不展示验证码的情况下临时阻止可疑设备。
这些机制的目标是确保只有真实用户能够通过“闸门”,而机器人会被阻止或大幅增加绕过难度。
验证码中的动态参数会根据所使用的解决方案、服务商以及具体的防护系统而有所不同。它们通常在会话期间或验证完成后生成。下面我们来了解这些主要类型:
除了 challenge 和 token 之外,还有一些针对不同验证码类型的附加参数,例如:
context(例如用于 AWS WAF)——包含与当前用户会话绑定的唯一数据。它通常在脚本 window.gokuProps 中生成:
window.gokuProps = {
"key":"",
"iv":"",
"context":""
}; geetest_challenge 或 challenge(用于 GeeTest v.3)——用于将用户请求与特定验证会话关联的标识符。它通常通过如下 URL 生成(注意该链接包含时间戳以防止缓存):
https://example.com/api/v1/gee-test/init-params?t=1730640766594 在 GeeTest v.3 中还使用以下参数:
另外还需要提到以下参数:
上述示例仅展示了部分会随会话变化的参数;实际上这些参数种类很多,并且不同验证码系统各不相同。了解它们的存在对于后续分析与成功处理验证码非常重要。
| 重要:以下内容仅用于了解、测试以及对您拥有合法访问权限的自有网站、应用或资源进行自动化处理。 |
如果您使用验证码自动解决服务,例如 CapMonster Cloud,那么在其文档中与验证码类型相关的部分通常会说明哪些参数是动态的,以及它们在代码中的生成位置。所有这些信息用于提取参数值,并在后续通过服务完成验证码解决。同时,具备基础的 开发者工具 使用能力也非常重要,可以帮助快速定位所需参数。
首先,我们来看这些参数的主要生成方式:
1. 通过 JavaScript(客户端)
当您打开包含验证码的页面时,会加载一个脚本,用于追踪用户行为——鼠标移动、点击以及键盘输入等。JavaScript 会生成各种参数,包括部分元素与表单、临时验证窗口(例如 Cloudflare Challenge)、随机数、用户交互数据以及设备信息。随后这些数据会被加密或处理,并发送到服务器。
2. 通过 API(服务端)
在验证码请求处理过程中,服务器可能会附加一些参数,例如会话标识符或哈希值。同时 API 也可能返回用于创建新验证码会话的参数,这些参数会在服务器端为每次请求自动更新。
为了更直观理解,我们来看两个例子:一个是 Amazon 验证码通过 JavaScript 生成 context,另一个是 GeeTest v.3 通过 API 生成 challenge 参数。
Amazon(AWS WAF)
在这种验证码类型中,关键参数(包括会变化的 context)通过专用的客户端防护脚本加载:

可以通过 开发者工具 在目标页面的元素中找到该脚本。
GeeTest v.3
在这种情况下,验证码参数通过 API 生成,可以在浏览器开发者工具的 Network(网络)标签中追踪相关 URL:

同时还会生成时间戳,以确保该请求与特定时间绑定。
可以通过分析浏览器与服务器之间的请求与响应来确定所需参数。以下是主要方法和步骤:
这些工具(例如 Charles Proxy)可以用于分析请求、查找动态参数并测试其变化,从而理解其逻辑以及服务器如何处理修改后的请求。
这些工具的工作方式包括:
使用 Charles Proxy 分析验证码参数的简要指南:

在 Charles Proxy 中分析验证码参数
另一种分析验证码数据并结合其他工具实现自动化绕过的方法,是使用浏览器模拟器,例如 Selenium、Puppeteer 和 Playwright。
自动化。这三种工具都允许控制浏览器,执行常规用户操作:点击、输入文本、页面跳转等。这一切都可以被自动化完成。
支持动态内容处理。Selenium、Puppeteer 和 Playwright 可以处理 JavaScript,从而能够解析页面中动态加载的元素。
测试。它们被广泛用于各种 Web 应用的自动化测试。
元素等待。可以设置等待元素加载,从而在页面加载完成后再获取数据。
响应分析。可以拦截网络请求,查看来自 API 的数据变化。
脚本访问。通过内置功能(例如 Puppeteer),可以执行 JavaScript,从动态加载的元素中提取信息。
DOM 元素捕获
使用 find_element_by_xpath 或 find_element_by_css_selector 方法来访问与验证码相关的值。
JavaScript 脚本
使用 driver.execute_script() 直接执行 JavaScript。
通过代理进行请求日志记录
集成 BrowserMob Proxy 用于分析网络流量。
可以提取请求头、请求体、令牌以及验证码参数。
请求与响应拦截
使用 page.on('request') 和 page.on('response') 捕获网络流量。
DOM 动态值
使用 page.evaluate() 等方法在页面级别分析参数。
Cookie 与 localStorage
使用 page.cookies() 或 page.evaluate() 分析存储数据。
网络请求
使用 page.on('request') 和 page.on('response') 监控网络数据。
DOM 分析
使用 page.locator() 从页面元素中提取数据。
执行 JavaScript
使用 page.evaluate() 对脚本中的参数进行分析与提取。
在你分析并找到所有必要的验证码参数之后,下一步就是使用 CapMonster Cloud 创建并向服务器发送任务,以自动完成验证码的解决。将该工具集成到你的代码中非常简单。该服务支持多种编程语言,例如 Python、JavaScript、C#。你只需要选择合适的语言并安装用于使用它的官方库即可。
在 Python 中,通过 pip 安装官方库:
pip install capmonstercloudclient# https://github.com/CapMonsterCloud/capmonsterclient-python
import asyncio
from capmonstercloudclient import CapMonsterClient, ClientOptions
from capmonstercloudclient.requests import RecaptchaV2Request
# from capmonstercloudclient.requests.baseRequestWithProxy import ProxyInfo # 如果计划使用代理,请取消注释
API_KEY = "YOUR_API_KEY" # 请填写您的 CapMonster Cloud API 密钥
async def solve_recaptcha_v2():
client_options = ClientOptions(api_key=API_KEY)
cap_monster_client = CapMonsterClient(options=client_options)
# 基础示例(无代理)
# CapMonster Cloud 会自动使用其代理
recaptcha2_request = RecaptchaV2Request(
websiteUrl="https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=high",
websiteKey="6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd"
)
# 使用自定义代理的示例
# 如果需要使用自己的代理,请取消以下注释
# proxy = ProxyInfo(
# proxyType="http",
# proxyAddress="123.45.67.89",
# proxyPort=8080,
# proxyLogin="username",
# proxyPassword="password"
# )
# recaptcha2_request = RecaptchaV2Request(
# websiteUrl="https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=high",
# websiteKey="6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd",
# proxy=proxy,
# userAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"
# )
# 如有需要可以检查余额
balance = await cap_monster_client.get_balance()
print("余额:", balance)
result = await cap_monster_client.solve_captcha(recaptcha2_request)
print("解决结果:", result)
asyncio.run(solve_recaptcha_v2())| 关于验证码类型及创建任务所需参数的详细信息,请参阅官方文档。 |
本节展示使用 JavaScript(Node.js)、Python 和 C# 提取动态参数以及解决不同类型验证码的示例。
根据验证类型的不同,自动化可以使用 Selenium 或内置 HTTP 请求实现。
重要:在开始之前,请先查阅 CapMonster Cloud 文档中所有必要参数列表: |
该类型验证码包含用于向服务器发起请求所需的 CapMonster Cloud 动态参数。参数通过 API 生成,使用如下形式的 URL:https://example.com/api/v1/gee-test/init-params?t=${t}。同时无需额外浏览器自动化工具 —— 可以直接使用内置 Fetch(Node.js)、Requests(Python)以及 Newtonsoft.Json (C#)。
Node.js
// https://github.com/CapMonsterCloud/capmonstercloud-client-js
// 导入必要的依赖
import { CapMonsterCloudClientFactory, ClientOptions, GeeTestRequest } from '@zennolab_com/capmonstercloud-client';
async function run() {
// 创建 CapMonster Cloud 客户端
const cmcClient = CapMonsterCloudClientFactory.Create(new ClientOptions({
clientKey: 'your_api_key', // 请替换为您的 CapMonsterCloud API 密钥
}));
// 通过 API 获取验证码参数
const t = new Date().getTime();
const response = await fetch(`https://example.com/api/v1/gee-test/init-params?t=${t}`); // 通过 API 获取 GeeTest 动态参数。请确保使用正确的 URL
const data = await response.json();
const { challenge, gt } = data;
const geeTestProxylessRequest = new GeeTestRequest({
websiteURL: "https://example.com", // 验证码页面 URL
gt: gt, // 从 API 获取的 gt 参数
challenge: challenge, // 从 API 获取的 challenge 参数
});
const solutionResponse = await cmcClient.Solve(geeTestProxylessRequest);
if (!solutionResponse || !solutionResponse.solution) {
throw new Error('验证码未解决。');
}
console.log('验证码已解决:', solutionResponse.solution);
}
run()
.then(() => {
console.log('完成');
process.exit(0);
})
.catch((err) => {
console.error(err);
process.exit(1);
});Python
# https://github.com/CapMonsterCloud/capmonsterclient-python
# 导入必要的依赖
import requests
import asyncio
import time
from capmonstercloudclient import CapMonsterClient, ClientOptions
from capmonstercloudclient.requests import GeetestRequest
async def run():
# 创建 CapMonster Cloud 客户端
client_options = ClientOptions(api_key='your_api_key') # 请替换为您的 CapMonsterCloud API 密钥
cmc_client = CapMonsterClient(options=client_options)
# 通过 API 获取验证码参数
t = int(time.time() * 1000) # 获取当前时间戳(毫秒)
response = requests.get(f'https://example.com/api/v1/gee-test/init-params?t={t}')
data = response.json()
challenge = data.get('challenge')
gt = data.get('gt')
if not challenge or not gt:
raise ValueError('无法获取验证码参数。')
# 创建验证码解决请求
gee_test_proxyless_request = GeetestRequest(
websiteUrl='https://example.com', # 验证码页面 URL
gt=gt,
challenge=challenge
)
# 发送验证码解决请求
solution_response = await cmc_client.solve_captcha(gee_test_proxyless_request)
if not solution_response or not solution_response:
raise ValueError('验证码未解决。')
print('验证码已解决:', solution_response)
asyncio.run(run())C#
// https://github.com/CapMonsterCloud/capmonstercloud-client-dotnet
// 导入 CapMonster Cloud 库及必要依赖
using Zennolab.CapMonsterCloud.Requests;
using Zennolab.CapMonsterCloud;
using Newtonsoft.Json;
class Program
{
static async Task Main(string[] args)
{
// 使用你的 CapMonster Cloud API 密钥配置客户端
var clientOptions = new ClientOptions
{
ClientKey = "your_api_key" // 将此处替换为你的 CapMonster Cloud API 密钥
};
// 使用指定配置创建 CapMonster Cloud 客户端
var cmCloudClient = CapMonsterCloudClientFactory.Create(clientOptions);
// 创建用于发送请求的 HTTP 客户端
using var httpClient = new HttpClient();
// 获取当前时间戳用于请求
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
// 构造用于获取 GeeTest 验证码动态参数的 URL
var requestUrl = $"https://example.com/api/v1/captcha/gee-test/init-params?t={timestamp}";
// 发送请求并以字符串形式获取响应
var response = await httpClient.GetStringAsync(requestUrl);
dynamic data = JsonConvert.DeserializeObject(response);
// 使用获取到的参数创建 GeeTest 验证码请求
var geetestRequest = new GeeTestRequest
{
WebsiteUrl = "https://example.com/demo/geetest", // 验证码页面 URL
Gt = data.gt, // 从响应中获取的 gt 参数
Challenge = data.challenge // 从响应中获取的 challenge 参数
};
// 发送验证码解决请求并获取结果
var geetestResult = await cmCloudClient.SolveAsync(geetestRequest);
Console.WriteLine($"验证码解决结果:\n挑战值 (Challenge): {geetestResult.Solution.Challenge}\n验证值 (Validate): {geetestResult.Solution.Validate}\n安全码 (SecCode): {geetestResult.Solution.SecCode}");
}
}
在使用 CapMonster Cloud 时,您可以选择两种方式来获取结果:token 或 cookie cf_clearance,它们可以用于后续对目标页面的请求,或注入到浏览器会话中。
在下面的示例中,我们将展示如何使用 Selenium 获取参数并生成解决方案以获取 token,而对于获取 cookie cf_clearance,我们将使用 HTTP 请求。
方法 1. Token
Node.js
// https://github.com/CapMonsterCloud/capmonstercloud-client-js
// 导入 CapMonster Cloud 库
import { Builder } from "selenium-webdriver";
import { Options } from "selenium-webdriver/chrome.js";
import { CapMonsterCloudClientFactory, ClientOptions, TurnstileRequest } from "@zennolab_com/capmonstercloud-client";
(async function example() {
// 创建 Chrome 配置对象
const options = new Options();
// 创建并启动 Chrome 浏览器驱动
const driver = await new Builder()
.forBrowser("chrome")
.setChromeOptions(options) // 设置 Chrome 配置
.build();
let params = null; // 用于存储验证码参数的变量
try {
while (!params) {
// 打开验证码页面
await driver.get(
"https://example.com/challenge-page",
); // 验证码页面 URL
// 在页面上执行 JavaScript 以捕获验证码参数
await driver.executeScript(`
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === 'render') {
return function(a, b) {
let p = {
websiteKey: b.sitekey,
websiteURL: window.location.href,
data: b.cData,
pagedata: b.chlPageData,
action: b.action,
userAgent: navigator.userAgent
};
console.log(JSON.stringify(p));
window.params = p;
window.turnstileCallback = b.callback;
return target.render.apply(this, arguments);
}
}
return target[prop];
}
});
`);
// 从 window.params 获取参数
params = await driver.executeAsyncScript(`
const callback = arguments[arguments.length - 1]; // 获取回调函数以完成执行
setTimeout(() => {
callback(window.params); // 通过回调返回参数
}, 5000);
`);
if (!params) {
console.log("未获取到参数,正在刷新页面...");
await driver.sleep(3000);
}
}
console.log("参数:", params); // 输出获取到的参数
// 使用 API 密钥创建 CapMonster Cloud 客户端
const cmcClient = CapMonsterCloudClientFactory.Create(
new ClientOptions({
clientKey: "YOUR_API_KEY", // 替换为你的 CapMonster Cloud API 密钥
}),
);
// 创建 Turnstile 验证码请求
const turnstileRequest = new TurnstileRequest({
websiteURL: params.websiteURL,
websiteKey: params.websiteKey,
data: params.data,
action: params.action,
cloudflareTaskType: "token",
pageAction: "managed",
pageData: params.pagedata,
});
// 发送验证码解决请求
const response = await cmcClient.Solve(turnstileRequest);
// 检查是否成功解决验证码
if (!response || !response.solution) {
throw new Error("验证码未解决。");
}
console.log("验证码已解决:", response.solution); // 输出验证码结果
// 在页面中执行 JavaScript,将 token 传入 callback 函数
await driver.executeScript(`
window.turnstileCallback('${response.solution.token}'); // 将验证码 token 传递给回调函数
`);
} catch (err) {
console.error("错误:", err);
} finally {
await driver.quit();
}
})();Python
# https://github.com/CapMonsterCloud/capmonsterclient-python
# 导入必要的依赖
import asyncio
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.chrome.options import Options
from capmonstercloudclient import CapMonsterClient, ClientOptions
from capmonstercloudclient.requests import TurnstileRequest
# 使用 API 密钥配置 CapMonsterCloud
client_options = ClientOptions(api_key="your_api_key") # 将其替换为你的 CapMonsterCloud API 密钥
cap_monster_client = CapMonsterClient(options=client_options)
# 用于获取验证码参数的函数
async def get_turnstile_params(driver):
params = None # 用于存储验证码参数的变量
while not params:
driver.get("https://example.com") # 打开带有验证码的网页
# 执行 JavaScript 代码以拦截 render 函数并提取参数
driver.execute_script("""
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === 'render') {
return function(a, b) {
let p = {
websiteKey: b.sitekey,
websiteURL: window.location.href,
data: b.cData,
pagedata: b.chlPageData,
action: b.action,
userAgent: navigator.userAgent
};
console.log(JSON.stringify(p));
window.params = p;
window.turnstileCallback = b.callback;
return target.render.apply(this, arguments);
};
}
return target[prop];
}
});
""")
# 通过 execute_async_script 从全局变量 window.params 获取参数
params = driver.execute_async_script("""
const callback = arguments[arguments.length - 1];
setTimeout(() => {
callback(window.params);
}, 5000);
""")
if not params:
print("未获取到参数,正在刷新页面...")
await asyncio.sleep(3)
return params # 返回获取到的参数
async def solve_turnstile(params):
# 创建用于解决验证码的请求(使用 CapMonsterCloud)
request = TurnstileRequest(
websiteURL=params["websiteURL"],
websiteKey=params["websiteKey"],
data=params["data"],
action=params["action"],
pageAction="managed",
cloudflareTaskType="token",
pageData=params["pagedata"],
userAgent=params["userAgent"]
)
# 发送验证码请求并获取 token
response = await cap_monster_client.solve_captcha(request)
return response["token"]
async def main():
chrome_options = Options()
driver = webdriver.Chrome(service=ChromeService(), options=chrome_options)
try:
# 获取验证码参数
params = await get_turnstile_params(driver)
print("已获取参数:", params)
# 解决验证码并获取 token
token = await solve_turnstile(params)
print("验证码已解决。Token:", token)
# 执行 JavaScript,将 token 传递给 callback 函数
driver.execute_script(f"window.turnstileCallback('{token}');")
except Exception as e:
# 处理可能发生的错误
print(f"错误: {e}")
finally:
await asyncio.sleep(5)
driver.quit()
asyncio.run(main())
C#
// https://github.com/CapMonsterCloud/capmonstercloud-client-dotnet
// 导入必要依赖
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Zennolab.CapMonsterCloud;
using Zennolab.CapMonsterCloud.Requests;
class Program
{
static async Task Main(string[] args)
{
// 使用 API 密钥配置 CapMonster Cloud
var clientOptions = new ClientOptions
{
ClientKey = "your_api_key" // 将其替换为你的 CapMonster Cloud API 密钥
};
// 创建 CapMonster Cloud 客户端
var cmCloudClient = CapMonsterCloudClientFactory.Create(clientOptions);
// ChromeDriver 配置
var chromeOptions = new ChromeOptions();
// 初始化 Chrome 驱动
using var driver = new ChromeDriver(chromeOptions);
// 获取验证码参数
var paramsObtained = await GetTurnstileParams(driver);
Console.WriteLine("已获取参数: " + string.Join(", ", paramsObtained));
// 创建验证码请求
var turnstileRequest = new TurnstileRequest
{
WebsiteUrl = paramsObtained["websiteURL"].ToString(),
WebsiteKey = paramsObtained["websiteKey"].ToString(),
Data = paramsObtained["data"].ToString(),
PageAction = paramsObtained["pageAction"].ToString(),
CloudflareTaskType = "token",
PageData = paramsObtained["pagedata"].ToString(),
UserAgent = paramsObtained["userAgent"].ToString()
};
// 使用 CapMonster Cloud 解决验证码
var turnstileResult = await cmCloudClient.SolveAsync(turnstileRequest);
Console.WriteLine("验证码已解决。Token: " + turnstileResult.Solution.Value);
// 将 token 传递到页面 callback 函数
((IJavaScriptExecutor)driver).ExecuteScript($"window.turnstileCallback('{turnstileResult.Solution.Value}');");
await Task.Delay(5000);
}
// 获取验证码参数的函数
static async Task<Dictionary<string, object>> GetTurnstileParams(IWebDriver driver)
{
Dictionary<string, object> paramsObtained = null; // 用于存储参数
while (paramsObtained == null) // 循环直到获取参数
{
driver.Navigate().GoToUrl("https://example.com"); // 打开验证码页面
// 执行 JavaScript 拦截验证码 render 并提取参数
((IJavaScriptExecutor)driver).ExecuteScript(@"
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === 'render') {
return function(a, b) {
let p = {
websiteURL: window.location.href,
websiteKey: b.sitekey,
data: b.cData,
pageAction: b.action,
pagedata: b.chlPageData,
userAgent: navigator.userAgent
};
console.log(JSON.stringify(p));
window.params = p;
window.turnstileCallback = b.callback;
return target.render.apply(this, arguments);
};
}
return target[prop];
}
});
");
// 从 window.params 获取参数
paramsObtained = await Task.Run(() =>
{
return (Dictionary<string, object>)((IJavaScriptExecutor)driver).ExecuteAsyncScript(@"
const callback = arguments[arguments.length - 1]; // 回调函数用于结束执行
setTimeout(() => {
callback(window.params); // 通过 callback 返回参数
}, 5000);
");
});
// 如果未获取到参数则等待重试
if (paramsObtained == null)
{
Console.WriteLine("未获取到参数,正在重新加载页面...");
await Task.Delay(3000);
}
}
return paramsObtained; // 返回获取到的参数
}
}
方法 2. Cookie cf_clearance
Node.js
// https://github.com/CapMonsterCloud/capmonstercloud-client-js
import { Buffer } from "buffer";
import {
CapMonsterCloudClientFactory,
ClientOptions,
TurnstileRequest,
} from "@zennolab_com/capmonstercloud-client";
import { ProxyAgent } from "undici";
async function main() {
const API_KEY = "YOUR_API_KEY_HERE";
const URL = "https://www.example.com/"; // 替换为需要的 URL
const cmcClient = CapMonsterCloudClientFactory.Create(
new ClientOptions({ clientKey: API_KEY }),
);
// ===== 代理 =====
const proxy = {
proxyType: "http",
proxyAddress: "PROXY_ADDRESS_HERE",
proxyPort: 1234,
proxyLogin: "PROXY_LOGIN_HERE",
proxyPassword: "PROXY_PASSWORD_HERE",
};
const proxyUrl = `http://${proxy.proxyLogin}:${proxy.proxyPassword}@${proxy.proxyAddress}:${proxy.proxyPort}`;
const dispatcher = new ProxyAgent(proxyUrl);
const userAgent =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36";
// ===== 1. 获取 HTML =====
const res = await fetch(URL, {
dispatcher,
headers: {
// 设置所需请求头
"User-Agent": userAgent,
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
},
});
const html = await res.text();
console.log("状态码:", res.status);
const htmlBase64 = Buffer.from(html, "utf-8").toString("base64");
// ===== 2. 向 CAPMONSTER CLOUD 发送请求 =====
const turnstileRequest = new TurnstileRequest({
websiteURL: URL,
websiteKey: "xxxxx",
cloudflareTaskType: "cf_clearance",
proxy,
htmlPageBase64: htmlBase64,
userAgent,
});
const result = await cmcClient.Solve(turnstileRequest);
const cookie = result.solution?.cf_clearance || result.solution;
console.log("cf_clearance:", cookie);
// ==========================
// 设置 COOKIE
// ==========================
const cookieHeader = `cf_clearance=${cookie}`;
// ===== 3. 携带 Cookie 重新请求 =====
const res2 = await fetch(URL, {
dispatcher,
headers: {
// 设置所需请求头
"User-Agent": userAgent,
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
Cookie: cookieHeader,
},
});
const html2 = await res2.text();
console.log("最终状态码:", res2.status);
console.log("最终 HTML 片段:\n", html2.slice(0, 800));
}
main().catch(console.error);Python
// https://github.com/CapMonsterCloud/capmonsterclient-python
import asyncio
import base64
import requests
from capmonstercloudclient import CapMonsterClient, ClientOptions
from capmonstercloudclient.requests import TurnstileRequest
from capmonstercloudclient.requests.baseRequestWithProxy import ProxyInfo # 使用 ProxyInfo
API_KEY = "YOUR_API_KEY_HERE" # 请填写你的 CapMonster Cloud API 密钥
async def solve_cf_clearance():
client_options = ClientOptions(api_key=API_KEY)
cap_monster_client = CapMonsterClient(options=client_options)
# 代理配置示例
proxy = ProxyInfo(
proxyType="http",
proxyAddress="PROXY_ADDRESS_HERE",
proxyPort=1234,
proxyLogin="PROXY_LOGIN_HERE",
proxyPassword="PROXY_PASSWORD_HERE"
)
# ===== 获取 HTML 页面并转换为 BASE64 =====
URL = "https://www.example.com"
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"
PROXY_URL = f"http://{proxy.proxyLogin}:{proxy.proxyPassword}@{proxy.proxyAddress}:{proxy.proxyPort}"
PROXY_DICT = {
"http": PROXY_URL,
"https": PROXY_URL
}
session = requests.Session()
session.proxies.update(PROXY_DICT)
# 设置必要的请求头
session.headers.update({
"User-Agent": UA,
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"sec-ch-ua": '"Chromium";v="148", "Google Chrome";v="148", "Not:A-Brand";v="99"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"'
})
# 第一次请求:获取带验证码的页面
resp = session.get(URL, verify=True, timeout=30)
print("初始状态码:", resp.status_code)
print("\n--- 原始页面片段 ---")
print(resp.text[:800])
print("\n----------------------------------\n")
html_base64 = base64.b64encode(resp.content).decode()
# ===== BASE64 提取结束 =====
# Cloudflare cf_clearance 必须使用你的代理进行解决
turnstile_request = TurnstileRequest(
websiteURL=URL,
websiteKey="xxxxx",
cloudflareTaskType="cf_clearance",
htmlPageBase64=html_base64,
userAgent=UA,
proxy=proxy
)
# 如有需要,可以检查余额
balance = await cap_monster_client.get_balance()
print("余额:", balance)
result = await cap_monster_client.solve_captcha(turnstile_request)
print("解决结果:", result)
# 从结果中获取 cf_clearance
cf_clearance_cookie = result.get("gRecaptchaResponse") or result.get("cf_clearance")
print("cf_clearance:", cf_clearance_cookie)
# 将 cf_clearance 写入 session cookie
session.cookies.set("cf_clearance", cf_clearance_cookie)
# 第二次请求(携带 cookie)
resp2 = session.get(URL, verify=True, timeout=30)
print("最终状态码:", resp2.status_code)
print("\n--- 最终页面片段 ---")
print(resp2.text[:800])
asyncio.run(solve_cf_clearance())
C#
// https://github.com/CapMonsterCloud/capmonstercloud-client-dotnet
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Zennolab.CapMonsterCloud;
using Zennolab.CapMonsterCloud.Requests;
class Program
{
static async Task Main(string[] args)
{
var API_KEY = "YOUR_API_KEY_HERE"; // 请替换为你的 CapMonster Cloud API 密钥
var URL =
"https://www.example.com";
// ===================== CAPMONSTER CLOUD 客户端 =====================
var cmCloudClient = CapMonsterCloudClientFactory.Create(
new ClientOptions
{
ClientKey = API_KEY
}
);
// ===================== 代理设置 =====================
var proxyHost = "YOUR_PROXY_ADDRESS_HERE";
var proxyPort = 1234;
var proxyUser = "YOUR_PROXY_LOGIN_HERE";
var proxyPass = "YOUR_PROXY_PASSWORD_HERE";
var proxy = new WebProxy(proxyHost, proxyPort)
{
Credentials = new NetworkCredential(proxyUser, proxyPass)
};
// ===================== HTTP 客户端 =====================
var handler = new HttpClientHandler
{
Proxy = proxy,
UseProxy = true,
UseCookies = true,
CookieContainer = new CookieContainer()
};
var http = new HttpClient(handler);
var userAgent =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36";
// 设置必要的请求头
http.DefaultRequestHeaders.UserAgent.ParseAdd(userAgent);
http.DefaultRequestHeaders.Accept.ParseAdd(
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
);
// ===================== 1. 初始请求 =====================
var response = await http.GetAsync(URL);
Console.WriteLine($"初始状态: {(int)response.StatusCode} {response.StatusCode}");
var html = await response.Content.ReadAsStringAsync();
Console.WriteLine(html.Substring(0, Math.Min(800, html.Length)));
var htmlBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(html));
// ===================== 2. 解决 CF Challenge =====================
var turnstileRequest = new TurnstileRequest
{
WebsiteUrl = URL,
WebsiteKey = "xxxxx",
CloudflareTaskType = "cf_clearance",
HtmlPageBase64 = htmlBase64,
UserAgent = userAgent,
Proxy = new ProxyContainer(
proxyHost,
proxyPort,
ProxyType.Http,
proxyUser,
proxyPass
)
};
var result = await cmCloudClient.SolveAsync(turnstileRequest);
var cookie = result.Solution?.Clearance?.ToString();
Console.WriteLine("\ncf_clearance Cookie:");
Console.WriteLine(cookie);
if (string.IsNullOrEmpty(cookie))
{
Console.WriteLine("未获取到令牌");
return;
}
// ===================== 设置 COOKIE =====================
handler.CookieContainer.Add(
new Uri(URL),
new Cookie("cf_clearance", cookie)
);
// ===================== 3. 携带 COOKIE 的请求 =====================
var finalResponse = await http.GetAsync(URL);
Console.WriteLine($"最终状态: {(int)finalResponse.StatusCode} {finalResponse.StatusCode}");
var finalHtml = await finalResponse.Content.ReadAsStringAsync();
Console.WriteLine(finalHtml.Substring(0, Math.Min(800, finalHtml.Length)));
}
}
在 Amazon AWS WAF 中,使用 Selenium 来提取参数,并通过 CapMonster Cloud 获取解决方案。
Node.js
// https://github.com/CapMonsterCloud/capmonstercloud-client-js
// 导入必要依赖
import { Builder } from "selenium-webdriver";
import { Options } from "selenium-webdriver/chrome.js";
import {
CapMonsterCloudClientFactory,
ClientOptions,
AmazonRequest,
} from "@zennolab_com/capmonstercloud-client";
(async function run() {
// Chrome 设置
const options = new Options();
// options.addArguments("--headless=new");
// 创建并启动 ChromeDriver
const driver = await new Builder()
.forBrowser("chrome")
.setChromeOptions(options)
.build();
const pageUrl =
"https://www.example.com/amazon-captcha-page"; // 替换为 Amazon 验证码页面 URL
try {
// ===== 1. 打开页面 =====
await driver.get(pageUrl);
// ===== 2. 获取 AWS WAF 验证码参数 =====
const captchaParams = await driver.executeScript(() => {
const gokuProps = window.gokuProps || {};
const scripts = [...document.querySelectorAll("script")];
return {
websiteKey: gokuProps.key || null,
context: gokuProps.context || null,
iv: gokuProps.iv || null,
challengeScriptUrl:
scripts.find((s) => s.src.includes("challenge.js"))?.src || null,
captchaScriptUrl:
scripts.find((s) => s.src.includes("captcha.js"))?.src || null,
};
});
console.log("验证码参数:");
console.dir(captchaParams, { depth: null });
// ===== 3. 创建 CapMonster Cloud 客户端 =====
const cmcClient = CapMonsterCloudClientFactory.Create(
new ClientOptions({
clientKey: "YOUR_CAPMONSTER_API_KEY", // 替换为你的 CapMonster API 密钥
}),
);
// ===== 4. 创建 AWS WAF 验证码解决请求 =====
const request = new AmazonRequest({
websiteURL: pageUrl,
challengeScript: captchaParams.challengeScriptUrl,
captchaScript: captchaParams.captchaScriptUrl,
websiteKey: captchaParams.websiteKey,
context: captchaParams.context,
iv: captchaParams.iv,
cookieSolution: true,
});
// ===== 5. 发送请求到 CapMonster Cloud =====
const response = await cmcClient.Solve(request);
console.log("完整响应:");
console.dir(response, { depth: null });
if (!response?.solution) {
throw new Error("CapMonster Cloud 返回空解");
}
const solution = response.solution;
const wafToken = solution.cookies?.["aws-waf-token"];
if (!wafToken) {
throw new Error(
`未找到 AWS WAF Token:\n${JSON.stringify(solution, null, 2)}`,
);
}
console.log("AWS WAF Token:");
console.log(wafToken);
// ==========================
// 设置 COOKIE
// ==========================
await driver.manage().deleteCookie("aws-waf-token");
await driver.manage().addCookie({
name: "aws-waf-token",
value: wafToken,
path: "/",
secure: true,
});
const cookies = await driver.manage().getCookies();
console.log("设置后的 Cookies:");
console.dir(cookies, { depth: null });
// ===== 6. 刷新页面 =====
console.log("正在刷新页面...");
await driver.navigate().refresh();
// 等待页面加载完成
await driver.sleep(3000);
console.log("当前 URL:");
console.log(await driver.getCurrentUrl());
} catch (err) {
console.error("错误:");
console.error(err);
} finally {
// await driver.quit();
}
})()
.then(() => {
console.log("完成");
process.exit(0);
})
.catch((err) => {
console.error(err);
process.exit(1);
});Python
# https://github.com/CapMonsterCloud/capmonsterclient-python
# 导入必要依赖
import asyncio
from capmonstercloudclient import CapMonsterClient, ClientOptions
from capmonstercloudclient.requests import AmazonWafRequest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
CAPTCHA_URL = "https://www.example.com" # 指定目标 URL
# ===== CHROMEDRIVER 配置 =====
chrome_options = Options()
# chrome_options.add_argument('--headless') # 取消注释以启用后台运行
driver = webdriver.Chrome(options=chrome_options)
# ===== 获取验证码参数函数 =====
def get_captcha_params():
driver.get(CAPTCHA_URL)
captcha_params = driver.execute_script("""
const gokuProps = window.gokuProps || {};
const scripts = Array.from(document.querySelectorAll('script'));
return {
websiteKey: gokuProps.key || "Not found",
context: gokuProps.context || "Not found",
iv: gokuProps.iv || "Not found",
challengeScriptUrl: scripts.find(script => script.src.includes('challenge.js'))?.src || "Not found",
captchaScriptUrl: scripts.find(script => script.src.includes('captcha.js'))?.src || "Not found"
};
""")
return captcha_params
# ===== CAPMONSTER CLOUD 配置 =====
client_options = ClientOptions(api_key="YOUR_API_KEY") # 替换为你的 API 密钥
cap_monster_client = CapMonsterClient(options=client_options)
async def solve_captcha(captcha_params):
# ===== 创建 CapMonsterCloud 请求并发送验证码求解 =====
amazon_waf_request = AmazonWafRequest(
websiteUrl=CAPTCHA_URL,
challengeScript=captcha_params["challengeScriptUrl"],
captchaScript=captcha_params["captchaScriptUrl"],
websiteKey=captcha_params["websiteKey"],
context=captcha_params["context"],
iv=captcha_params["iv"],
cookieSolution=True
)
return await cap_monster_client.solve_captcha(amazon_waf_request)
async def main():
try:
# ===== 1. 获取 AWS WAF 验证码参数 =====
captcha_params = get_captcha_params()
print("验证码参数:", captcha_params)
# ===== 2. 发送请求到 CapMonster Cloud =====
response = await solve_captcha(captcha_params)
print("验证码求解结果:", response)
if not response or "cookies" not in response:
raise Exception("CapMonster 返回空结果")
solution = response
waf_token = solution["cookies"].get("aws-waf-token")
if not waf_token:
raise Exception(f"未找到 AWS WAF token:\n{solution}")
print("AWS WAF token:")
print(waf_token)
# ==========================
# 设置 COOKIE
# ==========================
# 删除旧 cookie
driver.delete_cookie("aws-waf-token")
# 添加新 cookie
driver.add_cookie({
"name": "aws-waf-token",
"value": waf_token,
"path": "/",
"secure": True
})
# 检查 cookies
cookies = driver.get_cookies()
print("插入后的 Cookies:")
print(cookies)
# ===== 3. 刷新页面 =====
print("正在刷新页面...")
driver.refresh()
# 等待加载
await asyncio.sleep(3)
print("当前 URL:")
print(driver.current_url)
except Exception as e:
print("发生错误:", e)
finally:
driver.quit()
asyncio.run(main())C#
// https://github.com/CapMonsterCloud/capmonstercloud-client-dotnet
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Zennolab.CapMonsterCloud;
using Zennolab.CapMonsterCloud.Requests;
class Program
{
static async System.Threading.Tasks.Task Main(string[] args)
{
const string CAPTCHA_URL = "https://www.example.com"; // 验证码页面 URL
// ===== CHROMEDRIVER 配置 =====
var chromeOptions = new ChromeOptions();
// chromeOptions.AddArgument("--headless"); // 如有需要可启用
using var driver = new ChromeDriver(chromeOptions);
try
{
// ===== 1. 获取 AWS WAF 验证码参数 =====
var captchaParams = GetCaptchaParams(driver, CAPTCHA_URL);
// ===== 2. 创建 CAPMONSTER CLOUD 客户端 =====
var clientOptions = new ClientOptions
{
ClientKey = "YOUR_API_KEY" // 替换为你的 API Key
};
var cmCloudClient = CapMonsterCloudClientFactory.Create(clientOptions);
// ===== 3. 创建 AWS WAF 验证码请求 =====
var amazonWafRequest = new AmazonWafRequest
{
WebsiteUrl = CAPTCHA_URL,
ChallengeScript = captchaParams["challengeScriptUrl"],
CaptchaScript = captchaParams["captchaScriptUrl"],
WebsiteKey = captchaParams["websiteKey"],
Context = captchaParams["context"],
Iv = captchaParams["iv"],
CookieSolution = true
};
// ===== 4. 发送请求到 CAPMONSTER CLOUD =====
var solveResult = await cmCloudClient.SolveAsync(amazonWafRequest);
Console.WriteLine("完整响应:");
Console.WriteLine(solveResult);
if (solveResult?.Solution?.Cookies == null)
throw new Exception("CapMonster 返回空结果");
var wafToken = solveResult.Solution.Cookies.ContainsKey("aws-waf-token")
? solveResult.Solution.Cookies["aws-waf-token"]
: null;
if (string.IsNullOrEmpty(wafToken))
throw new Exception("未找到 AWS WAF token");
Console.WriteLine("AWS WAF token:");
Console.WriteLine(wafToken);
// ==========================
// 设置 COOKIE
// ==========================
// 删除旧 cookie
try
{
driver.Manage().Cookies.DeleteCookieNamed("aws-waf-token");
}
catch { }
// 获取域名
var uri = new Uri(CAPTCHA_URL);
var domain = uri.Host;
// 添加新 cookie
driver.Manage().Cookies.AddCookie(new Cookie(
"aws-waf-token",
wafToken,
domain,
"/",
DateTime.Now.AddDays(1)
));
// 检查 cookies
var cookies = driver.Manage().Cookies.AllCookies;
Console.WriteLine("插入后的 Cookies:");
foreach (var cookie in cookies)
{
Console.WriteLine($"{cookie.Name} = {cookie.Value}");
}
// ===== 5. 刷新页面 =====
Console.WriteLine("正在刷新页面...");
driver.Navigate().Refresh();
Thread.Sleep(3000);
Console.WriteLine("当前 URL:");
Console.WriteLine(driver.Url);
}
catch (Exception ex)
{
Console.WriteLine("错误:");
Console.WriteLine(ex);
}
finally
{
driver.Quit();
}
}
private static Dictionary<string, string> GetCaptchaParams(IWebDriver driver, string url)
{
driver.Navigate().GoToUrl(url);
var jsExecutor = (IJavaScriptExecutor)driver;
var result = jsExecutor.ExecuteScript(@"
const gokuProps = window.gokuProps || {};
const scripts = Array.from(document.querySelectorAll('script'));
return {
websiteKey: gokuProps.key || 'Not found',
context: gokuProps.context || 'Not found',
iv: gokuProps.iv || 'Not found',
challengeScriptUrl: scripts.find(s => s.src.includes('challenge.js'))?.src || 'Not found',
captchaScriptUrl: scripts.find(s => s.src.includes('captcha.js'))?.src || 'Not found'
};
") as IDictionary<string, object>;
return result.ToDictionary(
k => k.Key,
v => v.Value?.ToString() ?? "Not found"
);
}
}
动态参数处理和自动化测试通常会伴随一些复杂问题,例如请求限制、额外验证或页面元素动态更新等。以下是一些实用建议,可帮助测试过程更加稳定和可预测。
1. 使用 Undetected ChromeDriver
某些网站可能会检测标准的 Selenium WebDriver 特征,并启用额外的验证机制。
为了更真实地模拟网站访问行为,可以使用 undetected_chromedriver,它有助于让浏览器更接近普通用户环境。
pip install undetected-chromedriver
示例用法:
import undetected_chromedriver.v2 as uc
options = uc.ChromeOptions()
options.add_argument("--headless") # 无头模式运行
options.add_argument("--disable-blink-features=AutomationControlled")
driver = uc.Chrome(options=options)
driver.get("https://example.com")
print(driver.page_source)
driver.quit()
2. 模拟用户行为
在测试过程中,建议模拟真实用户与网站的交互行为。不要连续过快执行操作,建议在操作之间加入随机延迟:
import time
import random
time.sleep(random.uniform(1, 3)) # 延迟1到3秒页面滚动:某些元素只有在滚动后才会加载:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")鼠标移动:可以使用 pyautogui 或 selenium-wire 等库模拟鼠标行为
3. 使用代理服务器
代理可以帮助避免 IP 被封锁:
使用代理轮换机制,并确保代理地理位置与目标网站区域一致:
from selenium.webdriver.common.proxy import Proxy, ProxyType
proxy = Proxy()
proxy.proxy_type = ProxyType.MANUAL
proxy.http_proxy = "http://username:password@proxy_ip:port"
capabilities = webdriver.DesiredCapabilities.CHROME
proxy.add_to_capabilities(capabilities)
driver = webdriver.Chrome(desired_capabilities=capabilities)
4. 更新 user-agent 和请求头
options.add_argument("user-agent=您的 User-Agent")
总结:长期稳定运行避免封锁的建议
动态参数与验证码处理是一个非常有趣的过程,它可以帮助更好地理解 Web 安全机制的工作方式。在本文中,我们详细讲解了关键内容:从如何识别与分析动态参数,到如何提取它们并高效解决验证码。
我们还提供了 JavaScript(Node.js)、Python 和 C# 的代码示例,帮助你更轻松地学习如何提取必要数据,并使用 CapMonster Cloud 自动化验证码处理。
同时也介绍了用于模拟用户行为和代理服务器的工具。使用 Selenium、Puppeteer、Playwright、Undetected ChromeDriver、优质代理、User-Agent 轮换以及用户行为模拟,可以帮助你绕过许多限制。
需要注意的是请求频率,并遵守网站使用规则,以确保自动化既高效又合规。祝你在项目实现和开发中取得成功!
NB: 请注意,本产品仅用于对您自身的网站以及您依法拥有访问权限的资源进行自动化测试。