Hunt

Hunt CAPTCHA is an anti-bot system used on betting platforms to detect automated activity. It monitors user behavior and, if suspicious actions are detected, triggers an interactive verification.
-
For this task, use your own proxies.
-
Our solving system has two operating modes: X-HD generation (fingerprint) and CAPTCHA solving. If you only want to generate X-HD, do not pass the
dataparameter. If you need to solve the CAPTCHA, pass the token that the target site provides during certain actions (for example, when requesting an SMS).
Request parameters
IMPORTANT: some parameter values are dynamic — they change with each render of the page using Hunt.
Extract them immediately before creating the task to avoid errors during solving.
See examples of automatic parameter extraction in the sections How to get meta.token and Example of solving Hunt CAPTCHA.
type<string>requiredCustomTask
class<string>requiredHUNT
websiteURL<string>requiredThe URL of the page where the Hunt CAPTCHA is located.
apiGetLib (inside metadata)<string>requiredThe full link to the api.js file.
Example:
https://www.example.com/hd-api/external/apps/<hash>/api.js
Pass it in the following format:
"apiGetLib":"https://example.com/hd-api/external/apps/a2157wab1045d68672a63557e0n2a77edbfd15ea/api.js"
You can find this link in DevTools (the Network or Elements tabs) on the page with the Hunt CAPTCHA.
Use keyword search such as: hd-api or api.js.
data (inside metadata)<string>optionalThe data parameter must be specified when using CAPTCHA solving mode (see details below).
userAgent<string>optionalBrowser User-Agent.
Provide only the current Windows UA: userAgentPlaceholder
proxyType<string>requiredhttp - regular HTTP/HTTPS proxy;
https - use if http doesn’t work (required for some custom proxies);
socks4 - SOCKS4 proxy;
socks5 - SOCKS5 proxy.
proxyAddress<string>requiredProxy IP address (IPv4/IPv6). Not allowed:
- Transparent proxies
- Local machine proxies
proxyPort<integer>requiredProxy port.
proxyLogin<string>requiredProxy login.
proxyPassword<string>requiredProxy password.
The solution supports two operating modes:
-
X-HD (fingerprint) generation
- In this mode, you do not pass the
dataparameter. - After creating the task, you will receive an X-HD — a unique fingerprint tied to your IP address, which can be used for subsequent requests to the website.
- In this mode, you do not pass the
-
CAPTCHA solving
- In this mode, you must pass a token (the value of
meta.token) in thedataparameter. This token is issued by the website during specific actions (for example, when requesting an SMS). - After creating the task, you will receive the CAPTCHA solution as a token ready to be used on the website.
- In this mode, you must pass a token (the value of
When to use each mode:
| Situation | Is data required? |
|---|---|
| Initial initialization | No |
| Need to obtain X-HD | No |
| Website returned Captcha error | Yes |
meta.token received | Yes |
Example of a complete workflow:
- Create a task without
data - Receive X-HD from our service
- Send a request to the website using X-HD
- Receive
meta.token - Create a task with
data = meta.token - Receive the solution
- Submit the solution to the website
If you change the proxy, you must obtain a new X-HD.
Mode 1. X-HD Generation
Used to obtain an X-HD token bound to the IP address.
Create task method for X-HD generation
https://api.capmonster.cloud/createTask
Request
{
"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"
}
Response
{
"errorId": 0,
"taskId": 407533072
}
Mode 2. CAPTCHA solving
Used after the website returns a captcha error and provides meta.token.
How to get meta.token
- Send a request to the website (for example, an SMS request).
- Receive X-HD.
-1-feced69f9da880f442fb82a0d025775d.png)
- The website responds with:
{
"errors": [{"code": "113", "title": "Captcha error"}],
"meta": {
"token": "SITE_META_TOKEN"
}
}
-cb52653b917e55094fa4dbc891cd1746.png)
Create task method for CAPTCHA solving
The value of meta.token must be passed in the data parameter.
https://api.capmonster.cloud/createTask
Request
{
"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 value
},
"userAgent": "userAgentPlaceholder",
"proxyType": "http",
"proxyAddress": "8.8.8.8",
"proxyPort": 8080,
"proxyLogin": "proxyLoginHere",
"proxyPassword": "proxyPasswordHere"
}
Response
{
"errorId": 0,
"taskId": 407533072
}
Get task result method
Use the getTaskResult method to obtain the X-HD fingerprint or the Hunt CAPTCHA solution.
The value of solution.data.token:
-
In X-HD generation mode — this is the X-HD token that must be used in requests to the target website.
-
In CAPTCHA solving mode —
solution.data.tokenis the solution token that must be sent back to the website to confirm the action.
https://api.capmonster.cloud/getTaskResult
Request
{
"clientKey": "API_KEY",
"taskId": 407533072
}
Response
{
"errorId": 0,
"status": "ready",
"solution": {
"data": {
"token": "6IyDCCpDdSK...YGs1Wug/z/kLNSpjewI="
}
}
}
Working with cookies
The target site may use special cookies to manage the session. If they are missing or not sent with requests, the server may reject the request or require re-verification.
Example of cookies received from the website:
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
General principle of working with cookies:
-
First, you need to open a page on the website or send a GET request to the required page. This allows the server to initialize a user session and set the necessary cookies.
-
In the response, the server sends cookies via the
Set-Cookieheader. These cookies may contain a session identifier, security parameters, and anti‑bot related data. -
The received cookies must be stored, as they are used to identify the client in subsequent requests.
-
When sending further requests to the site’s API, the cookies must be sent back to the server in the
Cookieheader so that the server understands the request belongs to the same session. -
All requests should be performed within the same session using the same IP address (or proxy) and User-Agent. Otherwise, the server may treat the request as suspicious and require additional verification.
-
Sometimes some cookies are created on the client side (for example, by JavaScript on the page). During automation or testing, it may be necessary to extract cookies directly from the browser or generate them in a similar way.
Example of solving Hunt CAPTCHA
The examples below demonstrate a typical interaction flow with a website that uses Hunt CAPTCHA. The code shows how to:
- obtain initial cookies by opening a page on the website;
- generate additional cookies that may normally be created on the client side;
- create a fingerprint (X‑HD) via CapMonster Cloud used by the website to verify requests;
- send a request to the website API to initiate an action (for example, sending an SMS);
- pass the received data to the captcha solving service;
- after receiving the solution, send a final request to the API with the required parameters.
It is also important to use up‑to‑date HTTP headers and a correct User-Agent.
- JavaScript
- Python
Show code (Node.js)
import { gotScraping } from "got-scraping";
import crypto from "crypto";
/* ================= CONFIG (recommended to store in .env) ================= */
// CapMonster Cloud API settings, target website settings, and user data
const API_KEY = "YOUR_API_KEY"; // Your CapMonster Cloud API key
const SOLVER_URL = "https://api.capmonster.cloud";
const BASE_URL = "https://example.com"; // Base URL of the website
const API_GET_LIB =
"https://example.com/hd-api/external/apps/a1047eab1035d58682a53557e0b2a75edbfd15fd/api.js"; // Website api.js
const PHONE = "91123456789"; // Phone number for registration (without country code)
const COUNTRY_CODE = "54"; // Country code
const UA = "userAgentPlaceholder"; // User-Agent for requests
/* ================= Proxy settings ================= */
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 request headers
// htmlHeaders — for GET page requests
// apiHeaders — for website API requests
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 + "/", // Actual referer from the website
"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 ================= */
// Helper functions
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 ================= */
// Creating a task and waiting for captcha solution
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 ================= */
// Main process of automatic registration with captcha
(async () => {
try {
// ---------------- STEP 1: Get cookies ----------------
console.log("STEP 1 — Getting cookies...");
const base = await gotScraping.get(
BASE_URL + "/registration?type=phone_reg", // Replace with the actual registration page from the website
{
headers: htmlHeaders,
proxyUrl: PROXY,
},
);
// Save cookies received from the server
let cookies = (base.headers["set-cookie"] || [])
.map((c) => c.split(";")[0])
.join("; ");
// Generate additional cookies that are created on the client side
const che_g = crypto.randomUUID();
const ggru = randomString();
cookies += `; che_g=${che_g}`;
cookies += `; ggru=${ggru}`;
console.log("Cookies:", cookies);
// ---------------- STEP 2: Create 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: Send request to trigger SMS ----------------
console.log("\nSTEP 3 — Trigger SMS...");
const smsResp = await gotScraping.post(
BASE_URL + "/web-api/api/web/registration/v2/sms", // Replace with the actual API endpoint from the website
{
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: Solve captcha ----------------
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: Final request ----------------
console.log("\nSTEP 5 — Sending final request...");
const finalResp = await gotScraping.post(
BASE_URL + "/api/web/registration/v2/sms", // Replace with the actual API endpoint from the website
{
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);
}
})();
Show Code
import requests
import uuid
import random
import string
import time
# ================= CONFIG (recommended to store in .env) =================
# CapMonster Cloud API settings, target website settings, and user data
API_KEY = "YOUR_CAPMONSTER_API_KEY" # Replace with your CapMonster Cloud API key
SOLVER_URL = "https://api.capmonster.cloud"
BASE_URL = "https://example.com" # Base URL of the website
API_GET_LIB = "https://example.com/hd-api/external/apps/c1e24d5857463de4393e3f1489b00ebd4495da64/api.js" # Replace with the actual api.js URL from the website
PHONE = "9102345678" # Phone number for registration (without country code)
COUNTRY_CODE = "7" # Country code
UA = "userAgentPlaceholder" # User-Agent
# ================= Proxy settings =================
PROXY_HOST = "proxyAdress"
PROXY_PORT = 8080
PROXY_LOGIN = "proxyLogin"
PROXY_PASSWORD = "proxyPassword"
PROXY = f"http://{PROXY_LOGIN}:{PROXY_PASSWORD}@{PROXY_HOST}:{PROXY_PORT}"
proxies = {
"http": PROXY,
"https": PROXY
}
# ================= HEADERS =================
# HTTP request headers
# html_headers — for regular GET page requests
# api_headers — for requests to the website API
html_headers = {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
"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
}
api_headers = {
"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 + "/en", # Replace with the actual referer from the website
"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 =================
# Helper functions
def delay(ms):
"""Pause in milliseconds"""
time.sleep(ms / 1000)
def random_string(length=20):
"""Generate a random string (letters + digits)"""
chars = string.ascii_letters + string.digits
return ''.join(random.choice(chars) for _ in range(length))
# ================= CAPMONSTER CLOUD =================
# Functions for working with CapMonster Cloud (creating tasks and waiting for captcha solutions)
def create_task(task):
"""Create a task in CapMonster Cloud"""
r = requests.post(
SOLVER_URL + "/createTask",
json={
"clientKey": API_KEY,
"task": task
}
)
data = r.json()
if data["errorId"] != 0:
raise Exception("createTask error: " + str(data))
return data["taskId"]
def wait_result(task_id):
"""Wait for the task solution"""
while True:
r = requests.post(
SOLVER_URL + "/getTaskResult",
json={
"clientKey": API_KEY,
"taskId": task_id
}
)
data = r.json()
if data["status"] == "ready":
solution = data.get("solution", {})
return solution.get("token") or solution.get("data", {}).get("token")
delay(3000)
# ================= SESSION =================
# Create a requests session to store cookies between requests
session = requests.Session()
# ================= MAIN =================
# Main process of automatic registration with captcha
try:
# ---------------- STEP 1: Get cookies ----------------
print("STEP 1 — Getting cookies")
r = session.get(
BASE_URL + "/en/registration?type=phone", # Replace with the actual registration page from the website
headers=html_headers,
proxies=proxies
)
# Save cookies received from the server
cookies = "; ".join([f"{c.name}={c.value}" for c in session.cookies])
# Generate additional cookies that are created on the client side
che_g = str(uuid.uuid4())
ggru = random_string()
cookies += f"; che_g={che_g}"
cookies += f"; ggru={ggru}"
print("Cookies:", cookies)
# ---------------- STEP 2: Create fingerprint ----------------
print("\nSTEP 2 — Creating fingerprint")
fingerprint_task = create_task({
"type": "CustomTask",
"class": "HUNT",
"websiteURL": BASE_URL + "/en/",
"userAgent": UA,
"metadata": {
"apiGetLib": API_GET_LIB
},
"proxyType": "http",
"proxyAddress": PROXY_HOST,
"proxyPort": PROXY_PORT,
"proxyLogin": PROXY_LOGIN,
"proxyPassword": PROXY_PASSWORD
})
# Get the result (X-HD) which is required for the website API
xhd = wait_result(fingerprint_task)
print("X-HD:", xhd)
# ---------------- STEP 3: Send request to trigger SMS ----------------
print("\nSTEP 3 — Trigger SMS")
sms_resp = session.post(
BASE_URL + "/web-api/api/web/registration/v2/sms", # Replace with the actual API endpoint from the website
headers={**api_headers, "cookie": cookies, "x-hd": xhd},
json={
"data": {
"attributes": {
"phone": PHONE,
"country_code": COUNTRY_CODE
}
}
},
proxies=proxies
)
print("Status:", sms_resp.status_code)
try:
sms_data = sms_resp.json()
except:
print("Server returned non JSON:")
print(sms_resp.text)
raise Exception("Invalid JSON response")
meta_token = sms_data.get("meta", {}).get("token")
if not meta_token:
print("SMS response:", sms_data)
raise Exception("meta.token not received")
print("meta.token:", meta_token)
# ---------------- STEP 4: Solve captcha ----------------
print("\nSTEP 4 — Solving captcha")
solve_task = create_task({
"type": "CustomTask",
"class": "HUNT",
"websiteURL": BASE_URL + "/en/",
"userAgent": UA,
"metadata": {
"apiGetLib": API_GET_LIB,
"data": meta_token
},
"proxyType": "http",
"proxyAddress": PROXY_HOST,
"proxyPort": PROXY_PORT,
"proxyLogin": PROXY_LOGIN,
"proxyPassword": PROXY_PASSWORD
})
captcha_token = wait_result(solve_task)
print("Captcha token:", captcha_token)
# ---------------- STEP 5: Final request ----------------
print("\nSTEP 5 — Final request")
final = session.post(
BASE_URL + "/web-api/api/web/registration/v2/sms", # Replace with the actual API endpoint from the website
headers={**api_headers, "cookie": cookies, "x-hd": xhd},
json={
"data": {
"attributes": {
"phone": PHONE,
"country_code": int(COUNTRY_CODE),
"captcha": captcha_token
}
}
},
proxies=proxies
)
print("\nFINAL STATUS:", final.status_code)
try:
print(final.json())
except:
print(final.text)
except Exception as e:
print("\nFATAL ERROR")
print(e)
