Comparisons

reCAPTCHA v2 vs Invisible reCAPTCHA Explained

Both are reCAPTCHA v2 variants using the same underlying technology. The checkbox version shows "I'm not a robot" and may present image grids. The invisible version triggers automatically on user actions (button click, form submit, or page load) with no visible widget. For CaptchaAI solving, the only difference is adding invisible=1 to your request — but the token injection process differs significantly.


Side-by-side comparison

Feature v2 Checkbox v2 Invisible
Visible widget Yes — "I'm not a robot" checkbox No — hidden from users
Trigger mechanism User clicks checkbox Button click, form submit, or page load
Image challenge Shown when Google suspects a bot Popup in bottom-right corner when suspicious
User experience Moderate friction Low/zero friction
Implementation Add g-recaptcha div to page Add data-callback to button or grecaptcha.execute()
Sitekey format Same as invisible Same as checkbox
Token field g-recaptcha-response g-recaptcha-response
Callback function Optional Almost always required
CaptchaAI method method=userrecaptcha method=userrecaptcha + invisible=1
Token lifetime 120 seconds 120 seconds
Solve time 10-30 seconds 10-25 seconds

How each appears in the HTML

v2 Checkbox

<!-- Standard checkbox widget -->
<div class="g-recaptcha"
     data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
     data-callback="onSubmit">
</div>

<!-- Widget renders as: -->
<!-- [✓] I'm not a robot     reCAPTCHA logo -->

The user sees and interacts with the checkbox. If Google is suspicious, an image grid challenge appears inline.

v2 Invisible

<!-- Pattern 1: Invisible widget on a button -->
<button class="g-recaptcha"
        data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
        data-callback="onSubmit"
        data-size="invisible">
  Submit
</button>

<!-- Pattern 2: Invisible div (programmatic trigger) -->
<div class="g-recaptcha"
     data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
     data-size="invisible"
     data-callback="onSubmit">
</div>

<!-- Pattern 3: Programmatic render -->
<script>
  grecaptcha.render('submit-btn', {
    sitekey: '6Le-wvkSAAAAAPBMRTvw...',
    callback: onSubmit,
    size: 'invisible'
  });
</script>

No visible widget. reCAPTCHA activates when the user triggers the specified element or when grecaptcha.execute() is called.


How to detect which variant is on a page

Python detection:

import requests
from bs4 import BeautifulSoup
import re

def detect_recaptcha_variant(url):
    resp = requests.get(url)
    soup = BeautifulSoup(resp.text, "html.parser")

    # Check for invisible indicators
    invisible_widget = soup.find(attrs={"data-size": "invisible", "class": "g-recaptcha"})
    if invisible_widget:
        return {
            "variant": "invisible",
            "sitekey": invisible_widget.get("data-sitekey"),
            "callback": invisible_widget.get("data-callback")
        }

    # Check for programmatic invisible in scripts
    for script in soup.find_all("script"):
        if script.string and "invisible" in str(script.string):
            key_match = re.search(r"sitekey['\"]?\s*[:=]\s*['\"]([^'\"]+)", script.string)
            if key_match:
                return {
                    "variant": "invisible-programmatic",
                    "sitekey": key_match.group(1),
                    "callback": "check grecaptcha.render() call"
                }

    # Check for standard checkbox
    checkbox_widget = soup.find(class_="g-recaptcha")
    if checkbox_widget:
        return {
            "variant": "checkbox",
            "sitekey": checkbox_widget.get("data-sitekey"),
            "callback": checkbox_widget.get("data-callback")
        }

    return None

result = detect_recaptcha_variant("https://example.com/login")
print(result)

Node.js detection:

const axios = require("axios");
const cheerio = require("cheerio");

async function detectRecaptchaVariant(url) {
  const { data } = await axios.get(url);
  const $ = cheerio.load(data);

  // Check for invisible
  const invisible = $(".g-recaptcha[data-size='invisible']");
  if (invisible.length) {
    return {
      variant: "invisible",
      sitekey: invisible.attr("data-sitekey"),
      callback: invisible.attr("data-callback"),
    };
  }

  // Check scripts for programmatic invisible
  const scripts = $("script")
    .map((_, el) => $(el).html())
    .get()
    .join("\n");
  if (scripts.includes("invisible")) {
    const keyMatch = scripts.match(/sitekey['"]?\s*[:=]\s*['"]([^'"]+)/);
    if (keyMatch) {
      return {
        variant: "invisible-programmatic",
        sitekey: keyMatch[1],
        callback: "check render call",
      };
    }
  }

  // Check for standard checkbox
  const checkbox = $(".g-recaptcha");
  if (checkbox.length) {
    return {
      variant: "checkbox",
      sitekey: checkbox.attr("data-sitekey"),
      callback: checkbox.attr("data-callback"),
    };
  }

  return null;
}

Quick browser console check:

