Connecting

Real Chrome (Extension)

When a task needs the exact window the user is looking at right now—their real, already-logged-in session, not a fresh blank browser—use extension connect. It takes over the user's real Chrome: zero confirmations, zero tokens, no headless fingerprint. It is the highest anti-detection tier of any connection method.

The link has just four stops: the chrome-use CLI → a per-session daemon → the relay Chrome launches for the extension → the ab-connect extension in the browser. The extension drives pages over Chrome's own debugging protocol, so no remote-debugging port is opened. What each stop speaks and where the state lives is in How It Works.

One-time install

Extension connect only needs to be set up once. First register the native-messaging host, then install the chrome-use extension.

bash
# 1. Register the native-messaging host
$ chrome-use extension install

2. Install the chrome-use extension. The easiest way—and the one that stays stable across restarts—is a one-click Add to Chrome from the Chrome Web Store:

ℹ️ Dev-build fallback (Load unpacked)
chrome://extensions → turn on Developer modeLoad unpacked → pick extensions/ab-connect. Note: a load-unpacked extension may be disabled after Chrome restarts, so prefer the store build for unattended scenarios.

Auto-connect: open takes over

Once the extension is installed, a plain chrome-use open <url> automatically connects through the extension relay. auto_connect_cdp prefers the live relay over a bare --remote-debugging-port, so Chrome 136+'s "Allow remote debugging?" authorization prompt never appears. chrome-use extension connect is the explicit form of the same path.

bash
# With the extension installed, open takes over the real Chrome via the relay
$ chrome-use open "https://example.com"

# The explicit form of the same path
$ chrome-use extension connect
✅ When not to use it
If a fresh, isolated test browser is enough (no real login needed), use --launch—see below.

Multiple Chrome profiles: see which one, then pick it

The relay binds to the extension worker of the profile currently talking to the native host. If a site comes back showing logged out, confirm you took over the right profile before concluding the login was lost.

bash
# List every connected profile (shows email if identity permission is granted, else a stable id, with the default flagged)
$ chrome-use browsers

# Pin "this session" to a specific profile — sticky per session, so different agents don't interfere
$ chrome-use --browser "me@example.com" snapshot

# Check which profile you're currently driving
$ chrome-use extension status
$ chrome-use doctor
ℹ️ sticky per session
--browser <id|email> pins this session to a profile: the session's daemon binds on first connect, each session can pick a different profile, so concurrent agents don't fight over one. Logged out on the wrong profile ≠ login lost—run browsers first, then re-run with the correct --browser.

--launch vs --profile auto

--launch opens an isolated blank test profile—no cookies, no logins, no extensions (so the extension relay path is off). Its window is labeled chrome-use (<session>) in Chrome's profile menu, so anyone watching the desktop can tell at a glance which session the window belongs to. If a launched session needs more:

🔐 Need real cookies / login / extensions

