///
动态验证码参数:它们是什么,如何识别和提取。利用动态数据成功解决验证码问题
Ekaterina Yanchuk
Ekaterina Yanchuk
技术文章作者
June 9, 2026
12 分钟

 

如何处理 CAPTCHA 的动态参数:完整指南

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

dynamic-params.png

 

robots
立即开始自动化您的工作流 reCAPTCHA v2

验证码与网站的其他安全防护机制

 

如今,现代网站几乎离不开各种安全防护机制,例如 验证码(CAPTCHA)——用于验证访问者是否为真实用户,而非可能带来威胁的机器人。早期主要是文本验证码,需要在输入框中输入图片中的字符或回答简单问题。随着时间推移,用户验证与网站安全系统变得越来越复杂,使自动化程序更难以绕过。同时,开发者也尽量减少对真实用户的干扰,因此很多验证过程在后台自动完成,用户甚至不会察觉。

 

目前的验证方式不仅仅依赖单一测试,而是基于多种因素的综合分析:用户行为、浏览器特征、网络请求等。网站可能会检查 cookies、设备指纹、JavaScript 执行情况,并在检测到可疑行为时额外展示验证码。

 

什么是验证码的动态参数

 

另一层安全防护由所谓的 动态参数 提供。这些参数会在每次验证码请求时生成并变化。它们作为每次验证会话的唯一标识符,与静态参数(例如 sitekey)不同,静态参数保持不变,而动态参数会在每次请求时更新。这意味着自动化系统无法简单地重复使用之前获取的参数来通过验证。

 

这些措施如何防止机器人

 

每当用户请求验证码时,服务器都会生成一组新的数据(例如 challenge, context, token 等),这些数据对当前会话是唯一的。

这些参数可以防止答案被重复使用,并可能包含用户信息、会话信息以及时间戳。即使机器人能够解决一次验证码,也很难在不同动态参数的情况下重复该过程,这通常需要大量计算资源。

 

基于对会话数据和行为数据的分析,网站还可以识别机器人行为,并在不展示验证码的情况下临时阻止可疑设备。

这些机制的目标是确保只有真实用户能够通过“闸门”,而机器人会被阻止或大幅增加绕过难度。

 

验证码有哪些动态参数

 

验证码中的动态参数会根据所使用的解决方案、服务商以及具体的防护系统而有所不同。它们通常在会话期间或验证完成后生成。下面我们来了解这些主要类型:

  • Challenge(挑战)——本质上就是验证码本身,用户需要完成它以证明身份。它可以有多种形式,包括文本任务、图片选择或特定操作。Challenge 由服务器在页面加载时生成,并且对每个请求都是唯一的。用户完成 Challenge 后,服务器会验证答案,如果正确,则允许继续访问网站。
  • Token 用于验证用户会话并确认请求来自真实用户而非机器人。Token 可以在服务器端生成,并传递给客户端用于验证码流程中。通常 Token 在会话开始时或每次验证码请求时生成,并在验证码通过后发送回服务器进行验证。

除了 challenge 和 token 之外,还有一些针对不同验证码类型的附加参数,例如:

  • context(例如用于 AWS WAF)——包含与当前用户会话绑定的唯一数据。它通常在脚本 window.gokuProps 中生成:

    window.gokuProps = {
                "key":"",
                "iv":"",
                "context":""
            };     
  • geetest_challengechallenge(用于 GeeTest v.3)——用于将用户请求与特定验证会话关联的标识符。它通常通过如下 URL 生成(注意该链接包含时间戳以防止缓存):

    https://example.com/api/v1/gee-test/init-params?t=1730640766594  

在 GeeTest v.3 中还使用以下参数:

  • geetest_validate ——用于确认验证码已正确完成的代码。成功完成验证后生成,并证明验证已通过;
  • geetest_seccode ——额外的安全验证码,用于确认验证成功。
  • dataDome cookie(用于 DataDome)——由 DataDome 系统生成的 Cookie,用于追踪并检测自动化行为,并根据用户行为动态更新。
  • g-recaptcha-response(用于 reCAPTCHA)——验证码通过后生成的 token,用于提交到服务器进行验证。
  • cf_clearance(用于 Cloudflare 验证)——验证码通过后生成的 Cookie,用于访问受保护资源。

另外还需要提到以下参数:

  • s(或 sentinel/motionData)——可能包含鼠标移动与验证码交互的数据。
  • v(版本)——表示验证码版本,该值可能在服务器端更新,并且每个会话都需要对应的新版本值。

上述示例仅展示了部分会随会话变化的参数;实际上这些参数种类很多,并且不同验证码系统各不相同。了解它们的存在对于后续分析与成功处理验证码非常重要。

 

查找动态参数:使用开发者工具

