Captcha types
reCAPTCHA v2#
Types RecaptchaV2TaskProxyless and RecaptchaV2Task.
| Parameter | Required | Type | Description |
|---|---|---|---|
websiteURL |
yes | string | Full URL of the page where the captcha is located |
websiteKey |
yes | string | Value of the data-sitekey attribute of the reCAPTCHA widget |
isInvisible |
no | bool | true for invisible reCAPTCHA. Default is false |
recaptchaDataSValue |
no | string | Value of the data-s parameter, which may be required on Google services |
userAgent |
no | string | User-Agent of the browser used to load the captcha |
cookies |
no | string | Cookies in the format name1=value1; name2=value2, if the session is important for solving |
apiDomain |
no | string | Domain used to load reCAPTCHA: google.com or recaptcha.net. Default is google.com |
Only for RecaptchaV2Task (solving via your proxy), additionally:
| Parameter | Required | Type | Description |
|---|---|---|---|
proxyType |
yes | string | http, socks4, or socks5 |
proxyAddress |
yes | string | Proxy IP address or hostname |
proxyPort |
yes | int | Proxy port |
proxyLogin |
no | string | Login for proxy authorization |
proxyPassword |
no | string | Password for proxy authorization |
Task object examples
// RecaptchaV2TaskProxyless
{
"type": "RecaptchaV2TaskProxyless",
"websiteURL": "https://example.com/login",
"websiteKey": "6Le-xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"isInvisible": false
}
// RecaptchaV2Task (your proxy)
{
"type": "RecaptchaV2Task",
"websiteURL": "https://example.com/login",
"websiteKey": "6Le-xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"proxyType": "http",
"proxyAddress": "1.2.3.4",
"proxyPort": 8080,
"proxyLogin": "user",
"proxyPassword": "password",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."
}
getTaskResult response example
While the task is processing:
{
"errorId": 0,
"status": "processing"
}
Once solved:
{
"errorId": 0,
"status": "ready",
"solution": {
"gRecaptchaResponse": "03AGdBq..."
}
}
You need to pass the solution.gRecaptchaResponse value to the reCAPTCHA widget or the g-recaptcha-response form parameter.
reCAPTCHA v2 Enterprise#
Types RecaptchaV2EnterpriseTaskProxyless and RecaptchaV2EnterpriseTask.
| Parameter | Required | Type | Description |
|---|---|---|---|
websiteURL |
yes | string | Full URL of the page where the captcha is placed |
websiteKey |
yes | string | Value of the data-sitekey attribute of the reCAPTCHA Enterprise widget |
enterprisePayload |
no | object | Additional parameters of the grecaptcha.enterprise.render call, if the site passes them, for example the s value |
isInvisible |
no | bool | true for invisible reCAPTCHA. Default is false |
apiDomain |
no | string | Domain from which reCAPTCHA is loaded: google.com or recaptcha.net. Default is google.com |
userAgent |
no | string | User-Agent of the browser used to load the captcha |
cookies |
no | string | Cookies in the format name1=value1; name2=value2, if the session is important for solving |
Only for RecaptchaV2EnterpriseTask (solving via your proxy), additionally:
| Parameter | Required | Type | Description |
|---|---|---|---|
proxyType |
yes | string | http, socks4, or socks5 |
proxyAddress |
yes | string | Proxy IP address or hostname |
proxyPort |
yes | int | Proxy port |
proxyLogin |
no | string | Login for proxy authorization |
proxyPassword |
no | string | Password for proxy authorization |
Examples of the task object
// RecaptchaV2EnterpriseTaskProxyless
{
"type": "RecaptchaV2EnterpriseTaskProxyless",
"websiteURL": "https://example.com/login",
"websiteKey": "6Le-xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"isInvisible": false
}
// RecaptchaV2EnterpriseTask (your proxy)
{
"type": "RecaptchaV2EnterpriseTask",
"websiteURL": "https://example.com/login",
"websiteKey": "6Le-xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"isInvisible": false,
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
"cookies": "foo=bar; baz=1",
"proxyType": "http",
"proxyAddress": "1.2.3.4",
"proxyPort": 8080,
"proxyLogin": "user",
"proxyPassword": "password"
}
Example of getTaskResult response
While the task is being processed:
{
"errorId": 0,
"status": "processing"
}
After successful solving:
{
"errorId": 0,
"status": "ready",
"solution": {
"gRecaptchaResponse": "03AGdBq2kX9Lm...QpZr8vN3sT"
}
}
The solution.gRecaptchaResponse value is passed in the same way as a regular reCAPTCHA v2 token, to the widget or to the g-recaptcha-response parameter of the form.
The Enterprise method uses the reCAPTCHA Enterprise API. If the site passes additional parameters through enterprisePayload, include them in the request.
reCAPTCHA v3#
Type RecaptchaV3TaskProxyless. A proxy is not required for v3. Tasks are solved from the service IP addresses.
| Parameter | Required | Type | Description |
|---|---|---|---|
websiteURL |
yes | string | Full URL of the page with the captcha |
websiteKey |
yes | string | Site key of the reCAPTCHA v3 widget |
minScore |
yes | float | Required score. Supported values are 0.3, 0.7, and 0.9 |
pageAction |
no | string | Value of the action parameter that the site sets when calling grecaptcha.execute() |
isEnterprise |
no | bool | true if the site uses reCAPTCHA v3 Enterprise |
apiDomain |
no | string | Domain from which the reCAPTCHA script is loaded: google.com or recaptcha.net. Default is google.com |
Task object example
// RecaptchaV3TaskProxyless
{
"type": "RecaptchaV3TaskProxyless",
"websiteURL": "https://example.com/login",
"websiteKey": "6Le-xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"minScore": 0.3,
"pageAction": "login",
"isEnterprise": false
}
getTaskResult response example
While the task is processing:
{
"errorId": 0,
"status": "processing"
}
Once solved:
{
"errorId": 0,
"status": "ready",
"solution": {
"gRecaptchaResponse": "03AGdBq..."
}
}
You use the received token (solution.gRecaptchaResponse) just like a regular reCAPTCHA v3 token.
Finding the reCAPTCHA sitekey and callback function on the page#
If there are multiple reCAPTCHA widgets on the page or the callback is not directly visible in the markup, you can find the sitekey and callback function via the ___grecaptcha_cfg object, where Google stores the configuration of rendered widgets. Run the following code in the developer console or embed it in your automation script. It will return an array with the found reCAPTCHA clients along with their sitekey, pageurl, and callback reference.
function findRecaptchaClients() {
// eslint-disable-next-line camelcase
if (typeof (___grecaptcha_cfg) !== 'undefined') {
// eslint-disable-next-line camelcase, no-undef
return Object.entries(___grecaptcha_cfg.clients).map(([cid, client]) => {
const data = { id: cid, version: cid >= 10000 ? 'V3' : 'V2' };
const objects = Object.entries(client).filter(([_, value]) => value && typeof value === 'object');
objects.forEach(([toplevelKey, toplevel]) => {
const found = Object.entries(toplevel).find(([_, value]) => (
value && typeof value === 'object' && 'sitekey' in value && 'size' in value
));
if (typeof toplevel === 'object' && toplevel instanceof HTMLElement && toplevel['tagName'] === 'DIV') {
data.pageurl = toplevel.baseURI;
}
if (found) {
const [sublevelKey, sublevel] = found;
data.sitekey = sublevel.sitekey;
const callbackKey = data.version === 'V2' ? 'callback' : 'promise-callback';
const callback = sublevel[callbackKey];
if (!callback) {
data.callback = null;
data.function = null;
} else {
data.function = callback;
const keys = [cid, toplevelKey, sublevelKey, callbackKey]
.map((key) => `['${key}']`)
.join('');
data.callback = `___grecaptcha_cfg.clients${keys}`;
}
}
});
return data;
});
}
return [];
}
Usage:
let res = findRecaptchaClients()
console.log(res)
For each found client, data.version indicates whether it is v2 or v3. data.sitekey is the value for the websiteKey field in the createTask request. data.callback is the path to the callback function that needs to be executed with the token after receiving the solution.
Cloudflare Turnstile#
Types TurnstileTaskProxyless and TurnstileTask.
| Parameter | Required | Type | Description |
|---|---|---|---|
websiteURL |
yes | string | Full URL of the page where the Turnstile widget is located |
websiteKey |
yes | string | Value of the data-sitekey attribute of the Turnstile widget |
action |
no* | string | Value of the action parameter from the turnstile.render call. Required for Cloudflare Challenge pages |
data |
no* | string | Value of the cData parameter from the turnstile.render call. Required for Cloudflare Challenge pages |
pagedata |
no* | string | Value of the chlPageData parameter from the turnstile.render call. Required for Cloudflare Challenge pages |
userAgent |
no* | string | Current browser User-Agent. Required for Cloudflare Challenge pages |
Only for TurnstileTask (solving via your proxy), additionally:
| Parameter | Required | Type | Description |
|---|---|---|---|
proxyType |
yes | string | http, socks4, or socks5 |
proxyAddress |
yes | string | Proxy IP address or hostname |
proxyPort |
yes | int | Proxy port |
proxyLogin |
no | string | Login for proxy authorization |
proxyPassword |
no | string | Password for proxy authorization |
Task object examples
// TurnstileTaskProxyless
{
"type": "TurnstileTaskProxyless",
"websiteURL": "https://example.com/login",
"websiteKey": "0x4AAAAAAAxxxxxxxxxxxxxxxx"
}
// TurnstileTask (your proxy)
{
"type": "TurnstileTask",
"websiteURL": "https://example.com/login",
"websiteKey": "0x4AAAAAAAxxxxxxxxxxxxxxxx",
"proxyType": "http",
"proxyAddress": "1.2.3.4",
"proxyPort": 8080
}
getTaskResult response example
While the task is processing:
{
"errorId": 0,
"status": "processing"
}
Once solved:
{
"errorId": 0,
"status": "ready",
"solution": {
"token": "0.zxcv..."
}
}
You need to pass the received token (solution.token) to the widget callback function or the cf-turnstile-response field, depending on how you integrate Turnstile on your site.
Complex case: Cloudflare Challenge page#
A separate and more complex situation is the Cloudflare Challenge page. Besides websiteKey, additional parameters cData, chlPageData, and action are passed to the widget. In this case, you need to intercept the turnstile.render call to extract these values. You also need to intercept the callback function definition.
To intercept the parameters, embed the following JavaScript on the page before the Cloudflare Turnstile widget itself loads:
const i = setInterval(() => {
if (window.turnstile) {
clearInterval(i)
window.turnstile.render = (a, b) => {
let p = {
type: "TurnstileTaskProxyless",
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.tsCallback = b.callback
return 'foo'
}
}
}, 10)
The script replaces turnstile.render with a custom function. It intercepts the configuration object b, in which Cloudflare passes sitekey, cData, chlPageData, action, and callback. It logs the task object for createTask and saves a reference to the original callback function in window.tsCallback to call it later with the token.
An alternative approach is to intercept the network request to the api.js script and replace it with your own script. This script returns the required parameters and makes the callback function globally accessible.
When the solution is received from getTaskResult, execute the saved callback function by passing the token as an argument:
window.tsCallback('TOKEN_FROM_SOLUTION');
Keep the browser User-Agent unchanged when invoking the callback. The response may contain solution.userAgent; do not switch the browser to this value.
Yandex SmartCaptcha#
There are two methods for solving Yandex SmartCaptcha: token-based and image-based.
YandexSmartCaptchaTaskProxyless— token-based solving using our proxiesYandexSmartCaptchaTask— token-based solving using your proxiesCoordinatesTask— image-based solving, returns click coordinates
Token-based solving#
Types YandexSmartCaptchaTaskProxyless and YandexSmartCaptchaTask.
| Parameter | Required | Type | Description |
|---|---|---|---|
websiteURL |
yes | string | Full URL of the page where the captcha is loaded |
websiteKey |
yes | string | The sitekey value from the page code or captcha iframe |
userAgent |
no | string | User-Agent under which the captcha is solved |
cookies |
no | string | Cookies in the format name1=value1;name2=value2 |
Only for YandexSmartCaptchaTask (solving via your proxy), additionally:
| Parameter | Required | Type | Description |
|---|---|---|---|
proxyType |
yes | string | http, https, socks4, or socks5 |
proxyAddress |
yes | string | Proxy IP address or hostname |
proxyPort |
yes | int | Proxy port |
proxyLogin |
no | string | Login for proxy authorization |
proxyPassword |
no | string | Password for proxy authorization |
Task object examples
// YandexSmartCaptchaTaskProxyless
{
"type": "YandexSmartCaptchaTaskProxyless",
"websiteURL": "https://example.com/login",
"websiteKey": "Y5Lh0ti..."
}
// YandexSmartCaptchaTask (your proxy)
{
"type": "YandexSmartCaptchaTask",
"websiteURL": "https://example.com/login",
"websiteKey": "Y5Lh0ti...",
"proxyType": "http",
"proxyAddress": "1.2.3.4",
"proxyPort": 8080
}
getTaskResult response example
While the task is processing:
{
"errorId": 0,
"status": "processing"
}
Once solved:
{
"errorId": 0,
"status": "ready",
"solution": {
"token": "dV9xNjYyNTU3NjkxO4k9OTQuNVMuMjkuMjM9..."
}
}
solution.token should be used in the smart-token field or passed to your site's backend, the same way as a manually solved captcha.
Image to Text#
Type ImageToTextTask. No proxy is required. The captcha image itself is submitted directly.
| Parameter | Required | Type | Description |
|---|---|---|---|
body |
yes | string | The captcha image, Base64-encoded. Data-URI format is also supported |
phrase |
no | bool | true if the answer should contain at least two words separated by a space. Default is false |
case |
no | bool | true if the result is case-sensitive. Default is false |
numeric |
no | int | Character set hint: 0 — no preference, 1 — numbers only, 2 — letters only, 3 — numbers or letters only, 4 — must contain both numbers and letters |
math |
no | bool | true if the captcha requires a calculation. Default is false |
minLength |
no | int | Minimum answer length. 0 means no minimum |
maxLength |
no | int | Maximum answer length. 0 means no maximum |
comment |
no | string | A hint for the worker solving the image |
imgInstructions |
no | string | An optional instruction image, Base64-encoded, shown to the worker alongside the captcha image |
Task object example
{
"type": "ImageToTextTask",
"body": "iVBORw0KGgoAAAANSUhEUgAA...",
"numeric": 1,
"minLength": 4,
"maxLength": 6
}
getTaskResult response example
While the task is processing:
{
"errorId": 0,
"status": "processing"
}
Once solved:
{
"errorId": 0,
"status": "ready",
"solution": {
"text": "aB3fX9"
}
}
solution.text is the recognized text. Submit it to the target form field the same way you would a manually entered answer.
Coordinates#
Use CoordinatesTask for generic click-on-image captchas.
| Parameter | Required | Description |
|---|---|---|
body |
yes | Captcha image encoded as Base64 |
comment |
no | Text instruction for the worker |
imgInstructions |
no | Optional instruction image encoded as Base64 |
minClicks |
no | Minimum number of clicks |
maxClicks |
no | Maximum number of clicks |
The solution contains a coordinates array with click positions.
GeeTest v3#
Types GeeTestTaskProxyless and GeeTestTask. The same task types are used for GeeTest v4. The version is selected with the version field. The default version is 3.
| Parameter | Required | Type | Description |
|---|---|---|---|
websiteURL |
yes | string | Full URL of the page where the GeeTest widget is located |
version |
no | int | GeeTest version: 3 or 4. Default is 3 |
gt |
yes | string | Public gt value of the GeeTest widget |
challenge |
yes | string | Session-specific challenge value found on the page. Get a new value for each task |
geetestApiServerSubdomain |
no | string | Custom GeeTest API server subdomain, if the page uses one |
initParameters |
no | object | Additional parameters passed to the GeeTest initialization call |
userAgent |
no | string | User-Agent of the browser used to load the captcha |
risk_type |
no | string | Dynamic risk_type value included in the captcha loading request |
Only for GeeTestTask (solving via your proxy), additionally:
| Parameter | Required | Type | Description |
|---|---|---|---|
proxyType |
yes | string | http, socks4, or socks5 |
proxyAddress |
yes | string | Proxy IP address or hostname |
proxyPort |
yes | int | Proxy port |
proxyLogin |
no | string | Login for proxy authorization |
proxyPassword |
no | string | Password for proxy authorization |
Task object examples
// GeeTestTaskProxyless
{
"type": "GeeTestTaskProxyless",
"websiteURL": "https://example.com/login",
"gt": "f2ae6cadcf7886856696c46d84d109d1",
"challenge": "12345678abc90123d45678e90123f45g6"
}
// GeeTestTask (your proxy)
{
"type": "GeeTestTask",
"websiteURL": "https://example.com/login",
"gt": "f2ae6cadcf7886856696c46d84d109d1",
"challenge": "12345678abc90123d45678e90123f45g6",
"proxyType": "http",
"proxyAddress": "1.2.3.4",
"proxyPort": 8080
}
getTaskResult response example
While the task is processing:
{
"errorId": 0,
"status": "processing"
}
Once solved:
{
"errorId": 0,
"status": "ready",
"solution": {
"challenge": "12345678abc90123d45678e90123f45g6",
"validate": "0a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p",
"seccode": "0a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p|jordan"
}
}
Pass solution.validate and solution.seccode into the page's GeeTest callback according to the integration used by the target site.
GeeTest v4#
Same types as GeeTest v3, GeeTestTaskProxyless and GeeTestTask. Set version to 4 to use GeeTest v4.
| Parameter | Required | Type | Description |
|---|---|---|---|
websiteURL |
yes | string | Full URL of the page where the GeeTest v4 widget is located |
version |
yes | int | Must be 4 |
initParameters |
yes | object | Must contain captcha_id, the widget's static captcha identifier |
userAgent |
no | string | User-Agent of the browser used to load the captcha |
risk_type |
no | string | Dynamic risk_type value included in the captcha loading request |
Only for GeeTestTask (solving via your proxy), additionally:
| Parameter | Required | Type | Description |
|---|---|---|---|
proxyType |
yes | string | http, socks4, or socks5 |
proxyAddress |
yes | string | Proxy IP address or hostname |
proxyPort |
yes | int | Proxy port |
proxyLogin |
no | string | Login for proxy authorization |
proxyPassword |
no | string | Password for proxy authorization |
Task object examples
// GeeTestTaskProxyless (v4)
{
"type": "GeeTestTaskProxyless",
"websiteURL": "https://example.com/login",
"version": 4,
"initParameters": {
"captcha_id": "e392e65f912c780f2c3ebac7702651de"
}
}
// GeeTestTask (v4, your proxy)
{
"type": "GeeTestTask",
"websiteURL": "https://example.com/login",
"version": 4,
"initParameters": {
"captcha_id": "e392e65f912c780f2c3ebac7702651de"
},
"proxyType": "http",
"proxyAddress": "1.2.3.4",
"proxyPort": 8080
}
getTaskResult response example
While the task is processing:
{
"errorId": 0,
"status": "processing"
}
Once solved:
{
"errorId": 0,
"status": "ready",
"solution": {
"captcha_id": "e392e65f912c780f2c3ebac7702651de",
"lot_number": "...",
"pass_token": "...",
"gen_time": "...",
"captcha_output": "..."
}
}
solution.lot_number, pass_token, gen_time, and captcha_output together form the GeeTest v4 result object. Pass them into the page's GeeTest callback as-is.
Tencent#
Types TencentTaskProxyless and TencentTask.
| Parameter | Required | Type | Description |
|---|---|---|---|
websiteURL |
yes | string | Full URL of the page where the captcha is loaded |
appId |
yes | string | The value of the appId parameter found in the page source code |
captchaScript |
no | string | Captcha script URL from the page source code. Default: https://turing.captcha.qcloud.com/TCaptcha.js |
Only for TencentTask (solving via your proxy), additionally:
| Parameter | Required | Type | Description |
|---|---|---|---|
proxyType |
yes | string | http, socks4, or socks5 |
proxyAddress |
yes | string | Proxy IP address or hostname |
proxyPort |
yes | int | Proxy port |
proxyLogin |
no | string | Login for proxy authorization |
proxyPassword |
no | string | Password for proxy authorization |
Task object examples
// TencentTaskProxyless
{
"type": "TencentTaskProxyless",
"websiteURL": "https://example.com/login",
"appId": "190014885"
}
// TencentTask (your proxy)
{
"type": "TencentTask",
"websiteURL": "https://example.com/login",
"appId": "190014885",
"proxyType": "http",
"proxyAddress": "1.2.3.4",
"proxyPort": 8080
}
getTaskResult response example
While the task is processing:
{
"errorId": 0,
"status": "processing"
}
Once solved:
{
"errorId": 0,
"status": "ready",
"solution": {
"appid": "190014885",
"ret": 0,
"ticket": "tr0344YjJASGmJGtohyWS_y6tJKiqVPIdFgl87vWlVaQoueR8D6DH28go-i-VjeassM31SXO7D0*",
"randstr": "@KVN"
}
}
solution.appid, ret, ticket, and randstr together form the Tencent result object. Pass them into the page's captcha callback as-is.
Python SDK#
All listed task types are available in captcha_solver_api.tasks. Parameters preserve API casing: websiteURL, websiteKey, enterprisePayload, and imgInstructions; use pagedata and risk_type exactly as written. None fields are omitted, while False and 0 are preserved. Pass language_pool to the client or task-creation method, outside the task object. Examples for each type.