Scarnox · Blog

Headless browser detected: causes and fixes (2026)

A site reports "headless browser detected", or it quietly serves a different page to your automated browser. Sites do this because a headless browser runs without a window and often differs from a normal desktop browser in small, measurable ways. This guide explains which signals sites look at, how to diagnose what your own browser is exposing, and what a sensible fix looks like. It also covers the point where the right answer is to stop, or to treat the check as a captcha step.

Why sites check for headless browsers

Automation frameworks drive a real browser engine, so most of the page works the same. The differences show up at the edges:

Sites combine these signals into a score. A low score can mean a silent downgrade, a set of extra checks, or a block.

Step 1: see what your browser exposes

Before changing anything, look at what a page can read from your automation. The script below opens a page you control and prints the signals that matter. It is a diagnostic: use it on your own test pages, not to probe other people's systems.

from playwright.sync_api import sync_playwright

CHECK = """() => ({
    webdriver: navigator.webdriver,
    languages: navigator.languages,
    plugins: navigator.plugins.length,
    userAgent: navigator.userAgent,
    screen: [screen.width, screen.height],
    viewport: [window.innerWidth, window.innerHeight],
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
})"""

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    page.goto("https://example.com")  # replace with a page you own
    print(page.evaluate(CHECK))
    browser.close()

Run the same script with headless=False, then compare the two outputs. The differences are the things a site could notice.

Step 2: fix the inconsistencies, not just the flags

Hiding one flag while leaving others unchanged is the most common mistake. A user agent that says Windows while the fonts, timezone and screen size describe a Linux server is a stronger signal than a single property. Aim for an environment that is internally consistent:

Playwright lets you set several of these in one place:

context = browser.new_context(
    locale="en-US",
    timezone_id="America/New_York",
    viewport={"width": 1366, "height": 768},
)
page = context.new_page()

Step 3: slow down and act like a visitor

Automation becomes obvious when it is faster than a person can be. Add realistic pauses between page loads, avoid clicking the same element in a perfect rhythm, and do not open hundreds of pages in parallel from one address. Doing fewer, slower requests also reduces the load on the site, which is the right thing to do anyway.

Step 4: know when the check is a captcha

Some detection flows end in a challenge rather than a block. You will see a captcha widget, and that step needs a token from a solver. The live captcha type at Scarnox today is PopularCaptcha. The PopularCaptcha Python guide shows how the token is requested and submitted. Other widgets, such as Cloudflare Turnstile, are on the roadmap but not yet live, so check captcha types explained before you plan around one.

A captcha step does not mean the rest of your setup is sound. If the same site blocks every headless session no matter how you configure it, that is a clear signal the owner does not want automated access. Respect it.

What not to do

Do not try to hide automation from a site that forbids it, and do not use detection-evasion tooling to get past access controls. That is a different kind of project from the testing and public-data collection this guide covers. If your project needs access you have not been granted, ask the site owner or look for an official API or data feed.

Scrape responsibly

Where to go from here

If your automation is for end-to-end tests, the approach is different: see captcha in automated tests. If you are running a Playwright or Puppeteer setup, Playwright and Puppeteer captcha handling explains where the token goes.

Start with free trial credit, no card needed: create an account and test the PopularCaptcha flow on your own page. For current rates, see the pricing page.

Next steps