Dynamic CAPTCHA Parameters: What They Are, How to Identify and Extract Them. Successfully Solving CAPTCHAs with Dynamic Data
Nowadays, it is difficult to imagine modern web resources without certain protection mechanisms, such as CAPTCHA—designed to verify that a visitor is a real human and not a bot posing a potential threat. In the past, these were primarily text-based CAPTCHAs, where users needed to input characters from an image into a designated field or answer simple questions. Over time, user verification systems and website protection mechanisms have become more sophisticated to counter automated programs. Conversely, developers strive to minimize any inconvenience for real users, allowing the verification process to often occur in the background without user involvement.
Currently, verification relies not just on passing a specific test but on analyzing a wide range of factors: user behavior, browser characteristics, network requests, and more. Websites may inspect cookies, device fingerprints, JavaScript execution, and only display a CAPTCHA when suspicious activity is detected.
Another layer of protection is added by so-called dynamic parameters. These parameters are created and updated with each request to the CAPTCHA. They serve as unique identifiers for each verification session and, unlike static parameters (such as websitekey), which remain constant, dynamic parameters change with every CAPTCHA request. This means that an automated system cannot simply reuse previously obtained values to successfully pass the verification.
Every time a user requests a CAPTCHA, the server generates a new dataset (e.g., challenge, context, token, etc.), unique to that session.
These parameters prevent the reuse of responses and may include information about the user, session, or timestamps. Even if a bot manages to solve one CAPTCHA, repeating the same process with different dynamic parameters becomes challenging and requires significant computational resources.
By analyzing session and behavioral data, the website can identify bot activity and temporarily block suspicious devices without even issuing a CAPTCHA.
These measures ensure that only real users can pass through the "turnstile," while bots are blocked or face significant obstacles in solving the protection.
Changing captcha parameters differ depending on which solution and in general which vendor and which protection system is used. They are generated during the session or after completing it. Let's take a look at their main important types:
- A Challenge is, in fact, the captcha element itself, which the user must solve to confirm his identity. It can take a variety of forms, including text-based tasks, image selection, or performing certain actions. A challenge is created by the server when the page loads and is a unique challenge for each request. The user solves the Challenge, after which the server checks the answer and, if it is correct, allows the user to continue interacting with the site.
- Token is used to verify the user's session and confirm that the request is coming from a real user and not from a bot. Tokens can be created on the server side and transferred to the client for use in the captcha process. The token is usually generated at the beginning of the session or at each request for a captcha and after successfully passing the captcha is sent back to the server for verification.
In addition to challenge and token, there are additional parameters that can be specific to different types of captcha. Here are some of them:
- context (used, for example, in AWS WAF) - contains unique values tied to the current user session. Generated in the window.gokuProps:
window.gokuProps = {
"key":"",
"iv":"",
"context":""
};
- geetest_challenge or challenge (used in GeeTest v.3) is a captcha identifier that links a user's request to a specific verification session. It is generated in a URL that looks something like this (note that this link contains a timestamp to prevent the request from being cached):
https://example.com/api/v1/gee-test/init-params?t=1730640766594
GeeTest v.3 also uses the following parameters:
- geetest_validate – code that confirms that the captcha was solved correctly. Generated after a successful captcha has been solved and confirms that the check has been passed;
- geetest_seccode – An additional security code that confirms a successful solution.
- dataDomeCookie (used in DataDome) – cookies generated by the DataDome system to track and check the user for automated actions and updated in response to their behavior.
- g-recaptcha-response (used in ReCAPTCHA) – the token received after successfully passing the captcha is needed for further transfer to the server.
- cf_clearance (used in Cloudflare checks) – cookies that are generated after passing the captcha for successful access to the resource.
It is also worth mentioning such parameters as:
- s (or sentinel/motionData) – can contain data about mouse movements and interaction with the captcha..
- v (version) – Specifies the version of the captcha that can be updated on the server and requires an updated value for each session.
- rqdata – contains encrypted user session data.
The examples given reflect only a part of the parameters that change with each session; In fact, there are quite a few of them and for each type of check (captcha) they are different. Knowing about their presence is important for the subsequent analysis and successful solution of the captcha.
Find dynamic parameters, work with Developer Tools
If you use captcha solve services, for example, CapMonster Cloud, then in the documentation of these services, in the sections dedicated to captcha types, it is usually indicated which parameters are dynamic and where exactly in the code they are generated. All this is necessary in order to extract the values and subsequently use them to solve the captcha using the service. It is also useful to have basic skills in working with Developer Tools to quickly find the values of the necessary parameters.
First, let's define the main ways to generate such parameters:
- Using JavaScript (Client-side
When you open a page with a captcha, a script is loaded that tracks your actions – mouse movements, clicks, keystrokes. JavaScript generates parameters – some elements and forms, intermediate validation windows (as in the case of Cloudflare Challenge), random numbers, data about your interactions, and device information. This data is then encrypted or processed and sent to the server.
- Using API (server-side)
When processing a captcha request, the server can add useful parameters, such as session IDs or hashed values. The API can also return parameters that will be needed to create a new captcha session – they are updated on the server automatically for each attempt.
For clarity, let's consider both methods. As an example, let's take a captcha from Amazon with context generation via JavaScript and GeeTest v.3 with challenge key generation via API
Amazon (AWS WAF)
In this type of captcha, important parameters (including a changing context) are loaded through a special client protection script:

You can find it using the Developer Tools among the elements on the landing page.
Here, captcha parameters are generated through the API, you can track the required URL in requests in the Network tab:

A timestamp is also generated there so that the request is tied to a certain time.
You can determine the necessary parameters by analyzing requests and responses between the browser and the server. Here are the main ways and a step-by-step approach:
- Developer Tools:
- Open a web page with a captcha;
- Go to the "Network" tab;
- Find queries related to the captcha (usually these are requests to the captcha servers, for example, api.geetest.com, etc.);
- Check the parameters passed in these requests, for example: ?t=123456789123;
- Compare multiple queries;
- Refresh the page several times;
- Compare the parameters. If the values change between requests, they – are dynamic;
- Find JavaScript calls
– Look in DevTools under the "Sources" or "Elements" tab. Check which scripts are connected;
– Find parameter generation such as timestamp, context, challenge, etc.;
– Look for keywords: JavaScript code often uses functions to generate dynamic parameters;
9. Analyze server requests. Some parameters are generated by the server. This data must be saved and used in the next query. If the sequence of requests is broken (for example, obsolete cookies), the server may reject the check.
- Sniffers and proxy servers for analysis
These tools, such as Charles Proxy, allow you to intercept requests, find dynamic parameters, and test changes, help you understand their logic, and check how the server handles modified requests.
The work of these tools includes:
- The tools record requests to the captcha server (for example, with the parameters t, challenge, context).
- The headers, URL parameters, request body, and cookies are examined to identify key values.
- Changes parameters (e.g., tokens) to check their impact on the server's response.
- How the server reacts to changed data is tested.
A quick guide to using Charles Proxy to analyze captcha parameters:
- Download and install Charles Proxy.
- Enable SSL Proxying through Proxy → SSL Proxying Settings.... Add a captcha domain
- Launch Charles and the browser with the page where the captcha is loaded.
- Go to the page to start recording requests.
- In the Structure tab, find requests to CAPTCHA services (for example, www.google.com/recaptcha/api.js).
- Open requests/responses and examine the parameters passed in them (token, sitekey, challenge, cookies, etc.).
Another way to analyze captcha data and, in combination with other tools, automate their solving, is browser emulators – for example, Selenium, Puppeteer, and Playwright.
Automatization. All three tools allow you to manage browsers, perform common user actions: clicks, text input, page navigation, etc. All this can be done automated
Support for working with dynamic content. Selenium, Puppeteer, and Playwright can work with JavaScript, so you can handle dynamically loaded page elements.
Testing. They are widely used to automate the testing of various web applications.
Waiting for items. You can set up waiting for elements to load – this allows you to capture data after the page has finished loading.
Analysis of answers. Allow you to intercept network requests to see changes in the data that comes from the API.
Scripted access. Using built-in tools (such as Puppeteer), you can execute JavaScript to extract information from dynamically loaded elements.
Selenium
Intercepting DOM elements
Use the find_element_by_xpath or find_element_by_css_selector methods to access the values associated with the captcha.
Scripts JavaScript
Execute JavaScript directly with driver.execute_script().
Logging requests through proxies
Integration with BrowserMob Proxy to analyze network traffic.
You can extract headers, request bodies, tokens, and captcha parameters.
Puppeteer
Interception of requests and responses
Use page.on('request') and page.on('response') to capture network traffic.
Dynamic DOM values
Use methods such as page.evaluate() to analyze parameters at the page level.
Cookie and localStorage
Use page.cookies() or page.evaluate() to analyze storage.
Playwright
Network Requests
page.on('request') and page.on('response') to monitor network data.
Analysis DOM
page.locator() to extract data from elements.
Execution JavaScript
Use page.evaluate() to parse and extract parameters from scripts.
Using CapMonster Cloud
Once you have analyzed and found all the necessary captcha parameters, the next step is to use CapMonster Cloud to create and send the task to the server to solve the captcha automatically. Integrating this tool into your code is easy. It supports programming languages such as Python, JavaScript, C#, Go, and PHP. All you need to do is select the appropriate language and install the official library to use it.
- To get started, sign up for CapMonster Cloud and get an API key to access their service.
- Install the library
For Python, install the official library via pip:
pip install capmonstercloudclient
3. In your code, create a task to solve the captcha and get a solution. Python example:
import asyncio
from capmonstercloudclient import CapMonsterClient, ClientOptions
from capmonstercloudclient.requests import RecaptchaV2ProxylessRequest
client_options = ClientOptions(api_key=<YOUR_API_KEY>)
cap_monster_client = CapMonsterClient(options=client_options)
async def solve_captcha():
return await cap_monster_client.solve_captcha(recaptcha2request)
recaptcha2request = RecaptchaV2ProxylessRequest(websiteUrl="https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=high",
websiteKey="6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd")
responses = asyncio.run(solve_captcha())
print(responses)
4. After receiving the decision, send it to the web page in the form where confirmation is required.
5. You can set up proxies, use proxyless solutions, and other parameters depending on the type of captcha.
Tip: For complex captchas (e.g. DataDome or Geetest) use CustomTask
To demonstrate the examples, we will use the GeeTest v.3, Cloudflare Challenge, and Amazon (AWS WAF) test types in JavaScript, Python, and C# programming languages. To work with dynamic content, choose Selenium.
This type of captcha contains the dynamic parameters necessary to create a request to the CapMonster Cloud server. Parameters are generated through the API using a URL like this: https://example.com/api/v1/gee-test/init-params?t=${t}. At the same time, additional tools are not required for browser automation - you can get by with the built-in Fetch (for JavaScript) or the requests (for Python) and Newtonsoft.Json (for C#) libraries. A list of all parameters is given in the CapMonster Cloud documentation.
JavaScript
// Importing the necessary dependencies
const { CapMonsterCloudClientFactory, ClientOptions, GeeTestProxylessRequest } = require('@zennolab_com/capmonstercloud-client');
async function run() {
// Creating a client
CapMonster Cloud
const cmcClient = CapMonsterCloudClientFactory.Create(new ClientOptions({
clientKey: 'your_api_key', // Replace with your API key CapMonsterCloud
}));
// Get captcha parameters via API
const t = new Date().getTime();
const response = await fetch(`https://example.com/api/v1/gee-test/init-params?t=${t}`); // Get dynamic parameters for the GeeTest captcha through the API. Make sure you're using the right URL for your case
const data = await response.json();
const { challenge, gt } = data;
const geeTestProxylessRequest = new GeeTestProxylessRequest({
websiteURL: 'https://example.com', // URL of the page with the captcha
gt: gt, // gt parameter retrieved via API
challenge: challenge // Challenge parameter retrieved via API
});
const solutionResponse = await cmcClient.Solve(geeTestProxylessRequest);
if (!solutionResponse || !solutionResponse.solution) {
throw new Error('Captcha not solved.');
}
Python
# Importing the necessary dependencies
import requests
import asyncio
import time
from capmonstercloudclient import CapMonsterClient, ClientOptions
from capmonstercloudclient.requests import GeetestProxylessRequest
async def run():
# Creating a client CapMonster Cloud
client_options = ClientOptions(api_key='your_api_key') # Replace with your API key CapMonsterCloud
cmc_client = CapMonsterClient(options=client_options)
# Get captcha parameters through API
t = int(time.time() * 1000) # Get the current timestamp in milliseconds
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('Failed to get parameters for captcha.')
# Creating a request to solve the captcha
gee_test_proxyless_request = GeetestProxylessRequest(
websiteUrl='https://example.com', # URL of the page with the captcha
gt=gt,
challenge=challenge
)
# Sending a request for a captcha solution
solution_response = await cmc_client.solve_captcha(gee_test_proxyless_request)
if not solution_response or not solution_response:
raise ValueError('Captcha not solved.')
print('Captch solved:', solution_response)
asyncio.run(run())
C#
/ Importing the CapMonster Cloud library and the necessary dependencies
using Zennolab.CapMonsterCloud.Requests;
using Zennolab.CapMonsterCloud;
using Newtonsoft.Json;
class Program
{
static async Task Main(string[] args)
{
// Setting up a client with your CapMonster Cloud API key
var clientOptions = new ClientOptions
{
ClientKey = "your_api_key" // Replace with your CapMonster Cloud API key
};
// Creating a CapMonster Cloud client using the specified settings
var cmCloudClient = CapMonsterCloudClientFactory.Create(clientOptions);
// Creating an HTTP client to send requests
using var httpClient = new HttpClient();
// Get the current timestamp for the request
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
// Forming a URL for obtaining dynamic parameters of the GeeTest captcha
var requestUrl = $"https://example.com/api/v1/captcha/gee-test/init-params?t={timestamp}";
// Send a request and get a response in the form of a string
var response = await httpClient.GetStringAsync(requestUrl);
dynamic data = JsonConvert.DeserializeObject(response);
// Creating a query to solve the GeeTest captcha with the obtained parameters
var geetestRequest = new GeeTestProxylessRequest
{
WebsiteUrl = "https://example.com/demo/geetest", // URL of the page with the captcha
Gt = data.gt, // The gt parameter derived from the response
Challenge = data.challenge // The challenge parameter derived from the response
};
// Sending a request to solve a captcha and getting the result
var geetestResult = await cmCloudClient.SolveAsync(geetestRequest);
Console.WriteLine($"Captcha Solution:\nChallenge: {geetestResult.Solution.Challenge}\nValidate: {geetestResult.Solution.Validate}\nSecCode: {geetestResult.Solution.SecCode}");
}
}
To work with this type of check, you need to use browser emulators to correctly display dynamic content and open a special window for checking the Challenge Page. Dynamic parameters are generated via window.turnstile, and we'll intercept them using built-in JavaScript. These parameters are then used to form a request to the CapMonster Cloud server. Let's consider two ways – obtaining a token and a cf-clearance cookie, which can then be inserted into the browser, thereby confirming a successful decision. A list of all the necessary parameters is listed in the CapMonster Cloud documentation.
JavaScript
// Import the library CapMonster Cloud
const { Builder } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const { CapMonsterCloudClientFactory, ClientOptions, TurnstileRequest } = require('@zennolab_com/capmonstercloud-client');
(async function example() {
// Create a settings object for Chrome
const options = new chrome.Options();
// Creating and running a driver for Chrome Browser
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options) // Setting the settings for Chrome
.build();
let params = null; // Variable for storing captcha parameters
try {
while (!params) {
// Opening a page with a captcha
await driver.get('https://example.com'); // URL of the page with the captcha
// Executing JavaScript on the page to capture captcha parameters
await driver.executeScript(`
// Intercepting a call to the render function in a turnstile object to get parameters
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === 'render') {
// Overriding the render function to capture captcha parameters
return function(a, b) {
let p = {
websiteKey: b.sitekey, // Site key
websiteURL: window.location.href, // URL of the page with the captcha
data: b.cData,
pagedata: b.chlPageData,
action: b.action,
userAgent: navigator.userAgent
};
console.log(JSON.stringify(p)); // Output the parameters to the console for debugging
window.params = p; // Saving Parameters in a Global Variable
window.turnstileCallback = b.callback; // Save the callback function
return target.render.apply(this, arguments); // Calling the original render function
}
}
return target[prop]; // Return the rest of the object's properties
}
});
`);
// Getting parameters from the global variable window.params
params = await driver.executeAsyncScript(`
const callback = arguments[arguments.length - 1]; // Get a callback to complete
setTimeout(() => {
callback(window.params); // Passing parameters via callback
}, 5000);
`);
if (!params) {
console.log('Parameters are not received, reload the page...');
await driver.sleep(3000);
}
}
console.log('Options:', params); // Displaying the obtained parameters
// Creating a CapMonster Cloud client using an API key
const cmcClient = CapMonsterCloudClientFactory.Create(new ClientOptions({
clientKey: 'your_api_key', // Replace with your API key CapMonster Cloud
}));
// Creating a request for solving the Turnstile captcha with the received parameters
const turnstileRequest = new TurnstileRequest({
websiteURL: params.websiteURL,
websiteKey: params.websiteKey,
data: params.data,
action: params.action,
cloudflareTaskType: 'token',
pageAction: 'managed',
pageData: params.pagedata
});
// Sending a request for a captcha solution
const response = await cmcClient.Solve(turnstileRequest);
// Checking if the captcha is solved
if (!response || !response.solution) {
throw new Error('Captcha not solved.');
}
console.log('Captcha solved:', response.solution); // Displaying the solution of the captcha
// Executing JavaScript on the page to pass the received token to the callback functionю
await driver.executeScript(`
window.turnstileCallback('${response.solution.token}'); // Passing the captcha solution token to the callback function
`);
} catch (err) {
console.error('Error:', err);
} finally {
await driver.quit();
}
})();
Python
# Importing the necessary dependencies
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 TurnstileProxylessRequest
# Setting up CapMonsterCloud using an API key
client_options = ClientOptions(api_key="your_api_key") # Replace with your API key CapMonsterCloud
cap_monster_client = CapMonsterClient(options=client_options)
# Function for obtaining captcha parameters
async def get_turnstile_params(driver):
params = None # Variable for storing captcha parameters
while not params:
driver.get("https://example.com") # Open a web page with a captcha
# Execute JavaScript code to intercept the render function and extract parameters
driver.execute_script("""
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === 'render') {
// Overriding the render function to capture captcha parameters
return function(a, b) {
let p = {
websiteKey: b.sitekey, // Site key
websiteURL: window.location.href, // URL of the page with the captcha
data: b.cData,
pagedata: b.chlPageData,
action: b.action,
userAgent: navigator.userAgent
};
console.log(JSON.stringify(p));
window.params = p; // Saving Parameters to a Global Variable
window.turnstileCallback = b.callback; // Saving the callback function
return target.render.apply(this, arguments); // Call the original function render
};
}
return target[prop]; // Return the rest of the object's properties
}
});
""")
# Extracting Parameters from a Global Variable `window.params` through execute_async_script
params = driver.execute_async_script("""
const callback = arguments[arguments.length - 1]; // Get a callback to complete
setTimeout(() => {
callback(window.params); // Passing parameters via callback
}, 5000);
""")
if not params:
print("Parameters are not received, reload the page...")
await asyncio.sleep(3)
return params # Return the received parameters
async def solve_turnstile(params):
# Creating a request to solve a captcha using CapMonsterCloud
request = TurnstileProxylessRequest(
websiteURL=params["websiteURL"],
websiteKey=params["websiteKey"],
data=params["data"],
action=params["action"],
pageAction="managed",
cloudflareTaskType="token",
pageData=params["pagedata"],
userAgent=params["userAgent"]
)
# Send a request to solve the captcha and get a 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:
# Get the captcha parameters
params = await get_turnstile_params(driver)
print("Parameters received:", params)
# Solve the captcha and get a token
token = await solve_turnstile(params)
print("Captcha solved. Token:", token)
# Execute JavaScript to pass the token to the callback function
driver.execute_script(f"window.turnstileCallback('{token}');")
except Exception as e:
# We handle errors if they occur
print(f"Error: {e}")
finally:
await asyncio.sleep(5)
driver.quit()
asyncio.run(main())
C#
// Importing the necessary dependencies
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Zennolab.CapMonsterCloud;
using Zennolab.CapMonsterCloud.Requests;
class Program
{
static async Task Main(string[] args)
{
// CapMonster Cloud Settings Using API Key
var clientOptions = new ClientOptions
{
ClientKey = "your_api_key" // Replace with your CapMonster Cloud API key
};
// Creating a client to work with CapMonster Cloud
var cmCloudClient = CapMonsterCloudClientFactory.Create(clientOptions);
// ChromeDriver settings
var chromeOptions = new ChromeOptions();
// Initializing the Chrome Driver
using var driver = new ChromeDriver(chromeOptions);
// Getting captcha parameters
var paramsObtained = await GetTurnstileParams(driver);
Console.WriteLine("Parameters received: " + string.Join(", ", paramsObtained));
// Creating a captcha solution request
var turnstileRequest = new TurnstileProxylessRequest
{
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()
};
// Captcha solution using CapMonster Cloud
var turnstileResult = await cmCloudClient.SolveAsync(turnstileRequest);
Console.WriteLine("Captch solved. Token: " + turnstileResult.Solution.Value);
// Passing the token to the callback function on the page
((IJavaScriptExecutor)driver).ExecuteScript($"window.turnstileCallback('{turnstileResult.Solution.Value}');");
await Task.Delay(5000);
}
// Function for obtaining captcha parameters
static async Task<Dictionary<string, object>> GetTurnstileParams(IWebDriver driver)
{
Dictionary<string, object> paramsObtained = null; // Variable for storing parameters
while (paramsObtained == null) // Repeat until the parameters are obtained
{
driver.Navigate().GoToUrl("https://example.com"); // Open the page with the captcha
// Executing JavaScript to intercept captcha parameters
((IJavaScriptExecutor)driver).ExecuteScript(@"
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === 'render') {
// Overriding the render function to extract parameters
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; // Saving Parameters to a Global Variable
window.turnstileCallback = b.callback; // Saving the callback function
return target.render.apply(this, arguments); // Calling the original render function
};
}
return target[prop]; // Return the rest of the object's properties
}
});
");
// Extract the parameters from the global variable 'window.params' via ExecuteAsyncScript
paramsObtained = await Task.Run(() =>
{
return (Dictionary<string, object>)((IJavaScriptExecutor)driver).ExecuteAsyncScript(@"
const callback = arguments[arguments.length - 1]; // Callback to complete execution
setTimeout(() => {
callback(window.params); // Passing parameters via callback
}, 5000);
");
});
// If the parameters are not obtained, wait before trying again
if (paramsObtained == null)
{
Console.WriteLine("Parameters are not received, reload the page...");
await Task.Delay(3000);
}
}
return paramsObtained; // Return the received parameters
}
}
JavaScript
// Importing the necessary dependencies
const { Builder } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const { CapMonsterCloudClientFactory, ClientOptions, TurnstileRequest } = require('@zennolab_com/capmonstercloud-client');
(async function example() {
// Settings ChromeDriver
const options = new chrome.Options();
// Initialization WebDriver for sChrome
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();
let params = null; // Variable for storing captcha parameters
let htmlPageBase64 = ''; // Variable for storing the page in Base64 format
try {
while (!params) {
// Open the page with the captcha
await driver.get('https://example.com'); // Replace with your page URL
// Running a script to intercept the parameters of the Turnstile captcha
await driver.executeScript(`
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === 'render') {
// Overriding the render function to extract parameters
return function(a, b) {
let p = {
websiteKey: b.sitekey,
websiteURL: window.location.href
};
console.log(JSON.stringify(p));
window.params = p; // Saving Parameters to a Global Variable
return target.render.apply(this, arguments); //Calling the original render function
}
}
return target[prop]; // Return the rest of the object's properties
}
});
`);
// Extract the parameters using the 'window.params' global variable
params = await driver.executeAsyncScript(`
const callback = arguments[arguments.length - 1];
setTimeout(() => {
callback(window.params); // Return parameters via callback
}, 5000);
`);
if (!params) {
console.log('Parameters are not received, reload the page...');
await driver.sleep(3000); }
}
console.log('Captcha parameters:', params);
// Get the HTML code of the page and encode it in Base64
const pageSource = await driver.getPageSource();
htmlPageBase64 = Buffer.from(pageSource).toString('base64');
// CapMonster Cloud Client Provisioning
const cmcClient = CapMonsterCloudClientFactory.Create(new ClientOptions({
clientKey: 'your_api_key', // Replace with your CapMonster Cloud API key
}));
// Forming a request to solve the captcha
const turnstileRequest = new TurnstileRequest({
websiteURL: params.websiteURL,
websiteKey: params.websiteKey,
cloudflareTaskType: 'cf_clearance',
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
htmlPageBase64: htmlPageBase64,
proxyType: 'http',
proxyAddress: '8.8.8.8',
proxyPort: 8000,
proxyLogin: 'proxyLoginHere',
proxyPassword: 'proxyPasswordHere'
});
// Captcha solution using CapMonster Cloud
const response = await cmcClient.Solve(turnstileRequest);
if (!response || !response.solution) {
throw new Error('Captcha not solved.');
}
console.log('Captcha solved, cookie cf_clearance:', response.solution);
} catch (err) {
console.error('Error:', err);
} finally {
await driver.quit();
}
})();
Python
# Importing the necessary dependencies
import asyncio
import base64
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
# Setting up the CapMonster Cloud client
client_options = ClientOptions(api_key="your_api_key") # Replace with your CapMonsterCloud API key
cap_monster_client = CapMonsterClient(options=client_options)
# Function to get Turnstile parameters
async def get_turnstile_params(driver):
params = None
while not params:
# Loading the page with the captcha
driver.get("https://example.com") # Specify the URL of the page with the captcha
# Execute a script to intercept the Turnstile parameters
driver.execute_script("""
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === 'render') {
// Overriding the render method to extract parameters
return function(a, b) {
let p = {
websiteKey: b.sitekey,
websiteURL: window.location.href
};
console.log(JSON.stringify(p));
window.params = p; // Saving Parameters to a Global Variable
return target.render.apply(this, arguments);
};
}
return target[prop]; // Return the rest of the object's properties
}
});
""")
# Extracting parameters using an asynchronous script
params = driver.execute_async_script("""
const callback = arguments[arguments.length - 1];
setTimeout(() => {
callback(window.params || null); // Return parameters or null
}, 5000);
""")
if not params:
print("Parameters are not received, reload the page...")
await asyncio.sleep(3) # Waiting before trying again
return params
# Function for solving captchas
async def solve_turnstile(params, html_page_base64):
request = TurnstileRequest(
websiteURL=params["websiteURL"],
websiteKey=params["websiteKey"],
cloudflareTaskType="cf_clearance",
userAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
htmlPageBase64=html_page_base64,
proxyType="http",
proxyAddress="8.8.8.8",
proxyPort=8000,
proxyLogin="proxyLoginHere",
proxyPassword="proxyPasswordHere"
)
# Sending a request for a captcha solution
response = await cap_monster_client.solve_captcha(request)
print("Answer CapMonster:", response)
if "cf_clearance" not in response:
raise Exception("Captcha not solved.")
return response["cf_clearance"]
async def main():
chrome_options = Options()
driver = webdriver.Chrome(service=ChromeService(), options=chrome_options)
try:
# Get the Turnstile parameters
params = await get_turnstile_params(driver)
print("Captcha parameters received", params)
# Coding HTML pages in Base64
page_source = driver.page_source
html_page_base64 = base64.b64encode(page_source.encode("utf-8")).decode("utf-8")
print("The HTML of the page is encoded in Base64.")
# Solving the captcha
cf_clearance = await solve_turnstile(params, html_page_base64)
print("Captch solved. Cookie cf_clearance:", cf_clearance)
except Exception as e:
print(f"Error: {e}")
finally:
await asyncio.sleep(5)
driver.quit()
asyncio.run(main())
C#
// Importing the necessary dependencies
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Zennolab.CapMonsterCloud;
using Zennolab.CapMonsterCloud.Requests;
class Program
{
static async Task Main(string[] args)
{
// Client settings CapMonster Cloud
var clientOptions = new ClientOptions
{
ClientKey = "your_api_key" // Replace with your CapMonsterCloud API key
};
var cmCloudClient = CapMonsterCloudClientFactory.Create(clientOptions);
// Setting up ChromeDriver
var chromeOptions = new ChromeOptions();
using var driver = new ChromeDriver(chromeOptions);
try
{
// Getting Turnstile Parameters
var paramsObtained = await GetTurnstileParams(driver);
Console.WriteLine("Parameters received: " + string.Join(", ", paramsObtained));
// Creating a request to solve a captcha
var turnstileRequest = new TurnstileRequest
{
WebsiteUrl = paramsObtained["websiteURL"].ToString(),
WebsiteKey = paramsObtained["websiteKey"].ToString(),
CloudflareTaskType = "cf_clearance",
NoCache = false,
ProxyType = ProxyType.Http,
ProxyAddress = "8.8.8.8",
ProxyPort = 8000,
ProxyLogin = "proxyLoginHere",
ProxyPassword = "proxyPasswordHere",
PageData = paramsObtained["pagedata"].ToString(),
Data = paramsObtained["data"].ToString(),
HtmlPageBase64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(driver.PageSource)), // Encoding an HTML page
UserAgent = paramsObtained["userAgent"].ToString()
};
// sending a request to CapMonster Cloud
var turnstileResult = await cmCloudClient.SolveAsync(turnstileRequest);
Console.WriteLine("Captcha solved. Cookie cf_clearance: " + turnstileResult.Solution.Clearance);
// If necessary, add cf_clearance to browser cookies
// var cfClearance = turnstileResult.Solution.Clearance;
// driver.Manage().Cookies.AddCookie(new Cookie("cf_clearance", cfClearance));
// If you need a callback callback, make it through JavaScript
// ((IJavaScriptExecutor)driver).ExecuteScript($"window.turnstileCallback('{cfClearance}');");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
finally
{
await Task.Delay(5000);
driver.Quit();
}
}
// Function to get Turnstile parameters
static async Task<Dictionary<string, object>> GetTurnstileParams(IWebDriver driver)
{
Dictionary<string, object> paramsObtained = null;
while (paramsObtained == null)
{
// Opening the Turnstile page
driver.Navigate().GoToUrl("https://example.com"); // Specify a URL with a captcha
// Replacing the render method with JavaScript
((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,
pagedata: b.chlPageData,
data: b.cData,
userAgent: navigator.userAgent
};
console.log(JSON.stringify(p));
window.params = p;
window.turnstileCallback = b.callback; // Save the callback for a subsequent call
return target.render.apply(this, arguments);
};
}
return target[prop];
}
});
");
paramsObtained = await Task.Run(() =>
{
return (Dictionary<string, object>)((IJavaScriptExecutor)driver).ExecuteAsyncScript(@"
const callback = arguments[arguments.length - 1];
setTimeout(() => {
callback(window.params); // Return parameters if they exist
}, 5000);
");
});
if (paramsObtained == null)
{
Console.WriteLine("Parameters not received, page reload...");
await Task.Delay(3000);
}
}
return paramsObtained;
}
}
JavaScript
// Importing the necessary dependencies
const { Builder } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const { CapMonsterCloudClientFactory, ClientOptions, AmazonProxylessRequest } = require('@zennolab_com/capmonstercloud-client');
(async function run() {
// Settings for Chrome
const options = new chrome.Options();
// options.addArguments('--headless'); // Add if you want to run in the background
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();
const pageUrl = 'https://example.com'; // Provide the URL of the page with the CAPTCHA
await driver.get(pageUrl);
// Getting captcha parameters using JavaScript
const captchaParams = await driver.executeScript(() => {
const gokuProps = window.gokuProps || {}; // Get the gokuProps object if it exists
const scripts = Array.from(document.querySelectorAll('script')); // Collecting all the tags
<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"
};
});
console.log('Obtained parameters:', captchaParams);
// Setting up the CapMonster Cloud client
const cmcClient = CapMonsterCloudClientFactory.Create(new ClientOptions({
clientKey: 'your_api_key', // Replace with your API key
}));
// Creating a captcha solution request
const amazonProxylessRequest = new AmazonProxylessRequest({
websiteURL: pageUrl,
challengeScript: captchaParams.challengeScriptUrl,
captchaScript: captchaParams.captchaScriptUrl,
websiteKey: captchaParams.websiteKey,
context: captchaParams.context,
iv: captchaParams.iv,
cookieSolution: false, // If you want to receive a cookie, set it to true
});
try {
// Captcha Solution via CapMonster Cloud
const response = await cmcClient.Solve(amazonProxylessRequest);
if (!response?.solution) throw new Error('CAPTCHA not solved.');
console.log('CAPTCHA solved:', response.solution);
} catch (err) {
console.error('Error in solving CAPTCHA:', err);
} finally {
await driver.quit();
}
})()
.then(() => {
console.log('DONE');
process.exit(0);
})
.catch(err => {
console.error('ERROR:', err);
process.exit(1);
});
Python
# Importing Required Dependencies
import asyncio
from capmonstercloudclient import CapMonsterClient, ClientOptions
from capmonstercloudclient.requests import AmazonWafProxylessRequest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
CAPTCHA_URL = "https://example.com" # Enter the URL you want
# Configuring ChromeDriver
chrome_options = Options()
# chrome_options.add_argument('--headless') # Remove commenting for background work
driver = webdriver.Chrome(options=chrome_options)
def get_captcha_params():
"""
Get CAPTCHA parameters from the page via JavaScript.
"""
driver.get(CAPTCHA_URL)
captcha_params = driver.execute_script("""
const gokuProps = window.gokuProps || {}; // Get gokuProps with the
const scripts = Array.from(document.querySelectorAll('script')); // Everything on the page
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
# CapMonsterCloud Settings
client_options = ClientOptions(api_key="your_api_key") # Replace with your API key
cap_monster_client = CapMonsterClient(options=client_options)
async def solve_captcha(captcha_params):
"""
Create a request for CapMonsterCloud and send it to solve the captcha.
"""
amazon_waf_request = AmazonWafProxylessRequest(
websiteUrl=CAPTCHA_URL,
challengeScript=captcha_params["challengeScriptUrl"],
captchaScript=captcha_params["captchaScriptUrl"],
websiteKey=captcha_params["websiteKey"],
context=captcha_params["context"],
iv=captcha_params["iv"],
cookieSolution=False # If a cookie solution is required, specify True
)
return await cap_monster_client.solve_captcha(amazon_waf_request)
async def main():
try:
# Extracting captcha parameters
captcha_params = get_captcha_params()
print("Options CAPTCHA:", captcha_params)
# Captcha Solution
response = await solve_captcha(captcha_params)
print("Result of the solution CAPTCHA:", response)
except Exception as e:
print("An error has occurred:", e)
finally:
driver.quit()
asyncio.run(main())
C#
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Zennolab.CapMonsterCloud;
using Zennolab.CapMonsterCloud.Requests;
class Program
{
static async Task Main(string[] args)
{
const string CAPTCHA_URL = "https://example.com"; // URL with CAPTCHA
// ChromeDriver settings
var chromeOptions = new ChromeOptions();
// chromeOptions.AddArgument("--headless"); // Remove commenting for background work
using var driver = new ChromeDriver(chromeOptions);
// Extracting captcha parameters
var captchaParams = GetCaptchaParams(driver, CAPTCHA_URL);
// CapMonster Cloud Settings
var clientOptions = new ClientOptions
{
ClientKey = "your_api_key" // Replace with your CapMonster Cloud API key
};
var cmCloudClient = CapMonsterCloudClientFactory.Create(clientOptions);
// Creating a Request
var amazonWafRequest = new AmazonWafProxylessRequest
{
WebsiteUrl = CAPTCHA_URL,
ChallengeScript = captchaParams["challengeScriptUrl"],
CaptchaScript = captchaParams["captchaScriptUrl"],
WebsiteKey = captchaParams["websiteKey"],
Context = captchaParams["context"],
Iv = captchaParams["iv"],
CookieSolution = false
};
// Submit a Solution Request
var solveResult = await cmCloudClient.SolveAsync(amazonWafRequest);
// Output of results
Console.WriteLine("ExistingToken: " + solveResult.Solution.ExistingToken);
Console.WriteLine("CaptchaVoucher: " + solveResult.Solution.CaptchaVoucher);
}
private static Dictionary<string, string> GetCaptchaParams(IWebDriver driver, string url)
{
driver.Navigate().GoToUrl(url);
var jsExecutor = (IJavaScriptExecutor)driver;
// Executing JavaScript to extract parameters
var captchaParams = 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(script => script.src.includes('challenge.js'))?.src || 'Not found',
captchaScriptUrl: scripts.find(script => script.src.includes('captcha.js'))?.src || 'Not found'
};
") as IDictionary<string, object>;
return captchaParams.ToDictionary(k => k.Key, v => v.Value?.ToString() ?? "Not found");
}
}
Working with dynamic parameters and automatic captcha solving often comes with complications, such as blocks, captchas, or dynamically updated page elements. Below are practical tips for successfully solving such restrictions.
- Use Undetected ChromeDriver
Standard Selenium WebDriver identifiers are easily detected by security systems. To minimize the likelihood of blocking:
Install the undetected_chromedriver library. It automatically masks WebDriver usage:
pip install undetected-chromedriver
Example of use:
import undetected_chromedriver.v2 as uc
options = uc.ChromeOptions()
options.add_argument("--headless") # Run in the background
options.add_argument("--disable-blink-features=AutomationControlled")
driver = uc.Chrome(options=options)
driver.get("https://example.com")
print(driver.page_source)
driver.quit()
Enable headless browser mode to further reduce suspicion.
2. Emulation of user actions
A script that is too "robotic" can raise suspicions. Use the following techniques:
- Dynamic Delay: Insert random delay intervals between actions:
import time
import random
time.sleep(random.uniform(1, 3)) # 1 to 3 second delay
- Scrolling the page. Scrolling emulation makes the script look like a user:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
Mouse movement: Simulate mouse actions with libraries such as pyautogui or selenium-wire
3. Using proxy servers
Proxies help you avoid being blocked by IP address:
Use proxy rotation. Keep an eye on the proxy geography to match the region of the site:
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. Update user-agent and headers
options.add_argument("user-agent=Your User-Agent")
So, tips for long-term work without blocking:
- Avoid aggressive scraping.
- Use libraries that change behavior to differentiate themselves from other scripts.
- Use Headless Mode Carefully: Some Sites Recognize a "Headless" Browser.
Working with dynamic captcha parameters is an exciting process that allows you to better understand how web protection mechanisms work. In this article, we have analyzed the main points in detail: from how to identify and analyze dynamic parameters, to how to extract them and effectively solve captchas.
We also showed code examples in various programming languages so that you can easily learn how to extract the desired values and automate captcha solving with CapMonster Cloud.
We have not forgotten about the tools that will help you emulate user actions and work with proxy servers. Using solutions such as Selenium, Puppeteer, Playwright, Undetected ChromeDriver, high-quality proxies, User-Agent rotation, and user behavior emulation will give you the opportunity to solve many limitations.
At the same time, it is important to remember the frequency of requests and follow the rules for using web resources so that your automation is not only effective, but also ethical. Good luck in the implementation of your ideas and new projects!
Note: We'd like to remind you that the product is used for automating testing on your own websites and on websites to which you have legal access.