DEV Community

Cover image for reCAPTCHA v2 vs v3 vs Enterprise — how to tell which one you're fighting (and how to solve each)
Bassem Shahin
Bassem Shahin

Posted on

reCAPTCHA v2 vs v3 vs Enterprise — how to tell which one you're fighting (and how to solve each)

reCAPTCHA v2 vs v3 vs Enterprise — how to tell which one you're fighting

"reCAPTCHA is blocking me" is the start of a debugging session, not the end of one. There are four practical variants — v2 checkbox, v2 invisible, v3 score, and Enterprise — and they behave completely differently. They fail differently, they're solved differently, and the call you make to a solver isn't the same shape. So before you touch any code, the first job is identifying which one you're up against. The page tells you, if you know where to look.

How to tell which variant it is

Everything you need is in the page source and the script tags. Open devtools, look at the rendered widget and the api.js include.

v2 checkbox — the classic "I'm not a robot" box. In the DOM you'll see a

, and the page loads https://www.google.com/recaptcha/api.js. The sitekey starts with 6L. There's a visible checkbox; clicking it sometimes triggers an image grid ("select all bicycles").

v2 invisible — same api.js, same 6L... sitekey shape, but no visible checkbox. The widget is bound to a button or fired via grecaptcha.execute(), often with data-size="invisible". It only shows an image challenge if Google decides the session looks risky.

v3 score — there is no widget and no checkbox at all. The script include is https://www.google.com/recaptcha/api.js?render= — the ?render= parameter is the dead giveaway. The page calls grecaptcha.execute(sitekey, {action: 'login'}) and gets back a token plus a 0.0–1.0 score that the site's backend evaluates.

Enterprise — the script is https://www.google.com/recaptcha/enterprise.js?render=... (note enterprise.js, not api.js), and the JS calls live under grecaptcha.enterprise.*. Enterprise can run in a v2-style or v3-style mode, so identify it by the enterprise.js include first, then check widget vs. ?render=.

Quick reference for the script tell:

  • api.js + visible checkbox → v2 checkbox

  • api.js + data-size="invisible" / execute() → v2 invisible

  • api.js?render=KEY → v3

  • enterprise.js → Enterprise (then check widget vs. score mode)

What each means for automation

  • v2 checkbox is a puzzle problem — you need a token representing a solved challenge.

  • v2 invisible is mostly the same under the hood, except the challenge only surfaces when you look risky. Clean up IP/fingerprint and it often passes silently.

  • v3 is a reputation problem, not a puzzle. Nothing to click — you're scored on IP, fingerprint, behavior, and the action. A "fail" means you scored below the site's threshold.

  • Enterprise is the same two modes wearing a different SDK. The practical difference is the namespace and sometimes a required actionenterprise flag. It's the same v2/v3 mechanics with more backend signals on the site's side; your client job barely changes.

The most common mistake: grabbing a token for the wrong variant — a plain v2 token sent to a v3 endpoint, or v3 solved without the matching action. The token comes back fine, the form submits, and the site silently rejects it. Identifying correctly up front saves that whole loop.

The solve flow per variant

If your solving already speaks the 2Captcha-style API method=userrecaptcha, googlekey, pageurl), every variant is the same endpoint with a couple of parameters flipped. Submit to in.php, poll res.php, drop the token into g-recaptcha-response.

  • v2 checkbox / invisible: method=userrecaptcha, googlekey=, pageurl=. Invisible uses the exact same call.

  • v3: add version=v3 and action= (e.g. login). The action must match what the page passes to execute(). You can't request a score — the site's backend sets the minimum.

  • Enterprise: add enterprise=1 alongside the v2 or v3 parameters depending on the mode. Same googlekeypageurl; if score mode, still send action.

Here's the v3 case end to end; v2 is the same minus versionaction, Enterprise adds enterprise=1:


import requests, time

API_KEY  = "YOUR_API_KEY"

SITEKEY  = "6Lc..."                       # the data-sitekey / render key

PAGEURL  = "https://target.example/login"

# submit (v3 shown; drop version+action for v2, add enterprise=1 for Enterprise)

rid = requests.post("https://ocr.captchaai.com/in.php", data={

    "key": API_KEY, "method": "userrecaptcha",

    "version": "v3", "actison": "login",

    "googlekey": SITEKEY, "pageurl": PAGEURL, "json": 1,

}).json()["request"]

# poll

token = None

for _ in range(40):

    time.sleep(3)

    res = requests.get("https://ocr.captchaai.com/res.php", params={

        "key": API_KEY, "action": "get", "id": rid, "json": 1}).json()

    if res["status"] == 1:

        token = res["request"]; break

# submit token as g-recaptcha-response (matching the action for v3)

TL;DR

  • Identify from the script include: api.js (v2), api.js?render= (v3), enterprise.js (Enterprise); then checkbox vs. invisible vs. score by the widget/flow.

  • v2 = puzzle/token, v3 = reputation/score, Enterprise = same two modes, different SDK + an enterprise flag.

  • Solve flow is one endpoint: userrecaptcha + googlekey + pageurl, with version=v3action for v3 and enterprise=1 for Enterprise.


CaptchaAI returns tokens for reCAPTCHA v2 (checkbox + invisible), v3 (with action), and Enterprise, and it's 2Captcha-API-compatible — so an existing client is mostly a base-URL change. The trial is free (3 days, no card).

Top comments (0)