Explainers

隐形验证码系统解释:它们是如何工作的

隐形验证码验证用户而不显示可见的挑战。无需单击复选框,无需解决图像网格问题,也无需输入文本。验证完全通过 JavaScript 在后台进行,分析浏览器行为、设备信号和网络信誉。如果您的自动化工作流程遇到一个表单,该表单为某些用户干净地提交,但阻止其他用户(页面上没有可见的验证码),那么您正在处理不可见的验证码系统。


隐形验证码如何工作

所有不可见的验证码都遵循相同的核心模式:

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

与可见验证码的主要区别:验证从页面加载的那一刻起就持续运行,而不仅仅是在用户单击复选框时运行。


主要隐形验证码系统

1.reCAPTCHA v3

提供商: 谷歌 发布: 2018 市场份额: 隐形验证码中最高

reCAPTCHA v3 为每个页面操作返回 0.0 到 1.0 之间的浮点分数。网站所有者决定如何处理分数。

它如何收集信号:

<!-- 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>

execute() 调用按需触发信号收集。自脚本加载以来,reCAPTCHA 一直在后台收集数据。

分数解读:

分数 意义 典型动作
0.9 很可能是人类 允许
0.7 可能是人类 允许监控
0.5 不确定 需要额外验证
0.3 可能是机器人 阻止或显示 reCAPTCHA v2
0.1 很有可能是机器人 堵塞

页面源中检测:

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://staging.example.com/qa-login"))

2.Cloudflare Turnstile

提供商: Cloudflare 发布: 2022 年 市场份额: 增长最快

Turnstile 使用多阶段验证管道,无需收集用户数据。

验证阶段:

  1. 私有访问令牌检查 — 如果浏览器支持 Apple PAT,验证会立即完成
  2. 非交互式挑战 - 浏览器解决了轻量级加密工作量证明难题
  3. 托管挑战 — Cloudflare 根据其网络的风险信号在非交互式和交互式之间做出决定(20% 以上的互联网流量流经 Cloudflare)
  4. 互动挑战 — 仅在风险评分较高时显示;显示复选框样式的小部件

一体化:

<!-- Turnstile widget -->
<div class="cf-turnstile" data-sitekey="0x4AAAAAAAC3DHQhMMQ_Rxrg"></div>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

检测:

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 隐形

提供商: 谷歌 发布: 2017

这是在表单提交时以编程方式触发的 reCAPTCHA v2。没有可见的复选框 - 用户单击提交按钮,reCAPTCHA 在后台运行。如果风险评分足够高,则会弹出可见的图像挑战。

一体化:

<button class="g-recaptcha"
        data-sitekey="SITE_KEY"
        data-callback="onSubmit"
        data-size="invisible">
    Submit
</button>

与 v3 的主要区别: v2 Invisible 对于有风险的用户来说仍然是一个可见的挑战。 v3 从未表现出明显的挑战——网站必须决定如何处理分数。

4. hCaptcha 被动(企业)

提供商: 直觉机器 可用性: 仅限企业级

hCaptcha Enterprise 的被动模式在没有任何可见小部件的情况下评估用户。它使用与标准 hCaptcha 相同的行为信号,但仅向最可疑的访问者提出视觉挑战。

5. Apple 私有访问令牌

提供商: 苹果 可用性: iOS 16+、macOS Ventura+

这不是验证码提供程序,而是验证码绕过机制。 Apple 设备通过硬件认证证明其合法性,从而允许网站完全跳过验证码。

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

由 Cloudflare、Fastly 和其他 CDN 提供商支持。


使用 CaptchaAI 解决隐形验证码

不可见的验证码仍然会生成必须与表单一起提交的令牌。基于 API 的求解器在外部生成这些令牌。

解决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://staging.example.com/qa-login",
    "version": "v3",
    "action": "login",
    "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

解决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 — 解决 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,
            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://staging.example.com/qa-login", "login")
    .then((token) => console.log("Token:", token.substring(0, 50) + "..."));

检测不可见的验证码:综合检查器

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)

隐形验证码比较

特征 reCAPTCHA v3 旋转门 reCAPTCHA v2 隐形 h验证码被动
可见的挑战 绝不 很少 有时(后备) 很少
隐私 收集浏览数据 没有个人数据 收集浏览数据 收集交互数据
成本 免费(1M/month) 免费(无限制) 免费(1M/month) 仅限企业
返回分数 是(0.0-1.0) 否(通过/fail) 否(通过/fail) 是(企业)
回退可见的挑战 网站决定 由 Cloudflare 管理 图像网格弹出窗口 图像网格弹出窗口
CaptchaAI 支持 是(v3 令牌) 是(100% 成功) 是(令牌) 联系支持人员

评分政策示例

  • 定义在工作流程达到生产流量之前高、中、低分数会发生什么情况。
  • 使用中等分数的结果来触发升级检查,而不是将低于目标的每个分数都视为失败。
  • 随着时间的推移记录分数分布,因此目标端阈值漂移在转化率下降之前变得可见。

常见问题

如何判断页面是否有不可见的验证码?

检查验证码提供程序脚本的页面源。查找 recaptcha/api.js?render= (reCAPTCHA v3)、challenges.cloudflare.com/turnstile (Turnstile) 或 hcaptcha.com/1/api.jsdata-size="invisible" (hCaptcha 被动)。 CAPTCHA 小部件在页面上不可见,因此您必须检查 HTML 或网络请求。

不可见的验证码是否仍会生成令牌?

是的。不可见的验证码会生成必须包含在表单提交中的令牌。令牌被放置在隐藏的表单字段中或作为请求参数发送。基于 API 的求解器在外部生成这些令牌。

不可见的验证码可以阻止我的自动化而不显示任何错误吗?

是的。如果您的自动化在表单提交中未包含有效的验证码令牌,服务器将静默拒绝请求或返回一般错误。不会有可见的验证码质询——请求只是失败,因为令牌丢失或无效。

reCAPTCHA v3比reCAPTCHA v2更安全吗?

reCAPTCHA v3 更难以视觉检测(页面上没有小部件),但不一定更安全。 v3 返回网站必须采取行动的分数 - 如果阈值设置得太低,机器人很容易通过。 v2 强制提出明确的挑战/response. 实际上,具有严格阈值 (0.7+) 的 v3 加上作为后备的 v2 可提供最佳的安全性。


概括

隐形验证码通过对浏览器行为、设备特征和网络信誉的后台 JavaScript 分析来验证用户,无需任何可见的交互。 reCAPTCHA v3 和 Cloudflare Turnstile 是主要的实现方式,其中 Turnstile 由于其免费定价和隐私优先的设计而增长最快。对于自动化,不可见的验证码仍然需要有效的令牌。使用CaptchaAI生成这些代币:通过 userrecaptcha 方法使用 version=v3 生成 reCAPTCHA v3,通过 turnstile 方法生成 Cloudflare Turnstile,成功率 100%。

相关文章

该文章已禁用评论。