const el = document.querySelector('[data-size="invisible"]');
console.log(el ? "Invisible reCAPTCHA" : "Checkbox reCAPTCHA");
Detection signal v2 Checkbox v2 Invisible
data-size="invisible" Not present Present
Visible checkbox on page Yes No
grecaptcha.execute() called No (user clicks) Yes (programmatic)
Challenge popup position Inline, below checkbox Bottom-right corner of page

Solving with CaptchaAI

v2 Checkbox

import requests
import time

resp = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": "6Le-wvkSAAAA...",
    "pageurl": "https://example.com/form"
})
task_id = resp.text.split("|")[1]

for _ in range(60):
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": "YOUR_API_KEY", "action": "get", "id": task_id
    })
    if result.text.startswith("OK|"):
        token = result.text.split("|")[1]
        break

v2 Invisible

import requests
import time

resp = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": "6Le-wvkSAAAA...",
    "pageurl": "https://example.com/form",
    "invisible": 1  # Only parameter difference
})
task_id = resp.text.split("|")[1]

for _ in range(60):
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": "YOUR_API_KEY", "action": "get", "id": task_id
    })
    if result.text.startswith("OK|"):
        token = result.text.split("|")[1]
        break

Token injection — the critical difference

v2 Checkbox: Hidden field is usually enough

# Selenium — inject into hidden field
driver.execute_script(
    f'document.getElementById("g-recaptcha-response").value = "{token}";'
)

# If the page uses a callback, also call it
callback = driver.find_element("css selector", ".g-recaptcha").get_attribute("data-callback")
if callback:
    driver.execute_script(f'{callback}("{token}");')

v2 Invisible: Callback is almost always required

# Selenium — inject AND call the callback
driver.execute_script(
    f'document.getElementById("g-recaptcha-response").value = "{token}";'
)

# CRITICAL: Invisible reCAPTCHA almost always requires calling the callback
callback_name = driver.find_element(
    "css selector", ".g-recaptcha[data-size='invisible']"
).get_attribute("data-callback")

driver.execute_script(f'{callback_name}("{token}");')
// Puppeteer — invisible callback injection
await page.evaluate((tok) => {
  // Set the hidden field
  document.getElementById("g-recaptcha-response").value = tok;

  // Find and call the callback function
  const widget = document.querySelector("[data-size='invisible']");
  const cbName = widget?.getAttribute("data-callback");
  if (cbName && typeof window[cbName] === "function") {
    window[cbName](tok);
  }
}, token);

Key difference: v2 checkbox forms often work with just the hidden field injection because the user's click on the checkbox already registered the callback. Invisible reCAPTCHA never has that click — the callback must be called explicitly.


Universal solver for both variants

import requests
import time
from bs4 import BeautifulSoup

class RecaptchaV2UniversalSolver:
    def __init__(self, api_key):
        self.api_key = api_key

    def detect_and_solve(self, page_url, page_html=None):
        if not page_html:
            page_html = requests.get(page_url).text

        soup = BeautifulSoup(page_html, "html.parser")

        # Detect variant
        invisible = soup.find(attrs={"data-size": "invisible", "class": "g-recaptcha"})
        widget = invisible or soup.find(class_="g-recaptcha")

        if not widget:
            raise Exception("No reCAPTCHA widget found")

        sitekey = widget.get("data-sitekey")
        is_invisible = invisible is not None
        callback = widget.get("data-callback")

        params = {
            "key": self.api_key,
            "method": "userrecaptcha",
            "googlekey": sitekey,
            "pageurl": page_url
        }
        if is_invisible:
            params["invisible"] = 1

        resp = requests.get("https://ocr.captchaai.com/in.php", params=params)
        if not resp.text.startswith("OK|"):
            raise Exception(f"Submit failed: {resp.text}")

        task_id = resp.text.split("|")[1]
        for _ in range(60):
            time.sleep(5)
            result = requests.get("https://ocr.captchaai.com/res.php", params={
                "key": self.api_key, "action": "get", "id": task_id
            })
            if result.text.startswith("OK|"):
                return {
                    "token": result.text.split("|")[1],
                    "variant": "invisible" if is_invisible else "checkbox",
                    "callback": callback,
                    "sitekey": sitekey
                }
            if result.text != "CAPCHA_NOT_READY":
                raise Exception(f"Solve error: {result.text}")

        raise Exception("Timed out")

# Usage
solver = RecaptchaV2UniversalSolver("YOUR_API_KEY")
result = solver.detect_and_solve("https://example.com/login")
print(f"Variant: {result['variant']}, Callback: {result['callback']}")

Troubleshooting

Problem Checkbox fix Invisible fix
Token not accepted Inject into g-recaptcha-response field Inject AND call the data-callback function
Widget not found Look for .g-recaptcha class Check for data-size="invisible" or script render calls
Form submits but fails Check if callback is expected Callback is almost always required — find and call it
Page reloads after injection JavaScript validation failed Call callback before form auto-submission triggers

FAQ

Is invisible reCAPTCHA harder to solve?

No. The solving process through CaptchaAI is nearly identical. Adding invisible=1 to your request is the only change. The extra challenge is on the injection side: you must find and execute the callback function.

