Headless Chrome runs without a visible window — fast, lightweight, perfect for servers. But CAPTCHA systems actively detect headless mode. Here's how to choose the right mode and solve CAPTCHAs in both.
Quick Comparison
| Factor | Headless Chrome | Headed Chrome |
|---|---|---|
| Speed | Fast (no rendering overhead) | Slower (renders UI) |
| Memory | ~100-200 MB | ~300-500 MB |
| Server deployment | Native | Requires virtual display |
| CAPTCHA detection | High (detectable signals) | Low (looks like real user) |
| reCAPTCHA v3 score | 0.1-0.3 (bot range) | 0.7-0.9 (human range) |
| Debugging | Harder (no visual) | Easy (see the page) |
| Scaling | Excellent (low resources) | Resource-heavy |
How CAPTCHAs Detect Headless Chrome
Detection Signals
// Tests that CAPTCHA systems run
// 1. WebDriver flag (biggest tell)
navigator.webdriver // 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
Detection Test Results
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's "New Headless" Mode (v112+)
Chrome 112+ introduced --headless=new, which uses the same codebase as headed 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)
The new headless mode fixes some detection vectors but still exposes navigator.webdriver and has no plugins.
Headless + CaptchaAI (Python)
CaptchaAI works equally well in headless mode because it solves CAPTCHAs server-side — the browser mode doesn't affect the solving 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("--disable-blink-features=AutomationControlled")
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()
Headed on Servers (Virtual Display)
Run headed Chrome on headless servers using Xvfb:
Linux with Xvfb
# Install
sudo apt-get install xvfb
# Run with virtual display
xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" python script.py
Python with 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 with 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"]
Headless + Stealth Patches (Node.js)
const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra-plugin-stealth");
puppeteer.use(StealthPlugin());
async function headlessStealth() {
const browser = await puppeteer.launch({
headless: "new",
args: [
"--no-sandbox",
"--window-size=1920,1080",
"--disable-blink-features=AutomationControlled",
],
});
const page = await browser.newPage();
await page.setViewport({ width: 1920, height: 1080 });
// Additional stealth 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();
}
When to Use Each Mode
Use Headless When:
- Running on servers/CI without display
- Scaling to 50+ concurrent sessions
- Memory is limited
- CaptchaAI handles all CAPTCHA solving (browser mode irrelevant)
Use Headed When:
- Debugging CAPTCHA flows visually
- reCAPTCHA v3 scores matter (higher scores in headed)
- Target site blocks headless specifically
- Running on machines with displays
Use Headed + Virtual Display When:
- Need headed-level detection resistance on servers
- reCAPTCHA v3 gives low scores in headless
- Budget allows the extra memory (~2x per session)
Performance Benchmarks
| Scenario | Headless | Headed | Headed + Xvfb |
|---|---|---|---|
| Startup time | ~1s | ~2s | ~2.5s |
| Memory per tab | 100-200 MB | 300-500 MB | 300-500 MB |
| Page load (avg) | 1.5s | 2.5s | 2.5s |
| reCAPTCHA v3 score | 0.1-0.3 | 0.7-0.9 | 0.5-0.8 |
| Max concurrent (8GB) | 30-40 | 10-15 | 10-15 |
| CAPTCHA solve rate | Same (API) | Same (API) | Same (API) |
Key insight: CaptchaAI solve rates are identical regardless of browser mode. The mode only affects how often CAPTCHAs appear and reCAPTCHA v3 scores.
Troubleshooting
| Issue | Cause | Fix |
|---|---|---|
| Headless detected | navigator.webdriver flag |
Use stealth plugin or CDP patches |
| Low v3 scores in headless | Missing rendering signals | Switch to headed + Xvfb |
| Xvfb crash | Display number conflict | Use --auto-servernum |
| High memory in headed | GPU process | Add --disable-gpu flag |
| Screenshots blank in headless | Wrong viewport | Set --window-size=1920,1080 |
FAQ
Does CaptchaAI care if I use headless or headed?
No. CaptchaAI solves CAPTCHAs server-side using the sitekey and URL. The browser mode doesn't affect solving.
Is the new headless mode (--headless=new) safe from detection?
It's better than old headless but still detectable. Sites checking navigator.webdriver or plugin count will still flag it.
Can I get reCAPTCHA v3 scores above 0.7 in headless?
Rarely. Headless mode produces bot-like signals. Use headed + Xvfb for higher scores, or use CaptchaAI's v3 solving which returns high-score tokens.
Should I invest in stealth patches or just use CaptchaAI?
Both. Stealth reduces CAPTCHA frequency (fewer solves = lower cost). CaptchaAI handles the CAPTCHAs that still appear.
Related Guides
- Browser Fingerprinting and CAPTCHA
- Puppeteer Stealth + CaptchaAI
- Chrome DevTools Protocol + CaptchaAI
Choose the right browser mode for your CAPTCHA workflow — get your CaptchaAI key and solve CAPTCHAs in any configuration.
Discussions (0)
Join the conversation
Sign in to share your opinion.
Sign InNo comments yet.