Get API Key

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, found on some Google pages (Search, YouTube)
userAgent no string User-Agent under which the captcha is solved. It is advisable to pass the same one your bot uses
cookies no string Cookies in the format name1=value1; name2=value2, if the session is important for solving
enterprisePayload no object Additional data for reCAPTCHA v2 Enterprise, if enterprise markup is used

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
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 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 Minimum acceptable token score, for example 0.3, 0.7, or 0.9. The higher the value, the harder and longer the task takes to solve
pageAction no string Value of the action parameter that the site sets when calling grecaptcha.execute(). If known, pass it. This increases the chance of the site accepting the token
isEnterprise no bool true if the site uses reCAPTCHA v3 Enterprise
apiDomain no string Domain from which the reCAPTCHA script is loaded (www.google.com or www.recaptcha.net), if the site uses a non-standard domain

Task object example

// RecaptchaV3TaskProxyless
{
  "type": "RecaptchaV3TaskProxyless",
  "websiteURL": "https://example.com/login",
  "websiteKey": "6Le-xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "minScore": 0.3,
  "pageAction": "login"
}

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 all rendered widgets. Run the following code in the developer console or embed it in your automation script. It will return an array with all found reCAPTCHA clients (both v2 and v3) 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 will indicate 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 (see "How to use the received token" below).

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 data-action attribute, if set on the site
cData no string Value of the data-cdata attribute (custom payload), if the site uses it
pageData no string Value of the chlPageData parameter for more complex Turnstile checks
userAgent no string User-Agent under which the token will be solved and subsequently used. The token is tied to the User-Agent, so it must be passed by the same browser or bot that solved it

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
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 like cData, chlPageData, and action may be passed to the widget. The token will not be accepted without them. In this case, you need to intercept the turnstile.render call to extract these values. You also need to intercept the callback function definition and pass your browser userAgent in the request.

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 ready 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 (for example, via window).

When the solution is received from getTaskResult, you just need to execute the saved callback function by passing the token as an argument:

window.tsCallback('TOKEN_FROM_SOLUTION');