Skip to content

[Bug]: Environment-hosted browser tabs identify as HeadlessChrome with webdriver set, so sites like CNN and Google refuse to serve them #16638

Description

@josephv123

Before submitting

Area

apps/server

Summary

Tabs in the environment-hosted browser identify themselves as an automated headless browser, so ordinary sites refuse to serve them. This affects every tab of a server without an attached desktop app, such as a remote server opened from the desktop app, the web app, or mobile.

https://www.cnn.com/ shows only Unknown Error. Google search redirects to its "unusual traffic" captcha. In the browser panel this looks like broken links: you click a link and get an error page or a captcha.

Steps to reproduce

  1. Run a T3 server that no desktop app is attached to, such as t3 serve on a Linux machine. Connect to it from the desktop app or the web app.
  2. Open the Browser panel in a thread on that environment. The tab reports runtime: "server".
  3. Go to https://www.cnn.com/.
  4. Go to https://www.google.com/search?q=electron+webview.

Expected behavior

Both pages load as they do in Chrome on the same machine and network.

Actual behavior

  • CNN returns HTTP 200 with a 13-byte body, Unknown Error, from its Fastly/Varnish cache.
  • Google redirects to /sorry/index ("Our systems have detected unusual traffic from your computer network") with a reCAPTCHA.

Inside the tab, navigator.userAgent is Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/154.0.8037.92 Safari/537.36. navigator.userAgentData.brands includes HeadlessChrome, and navigator.webdriver is true.

Root cause

ServerBrowserContexts launches the pinned chrome-headless-shell through Playwright and creates contexts with only a viewport and a scale factor (launch options, context options). That leaves two automation signals in place:

  1. The headless identity. The shell's default user agent and client-hint brands both say HeadlessChrome.
  2. The webdriver flag. Chrome sets navigator.webdriver = true in headless mode on its own. Playwright 1.60 does not pass --enable-automation, and the launch arguments don't contain it. Only --disable-blink-features=AutomationControlled clears the flag.

Sites check different signals. To isolate them, I drove the same chrome-headless-shell 154.0.8037.92 binary with Playwright, from the same machine and IP, in five configurations:

Configuration CNN Google search DuckDuckGo
Current behavior Unknown Error captcha loads
User-agent string without Headless, brands unchanged loads captcha blocked (418 page)
User agent and brands set consistently through Emulation.setUserAgentOverride loads captcha loads
Webdriver flag off only (--disable-blink-features=AutomationControlled) Unknown Error captcha loads
Consistent user agent and brands, webdriver flag off loads loads loads

So CNN keys on the HeadlessChrome user agent and Google needs both signals gone. DuckDuckGo shows that changing only the user-agent string makes things worse: a user agent that disagrees with Sec-CH-UA gets blocked. A fix needs to change both together.

The brands can't be fixed with launch flags. A --user-agent flag changes the user-agent string, but chrome-headless-shell still reports HeadlessChrome in navigator.userAgentData.brands and Sec-CH-UA, so DuckDuckGo still returns its 418 page. The brand list is built into the shell. Adding UserAgentClientHint to --disable-features had no effect. CDP's Emulation.setUserAgentOverride with userAgentMetadata does set both (third row above), but it applies per target, so every page, popup, and worker would need it.

Full Google Chrome in headless mode is different: it already reports the normal Chromium/Google Chrome brands. Only its user-agent string says HeadlessChrome. I ran the same binary-level comparison against more sites, all from the same machine and IP:

Site chrome-headless-shell today Google Chrome 154 headless, --user-agent without Headless, AutomationControlled off
CNN Unknown Error loads
Google search captcha loads
OpenAI Platform (Cloudflare, as in #16596) 403 Just a moment... loads
NYT 403 loads
Stack Overflow Cloudflare "Performing security verification" loads
Reddit "You've been blocked by network security" "Prove your humanity" challenge
DuckDuckGo, Bing, Amazon load load

Workaround for operators: replace ~/.t3/tools/chrome-headless-shell/<platform>/<version>/chrome-headless-shell with a script that runs /usr/bin/google-chrome with the same arguments, plus --user-agent=…Chrome/<major>.0.0.0… and --disable-blink-features=AutomationControlled. T3 only checks that this path is an executable file, so it launches the script. I'm running this on the affected server. Tabs launched through T3 report normal Chrome (webdriver: false, Google Chrome brands), and CNN and Google search load in the browser panel. It has to be reapplied whenever T3 installs a new pinned shell version.

This is not a request to defeat captchas or bot checks. The tab is driven by a human in the browser panel, and the user is the person the site would serve in Chrome. The tab presents as automated only because of how T3 launches its shell.

Impact

Major degradation or frequent failure

Version or commit

T3 Code 0.0.46-nightly.20261006.2735. Code references are at 72d5c32ba6.

Environment

The server is t3 serve as a systemd user service on Ubuntu 26.04 (x86_64), using T3's bundled chrome-headless-shell 154.0.8037.92. The client is the T3 Code (Nightly) desktop app on macOS 26, connected to that server remotely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions