# Identify the captcha type

> How to tell which captcha a page uses (reCAPTCHA v2, invisible v2, v3, Enterprise, hCaptcha, Cloudflare Turnstile vs the challenge page) and which YesCaptcha task type to use.

Source: https://docs.yescaptcha.com/en/guides/identify-captcha/ · Last verified: 2026-10-15

Choosing the right task type starts with recognizing the captcha. The most reliable way is to open the browser’s developer tools (F12) and see in the Network panel which captcha script the page loads; you can also tell by appearance.

## Quick reference

| What you see | What it is | Task type |
| --- | --- | --- |
| An “I’m not a robot” checkbox | reCAPTCHA v2 | [reCAPTCHA v2](https://docs.yescaptcha.com/en/tasks/recaptcha-v2/) |
| No checkbox; an image challenge appears after you click submit; a small reCAPTCHA badge in the corner | Invisible reCAPTCHA v2 (or v3) | See “reCAPTCHA versions” below |
| No interaction at all; only the reCAPTCHA badge | reCAPTCHA v3 | [reCAPTCHA v3](https://docs.yescaptcha.com/en/tasks/recaptcha-v3/) |
| An “I am human” checkbox; image challenges branded hCaptcha | hCaptcha | [hCaptcha](https://docs.yescaptcha.com/en/tasks/hcaptcha/) |
| A Cloudflare widget inside a form; the page stays put after the check | Cloudflare Turnstile | [Turnstile](https://docs.yescaptcha.com/en/tasks/turnstile/) |
| The whole page shows “Just a moment…” / “Checking your connection” and then redirects | Cloudflare challenge page | [Cloudflare challenge page](https://docs.yescaptcha.com/en/tasks/cloudflare-challenge/) |
| Arkose Labs puzzles (such as “Pick the image that is the correct way up”) | FunCaptcha | [FunCaptcha](https://docs.yescaptcha.com/en/tasks/funcaptcha/) |
| An image of distorted letters and digits | Text captcha | [Image to text](https://docs.yescaptcha.com/en/tasks/image-to-text/) |

## reCAPTCHA versions

Search the Network panel for `api.js` or `enterprise.js`:

| Script loaded | Version |
| --- | --- |
| `recaptcha/api.js` with no `render` parameter or `render=explicit` | v2 |
| As above, and the `anchor` request URL contains `size=invisible` | Invisible v2: add `"isInvisible": true` |
| `recaptcha/api.js?render=SITE_KEY` (`render` is not `explicit`) | v3 |
| `recaptcha/enterprise.js` with no `render` parameter or `render=explicit` | v2 Enterprise |
| `recaptcha/enterprise.js?render=SITE_KEY` | v3 Enterprise |

Examples:

```text
https://www.google.com/recaptcha/api.js?onload=onloadcallback&render=explicit   → v2
https://www.google.com/recaptcha/api.js?render=6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696   → v3
https://www.google.com/recaptcha/enterprise.js?render=explicit   → v2 Enterprise
```

Invisible v2 sometimes passes only with a v3 type; try both.

You can also run this in the browser console. It lists every reCAPTCHA on the page with its version, site key, page URL and callback:

find-recaptcha-clients.js

```js
// Paste into the browser DevTools console on a page with reCAPTCHA, then run findRecaptchaClients().
// Lists every reCAPTCHA on the page: version (V2/V3), sitekey, page URL and the callback function.
function findRecaptchaClients() {
  if (typeof ___grecaptcha_cfg === 'undefined') return [];
  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 (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;
  });
}

findRecaptchaClients();
```

Example output:

```json
[
  {
    "id": "0",
    "version": "V2",
    "sitekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
    "function": "onSuccess",
    "callback": "___grecaptcha_cfg.clients['0']['l']['l']['callback']",
    "pageurl": "https://www.google.com/recaptcha/api2/demo"
  }
]
```

Google’s demo pages are useful for comparison: v2 `https://www.google.com/recaptcha/api2/demo`, invisible v2 `https://www.google.com/recaptcha/api2/demo?invisible=true`.

## Turnstile vs the challenge page

Both come from Cloudflare, but they are different:

-   **Turnstile** is a widget embedded in a page’s form. After verification it shows a check mark and the page stays where it is. The page loads `challenges.cloudflare.com/turnstile/v0/api.js`. Use [Turnstile](https://docs.yescaptcha.com/en/tasks/turnstile/).
-   **The challenge page** replaces the whole page with Cloudflare’s “Just a moment…” / “example.com needs to review the security of your connection” screen, which may also contain a widget; after passing, it redirects to the real page. The source contains `__cf_chl_rt_tk` or `cdn-cgi/challenge-platform`. Use [Cloudflare challenge page](https://docs.yescaptcha.com/en/tasks/cloudflare-challenge/).

If your program gets a 403 with “Just a moment…” but a browser opens the page directly, you’re probably only being blocked by TLS fingerprinting. A library that imitates a browser’s TLS fingerprint (such as curl\_cffi) usually fixes it without solving anything.
