# agent-browser-stealth ![agent-browser-stealth](assets/hero.png) Stealth fork of [agent-browser](https://github.com/vercel-labs/agent-browser) — connects to your real Chrome, shares your login sessions, and is undetectable by anti-bot systems. For basic usage, commands, and API reference, see the [upstream documentation](https://github.com/vercel-labs/agent-browser). ## Why this fork? real but undetectable fingerprint **agent-browser** launches a fresh browser with an empty profile. You need to log in again, and websites can detect it's automated. **agent-browser-stealth** connects to your existing Chrome. Your cookies, sessions, and browser fingerprint are all real — because it IS your real browser. | | agent-browser | agent-browser-stealth | |---|---|---| | Browser | Launches new Chrome | Connects to your Chrome | | Login state | Empty, need to re-login | Your existing sessions | | Fingerprint | Automation markers present | Your real fingerprint | | User collaboration | Separate window | Same window, take over anytime | | CAPTCHA | Agent stuck | You solve it, agent continues | ## How it works ![how it works](assets/how-it-works.png) Your **agent-browser CLI** talks to a tiny **browser extension** over Chrome **native messaging** — a local inter-process channel, *no network socket, no token, no remote server*. The extension uses `chrome.debugger` to drive the tabs you target in **your own, already-logged-in Chrome**, then hands results back to the CLI. Everything stays on your machine. ![architecture](assets/architecture.png) Each `--session` gets its **own colored Chrome tab group**, so multiple agents can share one real browser concurrently without stepping on each other — or your own tabs. ## Why the extension (not a raw debug port) Other local tools drive Chrome over a raw `--remote-debugging-port` (CDP). Since **Chrome 136**, every such connection pops a blocking **"Allow remote debugging?"** consent dialog — and the port has to be enabled up front. Our extension uses native messaging instead: **install once, then zero per-use confirmation.** | | **agent-browser-stealth** (this extension) | web-access (raw CDP port) | Claude in Chrome (chrome.debugger) | |---|---|---|---| | Connect method | native messaging — no port, no token | `--remote-debugging-port` | `chrome.debugger` | | **"Allow remote debugging?" popup** | **never** ✅ | **every connection** 🔴 | no | | Uses your real login | yes | yes | yes | | `Runtime.enable` (CDP) leak¹ | **off by default → clean** ✅ | domain enabled | n/a | | CreepJS stealth score² | **0% stealth · 0% headless** ✅ | real Chrome | real Chrome | | Per-session tab groups / concurrent agents | **yes** ✅ | no | no | | Built for the agent-browser CLI | yes | a separate proxy | a single-app assistant | > ¹ Verified against [rebrowser-bot-detector](https://bot-detector.rebrowser.net/): > our relay reports `runtimeEnableLeak: 🟢 No leak` and `navigatorWebdriver: 🟢`. > ² Verified against [CreepJS](https://abrahamjuliot.github.io/creepjs/) on the > connected real-Chrome path — see [Anti-detection](#anti-detection). > > The consent dialog isn't hypothetical: a raw-port tool pops it on **every** > attach (Chrome 136+ security). The extension path never does. ## Install ```bash curl -fsSL https://raw.githubusercontent.com/leeguooooo/agent-browser-stealth/main/install.sh | sh ``` Downloads the prebuilt binary for your platform from the latest [GitHub Release](https://github.com/leeguooooo/agent-browser-stealth/releases) and installs `agent-browser` (+ the `abs` alias). No npm, no tokens.
Other ways to install - **Pin a version:** `AGENT_BROWSER_VERSION=v0.27.0-fork.12 curl -fsSL https://raw.githubusercontent.com/leeguooooo/agent-browser-stealth/main/install.sh | sh` - **Custom location:** `AGENT_BROWSER_BIN_DIR=$HOME/bin curl -fsSL … | sh` - **Windows:** download `agent-browser-win32-x64.tar.gz` from the [Releases page](https://github.com/leeguooooo/agent-browser-stealth/releases) and put `agent-browser.exe` on your PATH. - **npm (legacy):** `npm install -g agent-browser-stealth` — still published, but GitHub Releases is the primary channel now.
### Install the AI agent skills The repo ships SKILL.md files for Claude Code, Cursor, etc. Pull them into the current project with [skills.sh](https://skills.sh): ```bash npx skills add leeguooooo/agent-browser-stealth ``` This drops `skills/agent-browser` (and the specialized `skill-data/{core,electron,slack,dogfood,agentcore,vercel-sandbox}`) into your project so your AI agent gets the right usage patterns and pre-approved bash permissions for `agent-browser`, `agent-browser-stealth`, and `abs`. ## Command names `agent-browser`, `agent-browser-stealth`, and `abs` are **the same binary** — `abs` is just a short alias. There is no separate "stealth executable"; stealth is a runtime behavior (see [Anti-detection](#anti-detection) below), applied automatically based on whether you attach to your real Chrome or `--launch` a fresh one. ## Setup: connect to your Chrome Attaching uses the Chrome DevTools Protocol, which Chrome only exposes when it is **launched with a remote-debugging port**. This is a startup flag, not a setting — the `chrome://inspect` toggle alone is **not** enough (it only enables target discovery, not the CDP attach). **Recommended — fully quit Chrome, then relaunch with the port:** ```bash # macOS open -a "Google Chrome" --args --remote-debugging-port=9222 # Linux google-chrome --remote-debugging-port=9222 # Windows: add --remote-debugging-port=9222 to your Chrome shortcut's target ``` Then run `agent-browser open ` — it auto-discovers the port and attaches. On first attach, **Chrome 136+ shows an "Allow remote debugging?" dialog — click Allow once** (it persists for that Chrome session). **No setup / don't want to touch your real Chrome?** Use `agent-browser --launch open ` to spawn a fresh isolated stealth browser (full anti-detection patches applied; see below). This always works without any port setup and is what CI uses automatically. ## Usage ```bash # Connect to your Chrome and navigate agent-browser open https://example.com # Everything works through your logged-in browser agent-browser click "Post" agent-browser fill "Title" "Hello World" agent-browser screenshot ./page.png ``` The agent operates in your Chrome — you'll see tabs opening, pages loading, clicks happening in real time. You can take over at any point (e.g. solve a CAPTCHA), then let the agent continue. ### Standalone mode (`--launch`) Spawn a separate browser instead of attaching to your running Chrome: ```bash # Throwaway: fresh, EMPTY profile — no cookies, no login (good for CI/testing) agent-browser --launch open https://example.com # Keep your login: launch with your real Chrome profile (cookies/sessions intact) agent-browser --launch --profile auto open https://x.com/home # or name it explicitly: --profile Default / --profile "Profile 1" ``` > ⚠️ Plain `--launch` (no `--profile`) uses a **temporary empty profile** — you will > NOT be logged into anything. For logged-in sites use `--profile auto` (picks the > Chrome profile you used most recently) or `--profile `. agent-browser prints > a warning when you `--launch` without a profile. In CI environments, standalone mode is used automatically. ## Anti-detection stealth shield When connected to your real Chrome, we inject **zero** JavaScript patches. Your browser's fingerprint is completely genuine. The guiding rule is **native CDP/Chrome overrides over JS lies** — a re-defined getter is itself detectable; a native override isn't. - `navigator.webdriver = false` via `Emulation.setAutomationOverride` (native, undetectable by CreepJS-style lie tests). - **`Runtime.enable` is left OFF by default.** A live `Runtime` domain is a detectable CDP signal (the patchright/rebrowser "runtime leak") — even when attached to your real Chrome. We only enable it when you opt into console/error capture (see below). `click`, `fill`, `eval`, etc. work without it. **Test results (connected to real Chrome):** | Test site | Result | |---|---| | [CreepJS](https://abrahamjuliot.github.io/creepjs/) | **0% stealth · 0% headless** (no override traces at all) | | [bot.incolumitas.com](https://bot.incolumitas.com/) | all checks OK — `overflowTest`, `overrideTest`, `puppeteerExtraStealthUsed`, worker consistency | | [bot.sannysoft.com](https://bot.sannysoft.com) | all green | | [BrowserScan](https://www.browserscan.net/bot-detection) | Webdriver · User-Agent · CDP all clean | | [Cloudflare Turnstile](https://nowsecure.nl) | passed | `0% stealth` on CreepJS is the key number: because the connect path patches **nothing**, there is no override for a lie-detector to catch. (Dashboards that read `navigator.languages` order or IP geolocation may show a soft "navigator"/"location" flag — that tracks *your real Chrome's* language list and network, not an automation tell.) When using `--launch` mode (standalone browser), a full suite of stealth patches is applied instead, and it still passes the suite above. ### Verify it yourself Don't take our word for it — point your connected Chrome at the toughest public detectors and compare: - **[CreepJS](https://abrahamjuliot.github.io/creepjs/)** — the most thorough fingerprint / lie detector - **[bot.incolumitas.com](https://bot.incolumitas.com/)** — behavioral + fingerprint scoring with a public methodology - **[BrowserScan](https://www.browserscan.net/bot-detection)** — Webdriver / User-Agent / CDP / Navigator - **[bot.sannysoft.com](https://bot.sannysoft.com)** — the classic automation-marker checklist - **[pixelscan.net](https://pixelscan.net/)** · **[iphey.com](https://iphey.com/)** — consistency & identity We deliberately **don't ship our own bot detector** — the strongest, most honest benchmark is the market's best detectors run against your real browser. ### Tuning knobs (environment variables) | Variable | Default | Effect | |---|---|---| | `AGENT_BROWSER_CAPTURE_CONSOLE` | off | Enable `Runtime` domain so `console` / `errors` capture page output. Off keeps the stealthiest profile. | | `AGENT_BROWSER_TIMEZONE` | unset | `--launch` only. An IANA id (e.g. `Asia/Tokyo`) sets the timezone natively (Intl + Date follow, no JS lie) to match a proxy; `auto` derives one from the locale. | | `AGENT_BROWSER_BLOCK_WEBRTC` | auto | `--launch` only. Auto-forces WebRTC through the proxy when one is set (no real-IP leak). `1` hides the local IP without a proxy; `0` opts out. | | `AGENT_BROWSER_HIDE_CANVAS` | off | `--launch` only. Adds session-stable canvas/audio fingerprint noise. Off by default (noise is itself a "lie"). | | `AGENT_BROWSER_ADAPTIVE_REF` | on | When a saved `@ref` moves and the role/name re-query fails, relocate it by fingerprint similarity (high score + clear margin required, else it fails loudly). `0` disables. | | `AGENT_BROWSER_CLICK_MODE` | _(auto)_ | Click strategy. Default scrolls the target into view, dispatches a coordinate click, and falls back to a DOM `.click()` if a floating layer occludes the point. `dom` always uses `.click()` (best for autocomplete/menu items that close on blur); `coord` is strict coordinate-only (hard-fail on occlusion). | ## Differences from upstream Based on [agent-browser v0.27.0](https://github.com/vercel-labs/agent-browser). Changes: - **Auto-connect is default** — `agent-browser open ` connects to your Chrome instead of launching a new one - **CDP-native stealth** — `Emulation.setAutomationOverride` instead of JS patches - **Dual stealth mode** — zero patches for real Chrome, full patches for `--launch` mode - **`--launch` / `--new` flag** — explicitly start a standalone browser - **CI auto-detection** — standalone mode when `CI` env var is set All upstream features (commands, snapshots, screenshots, recordings, tabs, sessions, etc.) work the same. See the [upstream repo](https://github.com/vercel-labs/agent-browser) for full documentation. ## License Apache-2.0 (same as upstream)