Invisible CAPTCHAs verify users without showing a visible challenge. There is no checkbox to click, no image grid to solve, and no text to type. The verification happens entirely in the background through JavaScript that analyzes browser behavior, device signals, and network reputation. If your automation workflow encounters a form that submits cleanly for some users but blocks others — with no visible CAPTCHA on the page — you are dealing with an invisible CAPTCHA system.
How invisible CAPTCHAs work
All invisible CAPTCHAs follow the same core pattern:
Page loads → CAPTCHA JavaScript injected
↓
Script runs in background, collecting signals:
├─ Browser fingerprint (canvas, WebGL, fonts, plugins)
├─ Behavioral data (mouse, keyboard, scroll, timing)
├─ Network data (IP reputation, TLS fingerprint)
├─ Device data (screen, GPU, CPU cores, memory)
└─ History data (cookies, previous CAPTCHA completions)
↓
Signals sent to CAPTCHA provider's risk engine
↓
Risk score computed
↓
Response varies by score:
├─ Low risk → Token issued silently (user sees nothing)
├─ Medium → Light challenge shown (checkbox, simple click)
└─ High risk → Full challenge (image grid) or block
The key difference from visible CAPTCHAs: the verification runs continuously from the moment the page loads, not just when the user clicks a checkbox.
Major invisible CAPTCHA systems
1. reCAPTCHA v3
Provider: Google
Release: 2018
Market share: Highest among invisible CAPTCHAs
reCAPTCHA v3 returns a floating-point score between 0.0 and 1.0 for every page action. The website owner decides what to do with the score.
How it collects signals:
<!-- reCAPTCHA v3 integration -->
<script src="https://www.google.com/recaptcha/api.js?render=SITE_KEY"></script>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('SITE_KEY', { action: 'login' }).then(function(token) {
// Token sent to server for verification
document.getElementById('captcha-token').value = token;
});
});
</script>
The execute() call triggers signal collection on-demand. Behind the scenes, reCAPTCHA has been collecting data since the script loaded.
Score interpretation:
| Score | Meaning | Typical action |
|---|---|---|
| 0.9 | Very likely human | Allow |
| 0.7 | Probably human | Allow with monitoring |
| 0.5 | Uncertain | Require additional verification |
| 0.3 | Probably bot | Block or show reCAPTCHA v2 |
| 0.1 | Very likely bot | Block |
Detection in page source:
import requests
import re
def detect_recaptcha_v3(url):
html = requests.get(url, timeout=10).text
indicators = {
"recaptcha_v3": False,
"site_key": None,
"actions": [],
}
# Check for v3 script
if "recaptcha/api.js?render=" in html:
indicators["recaptcha_v3"] = True
match = re.search(r"render=([A-Za-z0-9_-]+)", html)
if match:
indicators["site_key"] = match.group(1)
# Find action names
actions = re.findall(r"action:\s*['\"](\w+)['\"]", html)
indicators["actions"] = actions
return indicators
print(detect_recaptcha_v3("https://example.com/login"))
2. Cloudflare Turnstile
Provider: Cloudflare
Release: 2022
Market share: Fastest growing
Turnstile uses a multi-stage verification pipeline without requiring user data collection.
Verification stages:
- Private Access Token check — If the browser supports Apple PAT, verification completes instantly
- Non-interactive challenge — Browser solves a lightweight cryptographic proof-of-work puzzle
- Managed challenge — Cloudflare decides between non-interactive and interactive based on risk signals from its network (20%+ of internet traffic flows through Cloudflare)
- Interactive challenge — Only shown when risk score is high; displays a checkbox-style widget
Integration:
<!-- Turnstile widget -->
<div class="cf-turnstile" data-sitekey="0x4AAAAAAAC3DHQhMMQ_Rxrg"></div>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
Detection:
def detect_turnstile(url):
html = requests.get(url, timeout=10).text
indicators = {
"turnstile": False,
"site_key": None,
}
if "challenges.cloudflare.com/turnstile" in html or "cf-turnstile" in html:
indicators["turnstile"] = True
match = re.search(r'data-sitekey="([^"]+)"', html)
if match:
indicators["site_key"] = match.group(1)
return indicators
3. reCAPTCHA v2 Invisible
Provider: Google
Release: 2017
This is reCAPTCHA v2 triggered programmatically on form submission. No checkbox is visible — the user clicks the submit button and reCAPTCHA runs in the background. If the risk score is high enough, a visible image challenge appears as a popup.
Integration:
<button class="g-recaptcha"
data-sitekey="SITE_KEY"
data-callback="onSubmit"
data-size="invisible">
Submit
</button>
Key difference from v3: v2 Invisible still falls back to a visible challenge for risky users. v3 never shows a visible challenge — the website must decide what to do with the score.
4. hCaptcha Passive (Enterprise)
Provider: Intuition Machines
Availability: Enterprise tier only
hCaptcha Enterprise's passive mode evaluates the user without any visible widget. It uses the same behavioral signals as standard hCaptcha but only presents a visual challenge to the most suspicious visitors.
5. Apple Private Access Tokens
Provider: Apple
Availability: iOS 16+, macOS Ventura+
This is not a CAPTCHA provider but a CAPTCHA bypass mechanism. Apple devices prove they are legitimate through hardware attestation, allowing websites to skip CAPTCHAs entirely.
Device attestation:
1. Website requests a challenge from a token issuer
2. Device proves it is genuine without revealing identity
3. Token issuer generates a blind-signed token
4. Website verifies token → CAPTCHA skipped
Supported by Cloudflare, Fastly, and other CDN providers.
Solving invisible CAPTCHAs with CaptchaAI
Invisible CAPTCHAs still generate tokens that must be submitted with forms. API-based solvers generate these tokens externally.
Solving reCAPTCHA v3
import requests
import time
API_KEY = "YOUR_API_KEY"
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": "6LdKlZEpAAAAAAOQjzC2v_d36tWxCl6dWsozdSy9",
"pageurl": "https://example.com/login",
"version": "v3",
"action": "login",
"min_score": "0.9",
"json": 1,
})
task_id = submit.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}).json()
if result.get("status") == 1:
token = result["request"]
print(f"reCAPTCHA v3 token received (score ≥ 0.9)")
break
Solving Cloudflare Turnstile
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "turnstile",
"sitekey": "0x4AAAAAAAC3DHQhMMQ_Rxrg",
"pageurl": "https://example.com/signup",
"json": 1,
})
task_id = submit.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}).json()
if result.get("status") == 1:
turnstile_token = result["request"]
print(f"Turnstile token received (100% success rate)")
break
Node.js — Solving reCAPTCHA v3
const axios = require("axios");
async function solveRecaptchaV3(siteKey, pageUrl, action) {
const API_KEY = "YOUR_API_KEY";
// Submit
const { data: submit } = await axios.post(
"https://ocr.captchaai.com/in.php",
new URLSearchParams({
key: API_KEY,
method: "userrecaptcha",
googlekey: siteKey,
pageurl: pageUrl,
version: "v3",
action: action,
min_score: "0.9",
json: 1,
})
);
const taskId = submit.request;
// Poll
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const { data: result } = await axios.get(
"https://ocr.captchaai.com/res.php",
{
params: {
key: API_KEY,
action: "get",
id: taskId,
json: 1,
},
}
);
if (result.status === 1) {
return result.request;
}
}
throw new Error("Solve timeout");
}
solveRecaptchaV3("SITE_KEY", "https://example.com/login", "login")
.then((token) => console.log("Token:", token.substring(0, 50) + "..."));
Detecting invisible CAPTCHAs: comprehensive checker
import requests
import re
def detect_invisible_captcha(url):
"""Detect all invisible CAPTCHA types on a page."""
html = requests.get(url, timeout=10).text
results = []
# reCAPTCHA v3
if "recaptcha/api.js?render=" in html:
key = re.search(r"render=([A-Za-z0-9_-]+)", html)
results.append({
"type": "reCAPTCHA v3",
"site_key": key.group(1) if key else "unknown",
"solver_method": "userrecaptcha (version=v3)",
})
# reCAPTCHA v2 invisible
if 'data-size="invisible"' in html and "g-recaptcha" in html:
key = re.search(r'data-sitekey="([^"]+)"', html)
results.append({
"type": "reCAPTCHA v2 Invisible",
"site_key": key.group(1) if key else "unknown",
"solver_method": "userrecaptcha (invisible=1)",
})
# Cloudflare Turnstile
if "challenges.cloudflare.com/turnstile" in html:
key = re.search(r'data-sitekey="([^"]+)"', html)
results.append({
"type": "Cloudflare Turnstile",
"site_key": key.group(1) if key else "unknown",
"solver_method": "turnstile",
})
# hCaptcha (passive mode detected by script without visible widget)
if "hcaptcha.com/1/api.js" in html and 'data-size="invisible"' in html:
results.append({
"type": "hCaptcha Passive",
"solver_method": "hcaptcha",
})
if not results:
results.append({"type": "none detected"})
return results
for item in detect_invisible_captcha("https://example.com"):
print(item)
Invisible CAPTCHAs comparison
| Feature | reCAPTCHA v3 | Turnstile | reCAPTCHA v2 Invisible | hCaptcha Passive |
|---|---|---|---|---|
| Visible challenge | Never | Rarely | Sometimes (fallback) | Rarely |
| Privacy | Collects browsing data | No personal data | Collects browsing data | Collects interaction data |
| Cost | Free (1M/month) | Free (unlimited) | Free (1M/month) | Enterprise only |
| Score returned | Yes (0.0-1.0) | No (pass/fail) | No (pass/fail) | Yes (Enterprise) |
| Fallback visible challenge | Website decides | Managed by Cloudflare | Image grid popup | Image grid popup |
| CaptchaAI support | Yes (v3 token) | Yes (100% success) | Yes (token) | Contact support |
Frequently asked questions
How can I tell if a page has an invisible CAPTCHA?
Check the page source for CAPTCHA provider scripts. Look for recaptcha/api.js?render= (reCAPTCHA v3), challenges.cloudflare.com/turnstile (Turnstile), or hcaptcha.com/1/api.js with data-size="invisible" (hCaptcha passive). The CAPTCHA widget has no visible presence on the page, so you must inspect the HTML or network requests.
Does an invisible CAPTCHA still generate a token?
Yes. Invisible CAPTCHAs generate tokens that must be included in form submissions. The token is placed in a hidden form field or sent as a request parameter. API-based solvers generate these tokens externally.
Can invisible CAPTCHAs block my automation without showing any error?
Yes. If your automation does not include a valid CAPTCHA token in the form submission, the server will reject the request silently or return a generic error. There will be no visible CAPTCHA challenge — the request simply fails because the token is missing or invalid.
Is reCAPTCHA v3 more secure than reCAPTCHA v2?
reCAPTCHA v3 is harder to detect visually (no widget on page) but not necessarily more secure. v3 returns a score that the website must act on — if the threshold is set too low, bots pass easily. v2 forces a definitive challenge/response. In practice, v3 with a strict threshold (0.7+) plus v2 as fallback provides the best security.
Summary
Invisible CAPTCHAs verify users through background JavaScript analysis of browser behavior, device fingerprints, and network reputation — without any visible interaction. reCAPTCHA v3 and Cloudflare Turnstile are the dominant implementations, with Turnstile growing fastest due to its free pricing and privacy-first design. For automation, invisible CAPTCHAs still require valid tokens. Use CaptchaAI to generate these tokens: reCAPTCHA v3 via the userrecaptcha method with version=v3, and Cloudflare Turnstile via the turnstile method with a 100% success rate.
Discussions (0)
Join the conversation
Sign in to share your opinion.
Sign InNo comments yet.