重要:以下内容仅用于了解、测试以及对您拥有合法访问权限的自有网站、应用或资源进行自动化处理。

如果您使用验证码自动解决服务,例如 CapMonster Cloud,那么在其文档中与验证码类型相关的部分通常会说明哪些参数是动态的,以及它们在代码中的生成位置。所有这些信息用于提取参数值,并在后续通过服务完成验证码解决。同时,具备基础的 开发者工具 使用能力也非常重要,可以帮助快速定位所需参数。

首先,我们来看这些参数的主要生成方式:

1. 通过 JavaScript(客户端)

当您打开包含验证码的页面时,会加载一个脚本,用于追踪用户行为——鼠标移动、点击以及键盘输入等。JavaScript 会生成各种参数,包括部分元素与表单、临时验证窗口(例如 Cloudflare Challenge)、随机数、用户交互数据以及设备信息。随后这些数据会被加密或处理,并发送到服务器。

2. 通过 API(服务端)

在验证码请求处理过程中,服务器可能会附加一些参数,例如会话标识符或哈希值。同时 API 也可能返回用于创建新验证码会话的参数,这些参数会在服务器端为每次请求自动更新。

为了更直观理解,我们来看两个例子:一个是 Amazon 验证码通过 JavaScript 生成 context,另一个是 GeeTest v.3 通过 API 生成 challenge 参数。

Amazon(AWS WAF)

在这种验证码类型中,关键参数(包括会变化的 context)通过专用的客户端防护脚本加载:

AWS WAF example

可以通过 开发者工具 在目标页面的元素中找到该脚本。

 

GeeTest v.3

在这种情况下,验证码参数通过 API 生成,可以在浏览器开发者工具的 Network(网络)标签中追踪相关 URL:

geetest3-zh.png

同时还会生成时间戳,以确保该请求与特定时间绑定。

 

如何判断哪些参数是动态的?

 

可以通过分析浏览器与服务器之间的请求与响应来确定所需参数。以下是主要方法和步骤:

  • 开发者工具:
  1. 打开包含验证码的网页;
  2. 按 F12 并切换到 Network(网络)标签;
  3. 查找与验证码相关的请求(通常是验证码服务的接口,例如 api.geetest.com 等);
  4. 检查请求中传递的参数,例如 ?t=123456789123
  5. 对比多个请求;
  6. 多次刷新页面;
  7. 比较参数。如果每次请求的值都发生变化,则它们是动态参数;
  8. 查找 JavaScript 调用
  • DevToolsSourceElements 标签中查找已加载的脚本;
  • 找出诸如 timestamp, context, challenge 等参数的生成逻辑;
  • 搜索关键词:JavaScript 代码中通常包含生成动态参数的函数;
  1. 分析服务器请求。部分参数由服务器生成,这些数据必须保存并在后续请求中使用。如果请求顺序被破坏(例如使用过期的 cookies),服务器可能会拒绝验证。
  • 嗅探器与代理工具分析

这些工具(例如 Charles Proxy)可以用于分析请求、查找动态参数并测试其变化,从而理解其逻辑以及服务器如何处理修改后的请求。

这些工具的工作方式包括:

  • 工具会记录发送到验证码服务器的请求(例如包含 t, challenge, context 等参数)。
  • 分析请求头、URL 参数、请求体以及 cookies,以识别关键数据。
  • 修改参数(例如 token)以测试其对服务器响应的影响。
  • 测试服务器如何响应被修改后的数据。

 

使用 Charles Proxy 分析验证码参数的简要指南:

  1. 下载并安装 Charles Proxy
  2. 启用 通过代理进行 SSL 代理SSL Proxying Settings,并添加验证码相关域名。
  3. 启动 Charles 和加载验证码页面的浏览器。
  4. 进入页面并开始记录请求。
  5. Structure 标签中查找验证码服务的请求(例如 www.google.com/recaptcha/api.js)。
  6. 打开请求/响应并分析其中传递的参数(token、sitekey、challenge、cookies 等)。

Charles Proxy example

在 Charles Proxy 中分析验证码参数

 

使用自动化工具:Selenium、Puppeteer、Playwright

 

另一种分析验证码数据并结合其他工具实现自动化绕过的方法,是使用浏览器模拟器,例如 Selenium、Puppeteer 和 Playwright。

 

Selenium、Puppeteer 和 Playwright 的通用能力

 

自动化。这三种工具都允许控制浏览器,执行常规用户操作:点击、输入文本、页面跳转等。这一切都可以被自动化完成。

支持动态内容处理。Selenium、Puppeteer 和 Playwright 可以处理 JavaScript,从而能够解析页面中动态加载的元素。

测试。它们被广泛用于各种 Web 应用的自动化测试。

 

