Comparisons

用于验证码解决的 Headless 与 Headed Chrome

Headless Chrome 运行时没有可见窗口 - 快速、轻量级,非常适合服务器。但验证码系统会主动检测无头模式。以下是如何选择正确的模式并解决两种模式中的验证码问题。


快速比较

因素 headless 模式 headed 模式
速度 快速(无渲染开销) 速度较慢(呈现 UI)
记忆 〜100-200 MB 〜300-500 MB
服务器部署 本国的 需要虚拟显示
验证码检测 高(可检测信号) 低(看起来像真实用户)
reCAPTCHA v3 分数 0.1-0.3(机器人范围) 0.7-0.9(人类范围)
调试 更难(无视觉) 简单(见页面)
缩放 优秀(资源少) 资源密集型

验证码如何检测 Headless Chrome

检测信号

// Tests that CAPTCHA systems run

// 1. WebDriver flag (biggest tell)
navigator.userAgent  // true in headless, undefined in real browser

// 2. Chrome object completeness
window.chrome        // Missing or incomplete in headless

// 3. Plugins
navigator.plugins.length  // 0 in headless, 3+ in headed

// 4. WebGL renderer
// Headless: "SwiftShader Renderer"
// Headed:   "ANGLE (NVIDIA GeForce GTX 1080...)"

// 5. User-Agent contains "Headless"
navigator.userAgent.includes("Headless")  // Old Chrome versions

// 6. Screen dimensions
screen.width === 0   // Some headless configs

// 7. Notification permission
Notification.permission  // "denied" in headless without override

检测结果

Signal               Headed    Headless   New Headless (v112+)
─────────────────────────────────────────────────────────────
webdriver            false     true       true
chrome object        full      partial    improved
plugins              5         0          0
WebGL renderer       ANGLE     Swift      Swift
screen.width         1920      800        800
UA "HeadlessChrome"  no        yes        no (removed)

Chrome 的“新 Headless”模式 (v112+)

Chrome 112+ 引入了 --headless=new,它使用与 Chrome 相同的代码库:

from selenium import webdriver

# Old headless (more detectable)
options = webdriver.ChromeOptions()
options.add_argument("--headless")  # Legacy mode

# New headless (less detectable)
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")  # Shares headed rendering

driver = webdriver.Chrome(options=options)

新的无头模式修复了一些检测向量,但仍然暴露 navigator.userAgent 并且没有插件。


无头 + CaptchaAI (Python)

CaptchaAI 在无头模式下同样工作得很好,因为它在服务器端解决验证码 - 浏览器模式不会影响解决 API:

import requests
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

API_KEY = "YOUR_API_KEY"
API_URL = "https://ocr.captchaai.com"


def create_headless_driver():
    options = webdriver.ChromeOptions()
    options.add_argument("--headless=new")
    options.add_argument("--no-sandbox")
    options.add_argument("--no-sandbox")
    options.add_argument("--window-size=1920,1080")
    options.add_argument(
        "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
    )
    return webdriver.Chrome(options=options)


