跳转到主要内容
获取令牌时遇到问题吗
联系支持

Hunt

Hunt 验证码是一种用于博彩平台的反机器人系统,用于检测自动化行为。它会跟踪用户行为,并在检测到可疑活动时启动交互式验证。

注意!
  • 要完成此任务,请使用您自己的代理

  • 我们的解决系统有两种工作模式:生成 X-HD(指纹)验证码求解。如果您只需要生成 X-HD,请不要传递 data 参数。如果您需要解决验证码,请在 data 中传递目标网站在特定操作时生成的令牌(例如请求短信时)。

请求参数


重要提示:某些参数的值是动态的 — 它们会在每次渲染包含 Hunt 的页面时发生变化。
请在创建任务前立即提取这些参数,以避免在解决过程中出现错误。
自动提取参数的示例请参见章节 如何获取 meta.tokenHunt CAPTCHA 解决示例


type<string>required

CustomTask


class<string>required

HUNT


websiteURL<string>required

包含 Hunt 验证码的页面地址。


apiGetLib (在 metadata 内)<string>required

api.js 文件的完整链接。

示例: https://www.example.com/hd-api/external/apps/<hash>/api.js

请按以下格式传递: "apiGetLib":"https://example.com/hd-api/external/apps/a2157wab1045d68672a63557e0n2a77edbfd15ea/api.js"

您可以在包含 Hunt 验证码的页面中,通过 DevTools(NetworkElements 标签)找到该链接。 使用关键字搜索:hd-apiapi.js


data (在 metadata 内)<string>optional

当选择验证码求解模式时,需要传递 data(详见下文说明)。


userAgent<string>optional

浏览器的 User-Agent。
请仅传递来自 Windows 操作系统的最新 UA。目前为userAgentPlaceholder


proxyType<string>required

http - 常规 HTTP/HTTPS 代理;
https - 当 http 不可用时使用(某些自定义代理必填);
socks4 - SOCKS4 代理;
socks5 - SOCKS5 代理。


proxyAddress<string>required

代理 IP 地址(IPv4/IPv6)。禁止使用:

  • 透明代理
  • 本地机器代理


proxyPort<integer>required

代理端口


proxyLogin<string>required

代理登录名


proxyPassword<string>required

代理密码


该解决方案支持两种工作模式:

1. 生成 X-HD(指纹)

  • 在此模式下,您无需传递 data
  • 创建任务后,您将获得 X-HD —— 一个与您的 IP 绑定的唯一指纹,可用于后续向网站发送请求。

2. 验证码求解

  • 在此模式下,您需要在参数 data 中传递网站在特定操作时生成的令牌meta.token),例如在请求短信时。
  • 创建任务后,您将获得验证码解决结果,即一个可直接在网站上使用的令牌。

何时使用每种模式

场景是否需要传递 data
初始初始化
需要获取 X-HD
网站返回 Captcha error
已获得 meta.token

完整工作流程示例

  1. 创建任务 不传递 data
  2. 从我们的服务获取 X-HD
  3. 使用 X-HD 向网站发送请求
  4. 获取 meta.token
  5. 创建任务 并设置 data = meta.token
  6. 获取解决结果
  7. 将解决结果提交到网站
重要

如果更换代理,需要重新获取 X-HD。

模式 1:生成 X-HD

用于获取与 IP 绑定的 X-HD 令牌。

创建用于生成 X-HD 的任务方法

POST
https://api.capmonster.cloud/createTask

请求

{
"type": "CustomTask",
"class": "HUNT",
"websiteURL": "https://example.com",
"metadata": {
"apiGetLib": "https://example.com/hd-api/external/apps/a2157wab1045d68672a63557e0n2a77edbfd15ea/api.js"
},
"userAgent": "userAgentPlaceholder",
"proxyType": "http",
"proxyAddress": "8.8.8.8",
"proxyPort": 8080,
"proxyLogin": "proxyLoginHere",
"proxyPassword": "proxyPasswordHere"
}
}

响应

{
"errorId": 0,
"taskId": 407533072
}

模式 2:验证码求解

当网站返回 captcha 错误并提供 meta.token 后使用。

如何获取 meta.token

  1. 向网站发送请求(例如请求短信验证码)
  2. 获取 X-HD

  1. 网站返回:
{
"errors":[{"code":"113","title":"Captcha error"}],
"meta":{
"token":"SITE_META_TOKEN"
}
}

创建用于验证码求解的任务方法

需要将 meta.token 的值传递到 data 参数中。

POST
https://api.capmonster.cloud/createTask

请求

{
"type": "CustomTask",
"class": "HUNT",
"websiteUrl": "https://example.com",
"metadata": {
"apiGetLib": "https://example.com/hd-api/external/apps/a2157wab1045d68672a63557e0n2a77edbfd15ea/api.js",
"data": "kufyHK/s/jTNU...AfwIW", // META_TOKEN 的值
},
"userAgent": "userAgentPlaceholder",
"proxyType": "http",
"proxyAddress": "8.8.8.8",
"proxyPort": 8080,
"proxyLogin": "proxyLoginHere",
"proxyPassword": "proxyPasswordHere"
}