浏览器模拟器如何帮助识别动态内容?

 

元素等待。可以设置等待元素加载,从而在页面加载完成后再获取数据。

响应分析。可以拦截网络请求,查看来自 API 的数据变化。

脚本访问。通过内置功能(例如 Puppeteer),可以执行 JavaScript,从动态加载的元素中提取信息。

 

处理动态内容的方法与参数:

 

Selenium

DOM 元素捕获

使用 find_element_by_xpathfind_element_by_css_selector 方法来访问与验证码相关的值。

JavaScript 脚本

使用 driver.execute_script() 直接执行 JavaScript。

通过代理进行请求日志记录

集成 BrowserMob Proxy 用于分析网络流量。

可以提取请求头、请求体、令牌以及验证码参数。

 

Puppeteer

请求与响应拦截

使用 page.on('request')page.on('response') 捕获网络流量。

DOM 动态值

使用 page.evaluate() 等方法在页面级别分析参数。

Cookie 与 localStorage

使用 page.cookies()page.evaluate() 分析存储数据。

 

Playwright

网络请求

使用 page.on('request')page.on('response') 监控网络数据。

DOM 分析

使用 page.locator() 从页面元素中提取数据。

执行 JavaScript

使用 page.evaluate() 对脚本中的参数进行分析与提取。

 

使用 CapMonster Cloud

 

在你分析并找到所有必要的验证码参数之后,下一步就是使用 CapMonster Cloud 创建并向服务器发送任务,以自动完成验证码的解决。将该工具集成到你的代码中非常简单。该服务支持多种编程语言,例如 Python、JavaScript、C#。你只需要选择合适的语言并安装用于使用它的官方库即可。

 

CapMonster Cloud 在 Python 中的集成示例:

 

  1. 首先在 CapMonster Cloud 注册并获取用于访问服务的 API 密钥。
  2. 安装库

在 Python 中,通过 pip 安装官方库:

pip install capmonstercloudclient
  1. 在你的代码中创建一个验证码任务并获取结果。以下是 Python 上解决 reCAPTCHA v2 的示例:
# 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())
关于验证码类型及创建任务所需参数的详细信息,请参阅官方文档。
  1. 获取结果后,将其提交到需要验证的网页表单中。

 

动态参数提取与验证码解决示例

 

本节展示使用 JavaScript(Node.js)、Python 和 C# 提取动态参数以及解决不同类型验证码的示例。 
根据验证类型的不同,自动化可以使用 Selenium 或内置 HTTP 请求实现。

重要:在开始之前,请先查阅 CapMonster Cloud 文档中所有必要参数列表:

GeeTest v3

Cloudflare Challenge

AWS WAF

 

GeeTest v3(通过 API 获取动态参数):

 

该类型验证码包含用于向服务器发起请求所需的 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}");
    }
}

 


Cloudflare Challenge

 

在使用 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)));
    }
}

 


AWS WAF:

 

在 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);")

鼠标移动:可以使用 pyautoguiselenium-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 轮换以及用户行为模拟,可以帮助你绕过许多限制。

需要注意的是请求频率,并遵守网站使用规则,以确保自动化既高效又合规。祝你在项目实现和开发中取得成功! 
 

常见问题

动态 CAPTCHA 参数是每次 CAPTCHA 请求或用户会话重新生成的值。它们可能包括 token、challenge ID、context、rqdata 等,用于确认会话的唯一性并防止重复使用已解决的验证码结果。

静态参数(例如 sitekey)在同一个网站中保持不变,而动态参数会在每次请求时发生变化。这些动态值与特定用户会话以及 CAPTCHA 生成时间相关联。

主要目的是防止自动化攻击。即使机器人成功解决了一次 CAPTCHA,也无法重复使用该结果,因为服务器每次都要求新的参数。这大大增加了脚本化和重放攻击的难度。

最简单的方法是使用 DevTools 对比多个请求:

  • 打开包含 CAPTCHA 的页面
  • 进入 Network 面板
  • 多次刷新页面
  • 对比参数值

如果每次请求的值都不同,则说明它是动态参数。

这些工具可以自动处理 CAPTCHA,即使涉及动态参数,因为这些参数是在页面加载和会话初始化过程中生成的。

robots
立即开始自动化您的工作流 reCAPTCHA v2

NB: 请注意,本产品仅用于对您自身的网站以及您依法拥有访问权限的资源进行自动化测试。

ItGuy
geear
面向软件开发者的联盟计划
通过用户识别验证码的消费获取高达 30% 的返佣。
✅ 请求已发送
感谢您对我们的合作伙伴计划感兴趣!我们将在 7 个工作日内与您联系。
请求加入
填写表格以提交申请加入合作伙伴计划。
更多文章