Drop --launch and use --profile auto instead (reuse the user's real Chrome profile), or set AGENT_BROWSER_PROFILE=auto once to make every later call default to it.

🧩 Load an unpacked extension into the test profile

--launch --args "--load-extension=<dir>".

If "Allow remote debugging?" really does pop up

Don't keep retrying—each retry pops it again. At that point there are only two possibilities:

  1. You're on an old version. The relay-preference logic that avoids this prompt shipped many versions ago; if you still hit it, your chrome-use is too old—upgrade and retry:
bash · upgrade
$ curl -fsSL https://raw.githubusercontent.com/leeguooooo/chrome-use/main/install.sh | sh

# If which shows multiple installs, an old npm/pnpm copy may be shadowing the new one
$ which -a chrome-use
$ npm rm -g chrome-use   # or pnpm rm -g chrome-use, so the install.sh version wins
  1. The extension / relay isn't up. Have the user install the store extension (the one-click link above); once installed the relay stays online and this prompt never comes back.

Relay drops: the CLI self-heals

If a command suddenly reports "couldn't reach your Chrome" / "relay … failed"—usually the MV3 service worker got suspended, or two agents are sharing one relay—the CLI now self-heals: it waits for the worker's keepalive to bring the relay back (about 25 seconds) and retries once, so most drops you never even notice. If a command does surface the error:

  1. Just re-run the command—by then the relay has usually reconnected.
  2. Still failing: chrome-use status (check) → chrome-use extension connect (re-attach) → retry. The CLI registers the native host automatically, and opens the store page if the extension was never installed—you don't have to run extension install by hand.
  3. Never have the user quit/restart Chrome with --remote-debugging-port to recover a dropped relay—that loses all their tabs and completely breaks the extension path.
  4. chrome-use reconnect is a friendly alias for extension connect—it rebinds the session to the running Chrome with no reinstall needed.
  5. Browser totally unrecoverable? Don't sit waiting on a screenshot—fall back to non-visual verification: get text / eval, or read the deployed page with curl/WebFetch. Confirm a change is correct via DOM/HTML or the live URL, not a failure. Save screenshots for the visual checks you actually need to report to the user.
✅ Don't serialize agents to dodge "fragility"
A relay drop is transient and self-heals; it is not a signal that a shared browser can't be driven concurrently. Concurrent multi-agent is supported—each --session has its own tab group and drives only its own tabs. Give each agent a distinct --session and run them in parallel instead of one at a time.

OAuth / SSO redirects just work now

A login handoff (GitHub/Google OAuth, SSO) navigates the tab across processes, which used to orphan the old session and make the next read fail with "stale sessionId". The relay now re-attaches the opener automatically across that cross-process navigation and briefly retries the read while the new process stabilizes, so snapshot/screenshot/eval/get keep working through the entire handoff, and "Sign in with Google" / OAuth popup login goes end-to-end.

ℹ️ One GSI iframe limitation
The cross-origin Google GSI iframe (the "Continue as <user>" button) can only be pierced on Chrome 125+; on older Chrome that one button alone may still be out of reach. For more login/credential scenarios see Login & Credentials.

Strict multi-agent isolation

Every connected --session gets its own colored Chrome tab group (named after the session) and drives only its own tabs—multiple agents share one real browser without crossing wires, and the user's own tabs are never grouped. CDP doesn't move the user's mouse/keyboard while driving pages, so it never fights them for control.

ℹ️ Per-agent isolation is automatic
The session name is the isolation key: it maps to a dedicated tab group and a dedicated daemon (the port is derived from the name). When you don't pass --session / AGENT_BROWSER_SESSION, chrome-use auto-derives a per-agent defaultcu-<repo>-<id>, where <id> is a short hash of a stable per-agent terminal/agent-environment id (CMUX_SURFACE_ID, TERM_SESSION_ID, ITERM_SESSION_ID, TMUX_PANE …). So two agents in the same repo get different tab groups by default and no longer step on each other's active tab. In a bare shell with none of those env vars set, it falls back to the shared default. Override anytime: pass --session <name>, or set it to the same value to deliberately have multiple agents share one tab group. (The AGENT_BROWSER_* prefix is inherited from the upstream project—see Lineage for the history.)

A session (over the relay) tracks and drives only the tabs it created itself. Popups opened by your own actions—like the OAuth account picker that pops up when you click "Sign in with Google"—are followed and can be driven as part of your session (switch over and drive that picker). But it does not adopt the user's existing tabs, another agent's tabs, or unrelated popups (a login window the user opened is the user's). Bottom line: tab list shows only your session's tabs; to drive a specific page, navigate to it in one of your own tabs—don't expect an existing or popped-up tab to appear in the list.

No debugging banner on the user's pages

✅ Seamless takeover
The extension attaches Chrome's debugger only to agent-owned tabs (ones it created, or ones you adopt), never to the user's own tabs—so Chrome's "chrome-use started debugging this browser" banner never covers a page the user is using (it only shows on attached tabs, and the agent's are all background tabs). No Chrome restart, fully seamless.

Read a tab the user already has open: adopt

Need to read a tab the user already has open? Use chrome-use adopt <url-substring|targetId>—it finds that existing tab across tab groups (the user's own, or another session's) and drives it, without opening a new tab. When nothing matches it errors and lists the tabs it can see. This is the explicit, opt-in way to cross the isolation layer above (it tags the adopted tab into your session's tab group).

bash · adopt
# Adopt the tab the user is looking at, then do a read-only extraction on it
$ chrome-use adopt "claude.ai/design"
$ chrome-use snapshot
$ chrome-use get text
ℹ️ After adopt, the banner appears on that tab
Because it's exactly the one you explicitly asked to drive. That's expected, not a bug.

Anti-detection tier ranking

This real, logged-in Chrome (extension connect) > a headed launched browser > headless (forbidden). A genuine human browser has no headless / automation tells at all, so prefer it for any anti-bot-sensitive task.

Silent by default

When driving the user's real Chrome, the agent works entirely in the background—new tabs open unfocused, the agent never forces a tab to the front, and focus is emulated so background pages still render and report visibilityState: 'visible'. You don't have to do anything; just don't expect the user's view to follow you (only use an explicit bringToFront when you deliberately want to surface a tab).

Behavioral anti-bot: humanized input

--humanize off|fast|human (or AGENT_BROWSER_HUMANIZE) gives clicks, typing, and scrolling a human cadence; defaults to off, and a per-navigation detector auto-escalates pages guarded by Akamai/PerimeterX/DataDome to human. Trajectory parameters, cadence, and tuning are covered in Stealth & Anti-detection.

Getting past Cloudflare: solve once, reuse

Passing a Cloudflare challenge once mints a cf_clearance cookie bound to your IP + User-Agent; reuse the same egress IP and UA to skip the challenge until it expires, and driving the user's real Chrome (relay) persists it natively. Before spending effort solving, run chrome-use cf-status (aliases cf, clearance) as a preflight to avoid re-solving a challenge you already passed. The full flow, the reissue verdict, and reading the cookie are covered in Stealth & Anti-detection.


Related pages