响应

{
"errorId": 0,
"taskId": 407533072
}

获取任务结果的方法

使用 getTaskResult 方法来获取 X-HD 指纹或 Hunt 验证码的解决结果。

注意!

solution.data.token 的值:

  • 在生成 X-HD 模式下 —— 这是 X-HD 令牌,需要在向目标网站发送请求时使用。

  • 在验证码求解模式下 —— solution.data.token 是验证码解决令牌,需要将其提交回网站以确认操作。

POST
https://api.capmonster.cloud/getTaskResult

请求

{
"clientKey":"API_KEY",
"taskId": 407533072
}

响应

{
"errorId": 0,
"status": "ready",
"solution": {
"data": {
"token": "6IyDCCpDdSK...YGs1Wug/z/kLNSpjewI="
}
}
}

Cookies 的使用

注意!

目标网站可能使用特殊的 cookies 来管理会话。如果这些 cookies 缺失或未随请求发送,服务器可能会拒绝请求或要求重新验证。

从网站获取的 cookies 示例:

platform_type=desktop; typeBetNames=full; _glhf=1234567890; coefview=0; visit=1-123abc012345d1be726746568edc62d9; fast_coupon=true;
v3fr=1; lng=en; flaglng=en; SESSION=12a3aea8cdcfdbb9e7df8ee99b526a84; auid=ab0dW2mqlz1Tjo2AAwplAg==; ggru=195; che_g=12abcede-691f-c7b2-d1e8-8488bc557d98

Cookies 的基本工作原理:

  1. 首先需要打开网站页面,或者向目标页面发送 GET 请求。这样服务器会初始化用户会话并设置必要的 cookies。

  2. 在响应中,服务器会通过 Set-Cookie 头返回 cookies。这些 cookies 可能包含会话 ID、安全参数以及反机器人相关数据。

  3. 需要保存这些 cookies,因为后续请求会使用它们来识别客户端。

  4. 在向网站 API 发送后续请求时,需要在 Cookie 请求头中将 cookies 发送回服务器,以便服务器确认该请求属于同一会话。

  5. 所有请求应在同一会话中完成,并使用相同的 IP 地址(或代理)User-Agent。否则服务器可能会将请求视为可疑并要求重新验证。

  6. 有时部分 cookies 是在客户端创建的(例如页面上的 JavaScript)。在自动化或测试过程中,可能需要直接从浏览器提取 cookies,或以类似方式生成这些 cookies。

Hunt CAPTCHA 解决示例

下面的示例展示了与使用 Hunt CAPTCHA 的网站交互的典型流程。代码演示了如何:

  • 打开网站页面以获取初始 cookies;
  • 生成可能在客户端创建的额外 cookies;
  • 通过 CapMonster Cloud 创建用于请求验证的 fingerprint(X‑HD)
  • 向网站 API 发送请求以触发某个操作(例如发送 SMS);
  • 将获取的数据传递给验证码识别服务;
  • 在获得验证码解决结果后,向 API 发送 最终请求 并附带所需参数。

同时,还需要使用 最新的 HTTP 请求头以及正确的 User-Agent

显示代码 (Node.js)
import { gotScraping } from "got-scraping";
import crypto from "crypto";

/* ================= CONFIG(建议存储在 .env 中) ================= */
// CapMonster Cloud API、网站以及用户数据的配置

const API_KEY = "YOUR_API_KEY"; // 您的 CapMonster Cloud API 密钥
const SOLVER_URL = "https://api.capmonster.cloud";

const BASE_URL = "https://example.com"; // 网站的基础 URL
const API_GET_LIB =
"https://example.com/hd-api/external/apps/a1047eab1035d58682a53557e0b2a75edbfd15fd/api.js"; // 网站的 api.js

const PHONE = "91123456789"; // 用于注册的电话号码(不包含国家代码)
const COUNTRY_CODE = "54"; // 国家代码

const UA = "userAgentPlaceholder"; // 请求使用的 User-Agent

/* ================= 代理设置 ================= */

const PROXY_HOST = "proxyAddress";
const PROXY_PORT = 8080;
const PROXY_USER = "proxyLogin";
const PROXY_PASS = "proxyPassword";

const PROXY = `http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}`;

/* ================= HEADERS ================= */
// HTTP 请求头
// htmlHeaders — 用于 GET 页面请求
// apiHeaders — 用于网站 API 请求

const htmlHeaders = {
accept:
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-encoding": "gzip, deflate, br, zstd",
"accept-language": "en-US,en;q=0.9,ru;q=0.8",
"cache-control": "no-cache",
pragma: "no-cache",
priority: "u=0, i",
"sec-ch-ua": `"Not:A-Brand";v="99", "Google Chrome";v="145", "Chromium";v="145"`,
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": `"Windows"`,
"sec-fetch-dest": "document",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "none",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
"user-agent": UA,
};