Do both use the same sitekey format?

Yes. The sitekey format is identical. You cannot tell the variant from the sitekey alone — check for data-size="invisible" in the HTML.

Does invisible reCAPTCHA still show image challenges?

Yes. When Google detects suspicious behavior, invisible reCAPTCHA shows an image challenge popup in the bottom-right corner of the page. This is why you still need CaptchaAI — the invisible version can still present challenges.

Can a site switch between checkbox and invisible?

Yes. This is a configuration change on the site's end — same sitekey, different implementation. Some sites use checkbox on desktop and invisible on mobile. Always detect the variant dynamically.

Which is faster to solve?

Invisible solves are typically slightly faster (10-25 seconds vs 10-30 seconds) because they tend to trigger fewer image challenges. But the difference is marginal.


Discussions (0)

No comments yet.

Related Posts

Comparisons GeeTest vs reCAPTCHA
Compare Gee Test and re CAPTCHA side by side.

Compare Gee Test and re CAPTCHA side by side. Learn about challenge types, detection methods, solving approach...

Automation reCAPTCHA v3 Migration
Apr 01, 2026
Comparisons reCAPTCHA v2 vs v3 Explained
Compare re CAPTCHA v 2 and v 3 side by side.

Compare re CAPTCHA v 2 and v 3 side by side. Learn how each version works, their detection methods, and how to...

Automation reCAPTCHA v3 Migration
Mar 19, 2026
Comparisons Headless vs Headed Chrome for CAPTCHA Solving
Compare headless and headed Chrome for CAPTCHA automation — detection differences, performance trade-offs, and when to use each mode with Captcha AI.

Compare headless and headed Chrome for CAPTCHA automation — detection differences, performance trade-offs, and...

Automation Python reCAPTCHA v2
Mar 09, 2026
Comparisons reCAPTCHA v3 Enterprise vs Standard Comparison
Compare re CAPTCHA v 3 Enterprise and Standard versions.

Compare re CAPTCHA v 3 Enterprise and Standard versions. Learn about scoring differences, reason codes, enterp...

Automation reCAPTCHA v3 Migration
Feb 16, 2026
Comparisons reCAPTCHA Enterprise vs Standard — Complete Guide
Compare re CAPTCHA Enterprise and Standard versions.

Compare re CAPTCHA Enterprise and Standard versions. Learn the differences in features, scoring, pricing, and...

Automation reCAPTCHA v3 Migration
Feb 05, 2026
Comparisons Standard vs Enterprise reCAPTCHA v3 Solving Guide
Practical comparison of standard and enterprise re CAPTCHA v 3.

Practical comparison of standard and enterprise re CAPTCHA v 3. Covers detection, solving parameters, and Capt...

Automation reCAPTCHA v3 Migration
Jan 27, 2026
Reference CAPTCHA Token Injection Methods Reference
Complete reference for injecting solved CAPTCHA tokens into web pages.

Complete reference for injecting solved CAPTCHA tokens into web pages. Covers re CAPTCHA, Turnstile, and Cloud...

Automation Python reCAPTCHA v2
Apr 08, 2026
Integrations Puppeteer Stealth + CaptchaAI: Reliable Browser Automation
Standard Puppeteer gets detected immediately by anti-bot systems.

Standard Puppeteer gets detected immediately by anti-bot systems. `puppeteer-extra-plugin-stealth` patches the...

Automation reCAPTCHA v2 Cloudflare Turnstile
Apr 05, 2026
Comparisons WebDriver vs Chrome DevTools Protocol for CAPTCHA Automation
Compare Web Driver and Chrome Dev Tools Protocol (CDP) for CAPTCHA automation — detection, performance, capabilities, and when to use each with Captcha AI.

Compare Web Driver and Chrome Dev Tools Protocol (CDP) for CAPTCHA automation — detection, performance, capabi...

Automation Python reCAPTCHA v2
Mar 27, 2026
Comparisons ISP Proxies vs Datacenter Proxies for CAPTCHA Solving
Compare ISP and datacenter proxies for CAPTCHA solving — detection rates, speed, cost, and which works best with Captcha AI.

Compare ISP and datacenter proxies for CAPTCHA solving — detection rates, speed, cost, and which works best wi...

reCAPTCHA v2 Cloudflare Turnstile reCAPTCHA v3
Apr 05, 2026
Comparisons Cloudflare Managed Challenge vs Interactive Challenge
Understand the difference between Cloudflare's Managed Challenge and Interactive Challenge, how each works, and the best approach for solving them.

Understand the difference between Cloudflare's Managed Challenge and Interactive Challenge, how each works, an...

Automation Migration Cloudflare Challenge
Mar 31, 2026
Comparisons Grid Image vs Normal Image CAPTCHA: API Parameter Differences
Compare Grid Image and Normal Image CAPTCHA types — different API parameters, response formats, and when to use each method with Captcha AI.

Compare Grid Image and Normal Image CAPTCHA types — different API parameters, response formats, and when to us...

Automation Image OCR Migration
Mar 25, 2026