def solve_captcha(site_url, sitekey):
    resp = requests.post(f"{API_URL}/in.php", data={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": site_url,
        "json": 1,
    })
    task_id = resp.json()["request"]

    for _ in range(60):
        time.sleep(5)
        resp = requests.get(f"{API_URL}/res.php", params={
            "key": API_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = resp.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]

    raise TimeoutError("Solve timeout")


# Full headless workflow
driver = create_headless_driver()

try:
    driver.get("https://example.com/form")
    time.sleep(2)

    sitekey = driver.execute_script(
        "return document.querySelector('[data-sitekey]')?.getAttribute('data-sitekey')"
    )

    if sitekey:
        token = solve_captcha(driver.current_url, sitekey)
        driver.execute_script(f"""
            document.querySelector('#g-recaptcha-response').value = '{token}';
        """)
        driver.find_element(By.CSS_SELECTOR, "form").submit()

finally:
    driver.quit()

面向服务器(虚拟显示)

使用 Xvfb 在无头服务器上运行有头 Chrome:

Linux 与 Xvfb

# Install
sudo apt-get install xvfb

# Run with virtual display
xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" python script.py

Python 与 PyVirtualDisplay

from pyvirtualdisplay import Display
from selenium import webdriver

display = Display(visible=0, size=(1920, 1080))
display.start()

options = webdriver.ChromeOptions()
# No --headless flag = headed mode in virtual display
options.add_argument("--no-sandbox")
options.add_argument("--window-size=1920,1080")

driver = webdriver.Chrome(options=options)
# Now runs headed Chrome with real rendering, but no physical display

Docker 与 Xvfb

FROM python:3.12-slim

RUN apt-get update && apt-get install -y \
    xvfb \
    chromium \
    chromium-driver \
    && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . /app
WORKDIR /app

CMD ["xvfb-run", "--auto-servernum", "python", "main.py"]

无头 + 标准补丁 (Node.js)

const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer (默认配置)");

puppeteer.use(StealthPlugin());

async function headlessStealth() {
  const browser = await puppeteer.launch({
    headless: "new",
    args: [
      "--no-sandbox",
      "--window-size=1920,1080",
      "--no-sandbox",
    ],
  });

  const page = await browser.newPage();
  await page.setViewport({ width: 1920, height: 1080 });

  // Additional QA patches
  await page.evaluateOnNewDocument(() => {
    Object.defineProperty(navigator, "webdriver", {
      get: () => undefined,
    });

    Object.defineProperty(navigator, "plugins", {
      get: () => [1, 2, 3, 4, 5],
    });
  });

  await page.goto("https://example.com/form");

  // Detect and solve CAPTCHA with CaptchaAI
  const sitekey = await page.evaluate(() =>
    document.querySelector("[data-sitekey]")?.getAttribute("data-sitekey")
  );

  if (sitekey) {
    // Call CaptchaAI API (see other guides for full implementation)
    const token = await solveCaptchaAI(page.url(), sitekey);

    await page.evaluate((t) => {
      document.querySelector("#g-recaptcha-response").value = t;
    }, token);
  }

  await browser.close();
}

何时使用每种模式

在以下情况下使用 Headless:

  • 在服务器上运行/CI而不显示
  • 扩展到 50+ 并发会话
  • 内存有限
  • CaptchaAI 处理所有验证码解决(浏览器模式无关)

在以下情况下使用标题:

  • 直观地调试验证码流
  • reCAPTCHA v3 scores matter (higher scores in headed)
  • 目标站点专门阻止无头
  • 在带有显示屏的机器上运行

在以下情况下使用标题 + 虚拟显示:

  • 服务器上需要高级检测阻力
  • reCAPTCHA v3 在 headless 中给出低分
  • 预算允许额外的内存(每个会话约 2 倍)

性能基准

设想 无头 为首 标题 + Xvfb
启动时间 〜1秒 〜2秒 ~2.5秒
每个选项卡的内存 100-200MB 300-500MB 300-500MB
页面加载(平均) 1.5秒 2.5秒 2.5秒
reCAPTCHA v3 分数 0.1-0.3 0.7-0.9 0.5-0.8
最大并发数 (8GB) 30-40 10-15日 10-15日
验证码解决率 相同(API) 相同(API) 相同(API)

关键见解: 无论浏览器模式如何,CaptchaAI 解决率都是相同的。该模式仅影响验证码出现的频率和 reCAPTCHA v3 分数。


故障排除

问题 原因 处理方式
检测到无头 navigator.userAgent 标志 使用隐形插件或 CDP 补丁
headless 中 v3 分数低 缺少渲染信号 切换到 Headed + Xvfb
Xvfb 崩溃 显示号码冲突 使用--auto-servernum
头部记忆力高 GPU进程 添加 --disable-gpu 标志
无头时截图空白 视口错误 设置 --window-size=1920,1080

常问问题

CaptchaAI 关心我使用无头还是有头吗?

不会。CaptchaAI 使用 sitekey 和 URL 在服务器端解析验证码。浏览器模式不影响求解。

新的无头模式 (--headless=new) 是否不会被检测到?

它比旧的无头更好,但仍然可以检测到。检查 navigator.userAgent 或插件计数的站点仍会对其进行标记。

我可以在 Headless 中获得高于 0.7 的 reCAPTCHA v3 分数吗?

很少。无头模式产生类似机器人的信号。使用 head + Xvfb 获得更高分数,或使用 CaptchaAI 的 v3 求解返回高分标记。

我应该投资标准补丁还是只使用 CaptchaAI?

两个都。隐形降低了验证码频率(更少的解决=更低的成本)。 CaptchaAI 处理仍然出现的验证码。


相关指南

  • 浏览器QA 配置和验证码
  • Puppeteer隐身 + CaptchaAI
  • Chrome DevTools 协议 + CaptchaAI

为您的验证码工作流程选择正确的浏览器模式 -获取您的 CaptchaAI 密钥并在任何配置中解决验证码。

该文章已禁用评论。