const apiHeaders = {
accept: "application/vnd.api+json",
"accept-encoding": "gzip, deflate, br, zstd",
"accept-language": "en-US,en;q=0.9,ru;q=0.8",
"cache-control": "no-cache",
pragma: "no-cache",
priority: "u=1, i",
"content-type": "application/vnd.api+json",
origin: BASE_URL,
referer: BASE_URL + "/", // 网站当前使用的 referer
"sec-ch-ua": `"Not:A-Brand";v="99", "Google Chrome";v="145", "Chromium";v="145"`,
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": `"Windows"`,
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"user-agent": UA,
"x-requested-with": "XMLHttpRequest",
};

/* ================= UTILS ================= */
// 辅助函数

const delay = (ms) => new Promise((r) => setTimeout(r, ms));

function randomString(len = 20) {
const chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let result = "";
for (let i = 0; i < len; i++) {
result += chars[Math.floor(Math.random() * chars.length)];
}
return result;
}

/* ================= CAPMONSTER CLOUD ================= */
// 创建任务并等待验证码解决结果

async function createTask(task) {
const { body } = await gotScraping.post(`${SOLVER_URL}/createTask`, {
json: { clientKey: API_KEY, task },
responseType: "json",
});

if (body.errorId !== 0)
throw new Error("createTask error: " + JSON.stringify(body));

return body.taskId;
}

async function waitResult(taskId) {
while (true) {
const { body } = await gotScraping.post(`${SOLVER_URL}/getTaskResult`, {
json: { clientKey: API_KEY, taskId },
responseType: "json",
});

if (body.status === "ready")
return body.solution?.token || body.solution?.data?.token;

await delay(3000);
}
}

/* ================= MAIN FLOW ================= */
// 带验证码的自动注册主流程

(async () => {
try {
// ---------------- STEP 1: 获取 cookies ----------------
console.log("STEP 1 — Getting cookies...");

const base = await gotScraping.get(
BASE_URL + "/registration?type=phone_reg", // 请替换为网站当前的注册页面
{
headers: htmlHeaders,
proxyUrl: PROXY,
},
);

// 保存服务器返回的 cookies
let cookies = (base.headers["set-cookie"] || [])
.map((c) => c.split(";")[0])
.join("; ");

// 生成客户端创建的额外 cookies
const che_g = crypto.randomUUID();
const ggru = randomString();

cookies += `; che_g=${che_g}`;
cookies += `; ggru=${ggru}`;

console.log("Cookies:", cookies);

// ---------------- STEP 2: 创建 fingerprint ----------------
console.log("\nSTEP 2 — Creating fingerprint...");

const fingerprintTaskId = await createTask({
type: "CustomTask",
class: "HUNT",
websiteURL: BASE_URL + "/",
userAgent: UA,
metadata: { apiGetLib: API_GET_LIB },
proxyType: "http",
proxyAddress: PROXY_HOST,
proxyPort: PROXY_PORT,
proxyLogin: PROXY_USER,
proxyPassword: PROXY_PASS,
});

const xhd = await waitResult(fingerprintTaskId);
console.log("X-HD:", xhd);

// ---------------- STEP 3: 发送 SMS 请求 ----------------
console.log("\nSTEP 3 — Trigger SMS...");

const smsResp = await gotScraping.post(
BASE_URL + "/web-api/api/web/registration/v2/sms", // 请替换为网站当前的 API endpoint
{
headers: { ...apiHeaders, cookie: cookies, "x-hd": xhd },
json: {
data: { attributes: { phone: PHONE, country_code: COUNTRY_CODE } },
},
proxyUrl: PROXY,
responseType: "json",
},
);

const metaToken = smsResp.body?.meta?.token;
if (!metaToken) {
console.log("SMS response:", smsResp.body);
throw new Error("meta.token not received");
}

console.log("meta.token:", metaToken);

// ---------------- STEP 4: 解决验证码 ----------------
console.log("\nSTEP 4 — Solving Hunt captcha...");

const solveTaskId = await createTask({
type: "CustomTask",
class: "HUNT",
websiteURL: BASE_URL + "/",
userAgent: UA,
metadata: { apiGetLib: API_GET_LIB, data: metaToken },
proxyType: "http",
proxyAddress: PROXY_HOST,
proxyPort: PROXY_PORT,
proxyLogin: PROXY_USER,
proxyPassword: PROXY_PASS,
});

const captchaToken = await waitResult(solveTaskId);
console.log("Captcha token:", captchaToken);

// ---------------- STEP 5: 发送最终请求 ----------------
console.log("\nSTEP 5 — Sending final request...");

const finalResp = await gotScraping.post(
BASE_URL + "/api/web/registration/v2/sms", // 请替换为网站当前的 API endpoint
{
headers: { ...apiHeaders, cookie: cookies, "x-hd": xhd },
body: JSON.stringify({
data: {
attributes: {
phone: PHONE,
country_code: parseInt(COUNTRY_CODE),
captcha: captchaToken,
},
},
}),
proxyUrl: PROXY,
},
);

console.log("\nFINAL RESPONSE HEADERS:", finalResp.headers);
console.log("\nFINAL RESPONSE BODY:", finalResp.body);
} catch (err) {
console.error("\nFATAL ERROR:");
console.error(err);
}
})();