[BUG] Claude-in-Chrome: Browser extension persistently fails to connect from CLI

Open 💬 21 comments Opened Feb 10, 2026 by NandoTheessen

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

The Claude-in-Chrome browser extension consistently fails to connect when invoked from Claude Code CLI. Every MCP tool call (tabs_context_mcp, switch_browser, etc.) returns the same error:

Browser extension is not connected. Please ensure the Claude browser extension is installed and running...

The connection never establishes despite extensive troubleshooting across multiple sessions.

Troubleshooting Already Attempted

  • Reinstalled/re-enabled the Chrome extension multiple times
  • Restarted Chrome multiple times
  • Restarted Claude Code CLI multiple times
  • Logged out and re-logged into claude.ai on all devices
  • Clicked the extension icon / checked for "Connect" button in extension popup
  • Tried switch_browser MCP tool to re-initiate connection
  • Issue persists across multiple separate CLI sessions over multiple days

Error Message

Browser extension is not connected. Please ensure the Claude browser extension is installed and running
(https://claude.ai/chrome), and that you are logged into claude.ai with the same account as Claude Code.
If this is your first time connecting to Chrome, you may need to restart Chrome for the installation to
take effect.

This exact same message is returned for all MCP browser tools attempted:

  • tabs_context_mcp (with createIfEmpty: true)
  • switch_browser

Environment

  • Claude Code version: 2.1.38
  • OS: macOS 26.2 (Build 25C56)
  • Architecture: Apple Silicon (arm64)
  • Chrome version: 144.0.7559.133
  • Node.js: v23.6.0
  • Model: claude-opus-4-6

Expected Behavior

tabs_context_mcp should establish a connection to the Chrome extension and return available tab context, allowing browser automation tools to function.

Actual Behavior

All MCP browser tool calls fail immediately with the "Browser extension is not connected" error. No connection is ever established regardless of troubleshooting steps taken.

Additional Context

  • The issue has persisted across multiple days and sessions, not a one-time failure
  • No additional error details or logs are surfaced beyond the generic connection error message
  • It's unclear whether the issue is on the CLI/MCP side or the extension side, as no diagnostic info is provided
  • In a previous session, the MCP bridge appeared to reject connection requests due to a user identity mismatch — the authenticated user on the Claude Code CLI side did not match the authenticated user on the Chrome extension / claude.ai side. The user

verified they were logged into the same account on both sides and re-authenticated on all devices, but the issue persisted. This suggests a possible bug in the authentication/session handshake between the CLI and the browser extension bridge, where
stale session tokens or cached identity state may cause a permanent mismatch even after re-login.

What Should Happen?

Claude Code CLI should be able to use the browser.

Error Messages/Logs

Steps to Reproduce

  1. Install Claude-in-Chrome extension in Chrome
  2. Log into claude.ai in the browser
  3. Start a Claude Code CLI session
  4. Call any mcp__claude-in-chrome__* tool (e.g., tabs_context_mcp with createIfEmpty: true)
  5. Observe: always returns "Browser extension is not connected" error

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

v2.1.38

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

Also present in VsCode Extension

View original on GitHub ↗

21 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/20997
  2. https://github.com/anthropics/claude-code/issues/23662
  3. https://github.com/anthropics/claude-code/issues/20298

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

liransmartlighthouse · 5 months ago

Cross-platform confirmation: Same issue on Linux (Ubuntu/Zorin 17.3)

Experiencing the identical "Invalid token or user mismatch" bridge rejection on Linux with v2.1.38.

Environment

  • OS: Zorin OS 17.3 (Ubuntu-based, kernel 6.8.0-94-generic)
  • Claude Code: v2.1.38
  • Chrome: Google Chrome (/opt/google/chrome/chrome)
  • Extension: v1.0.47 (ID: fcoeoabgfenejglbffodgkkbkcdhcgfn)
  • Plan: Max ($200/mo)
  • Auth: Same account (liran@smartlighthouse.com) confirmed on both CLI (/status) and claude.ai

Diagnostic findings

Everything below the bridge is healthy:

| Component | Status |
|-----------|--------|
| Native messaging host manifest | Correct (~/.config/google-chrome/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json) |
| Native host binary | Points to correct version (~/.local/share/claude/versions/2.1.38) |
| Chrome spawns native host | Confirmed (PID 2426014, parent = Chrome PID 2425776) |
| Unix socket created | /tmp/claude-mcp-browser-bridge-liran/2426014.sock — listening |
| Socket accepts connections | Verified via Python socket.connect() |
| Extension detected by CC | Extension fcoeoabgfenejglbffodgkkbkcdhcgfn found in chrome Default |

The failure is specifically in the WebSocket bridge handshake:

[Claude in Chrome] Connecting to bridge: wss://bridge.claudeusercontent.com/chrome/68a474fc-...
[Claude in Chrome] WebSocket connected, sending connect message
[Claude in Chrome] Bridge received: {"type":"error","error":"Invalid token or user mismatch"}
[Claude in Chrome] Bridge connection closed (code: 1008, duration: 0ms)

This repeats indefinitely (30+ attempts observed) with exponential backoff capping at 30s intervals. Every retry fetches a fresh OAuth token, connects successfully to the WebSocket, then gets immediately rejected by the bridge.

What was tried (none helped)

  • Fresh login on claude.ai (log out + log back in)
  • New Claude Code session
  • Restarting Chrome
  • Confirmed same email on both sides

Key observation

The bridge uses cloud-based WebSocket pairing (wss://bridge.claudeusercontent.com), not the local Unix socket. CC's OAuth token is rejected server-side despite being for the correct account. This suggests the issue is in the bridge's token validation logic, not in the local native messaging setup.

The debug log (~/.claude/debug/) does not log actual token values — only that it "Fetches OAuth token" before each attempt. No way to inspect what's being sent vs. what's expected without server-side logs.

NickSdot · 5 months ago

For some reason

~/.claude/chrome/chrome-native-host

contains a hard-coded version

exec "/Users/Nick/.local/share/claude/versions/2.1.21" --chrome-native-host

which seems to cause different kind of troubles. After changing it too

exec "/Users/Nick/.local/bin/claude" --chrome-native-host

things worked smoother for me.

Hyeong-soo · 5 months ago

Additional findings: existing workaround is incomplete when token becomes stale

I hit this same issue (macOS, Claude Code v2.1.41, Chrome extension v1.0.49) and found that the commonly suggested workaround (disable Desktop's native messaging manifest + restart Chrome) is not sufficient when the extension's OAuth token has already gone stale.

Root cause chain

  1. Claude Desktop's native host (com.anthropic.claude_browser_extension) intercepts the Chrome extension connection before Claude Code's host (com.anthropic.claude_code_browser_extension)
  2. While Desktop's native host holds the connection, the extension's normal token refresh cycle breaks
  3. The extension's accessToken remains in local storage with a valid tokenExpiry, but is actually revoked server-side
  4. After disabling Desktop's manifest and reconnecting, the bridge rejects with "Invalid token or user mismatch" — even though it's the same account
  5. Re-authenticating via Claude Code CLI (/login) resolves the token mismatch

Debugging evidence

  • chrome.storage.local showed mcpConnected: false, valid bridgeDeviceId, accessToken with unexpired tokenExpiry
  • Manual WebSocket to wss://bridge.claudeusercontent.com succeeded (connection opened)
  • Sending {type: "connect", client_type: "chrome-extension", device_id: ..., oauth_token: ...} returned {"type":"error","error":"Invalid token or user mismatch"} followed by close code 1008
  • CLI and extension had different token prefixes (sk-ant-oat01-mQoW... vs sk-ant-oat01-NQ5W...) despite being the same account
  • After re-login via CLI, bridge pairing succeeded

Suggested workaround update

The workaround should include an additional step:

  1. Disable Desktop's native messaging manifest (rename com.anthropic.claude_browser_extension.json to .disabled)
  2. Restart Chrome
  3. Re-authenticate Claude Code CLI (/login) to refresh the OAuth token
  4. Start Claude Code with claude --chrome
olegiv · 5 months ago

Additional confirmation: macOS, Claude Code v2.1.42

Same "Invalid token or user mismatch" bridge rejection.

Environment:

  • macOS Darwin 25.2.0 (Apple Silicon)
  • Claude Code v2.1.42
  • Chrome extension fcoeoabgfenejglbffodgkkbkcdhcgfn (profile: Default)

Root cause found: Claude Desktop native host hijacking

Claude Desktop's manifest (com.anthropic.claude_browser_extension.json) claims the same extension ID, so Chrome spawns Desktop's host instead of Claude Code's:

PID 42954: /Applications/Claude.app/Contents/Helpers/chrome-native-host chrome-extension://fcoeoabgfenejglbffodgkkbkcdhcgfn/

After disabling Desktop's manifest + Chrome restart + CLI re-login (/login):

Bridge still rejects every attempt:

[Claude in Chrome] Connecting to bridge: wss://bridge.claudeusercontent.com/chrome/746fee22-...
[Claude in Chrome] Bridge received: {"type":"error","error":"Invalid token or user mismatch"}
[Claude in Chrome] Bridge connection closed (code: 1008, duration: 0ms)

Retries indefinitely with backoff (10+ attempts observed). The token mismatch persists even after fresh /login on the CLI side, confirming this is a server-side issue in the bridge's token validation — not a local configuration problem.

olegiv · 5 months ago

Follow-up: The /login command opens Safari (macOS default browser) instead of Chrome for OAuth authentication. This likely contributes to the token mismatch — the CLI gets a token issued through a Safari session, while the bridge expects it to match the Chrome session on claude.ai.

This could be a separate issue: /login should either open the auth flow in Chrome specifically (since that's where the extension lives), or the bridge should accept tokens regardless of which browser issued them.

olegiv · 5 months ago

RESOLVED — working fix:

  1. Set Chrome as default browser (so /login opens OAuth in Chrome, not Safari/other)
  2. Run /login to re-authenticate
  3. Start a fresh session with claude --chrome

The root cause: /login opens the OS default browser for OAuth. If that's not Chrome, the token is issued through a different browser session than where the extension lives, causing the bridge to reject with "Invalid token or user mismatch."

Summary of full fix if Claude Desktop is also installed:

  1. Disable Desktop's native messaging manifest (rename com.anthropic.claude_browser_extension.json to .disabled in Chrome's NativeMessagingHosts directory)
  2. Set Chrome as default browser
  3. /login to re-authenticate through Chrome
  4. Restart Chrome
  5. claude --chrome
anton000 · 5 months ago

Environment

  • AlmaLinux 8 (Linux)
  • Chrome running on Xvfb virtual display (:1) with noVNC for remote access
  • Claude Code CLI (v2.1.42+), started with --chrome flag
  • Chrome v144.0.7559.59 with Claude extension v1.0.49

Issue

Browser extension failed to connect after initial working session. All MCP browser tool calls returned:

Browser extension is not connected
  • Extension installed and enabled
  • Logged into claude.ai in browser
  • Native messaging host configured correctly
  • Socket existed in /tmp/claude-mcp-browser-bridge-root/
  • No errors in extension service worker console
  • Connection still failed

Root Cause

The MCP server process (--claude-in-chrome-mcp) retained stale OAuth tokens after running /login to re-authenticate.**

The MCP server started at session initialization and continued running with old credentials even after the CLI re-authenticated. The native host process (--chrome-native-host) restarted with Chrome, but the MCP server did not.

Solution
Restart the MCP server process after re-authentication:

# 1. Re-authenticate
/login

# 2. Kill the old MCP server process (find PID first)
ps aux | grep "claude-in-chrome-mcp"
kill <PID>

# 3. Restart Chrome (this triggers fresh MCP server + native host)
pkill chrome
DISPLAY=:1 google-chrome --no-sandbox --disable-gpu &

# 4. Wait ~5 seconds, then test connection
# Browser tools should now work
Nachx639 · 5 months ago

Root cause found: cloud bridge vs local socket transport

After extensive debugging (binary analysis of Claude Code, process tracing, socket inspection), I found the actual root cause of why the bridge rejects with "Invalid token or user mismatch":

The MCP server (--claude-in-chrome-mcp) has two transport modes:

  1. Local Unix socket — connects directly to the native host's socket at /tmp/claude-mcp-browser-bridge-<user>/<pid>.sock
  2. Cloud WebSocket bridge — connects to wss://bridge.claudeusercontent.com (requires valid OAuth token matching on both sides)

A GrowthBook feature flag called tengu_copper_bridge controls which transport is used. When set to true (the default for many users), it uses the cloud bridge — which is where all the token mismatch errors come from.

The fix

Edit ~/.claude.json (NOT ~/.claude/settings.json) and set the flag to false:

{
  "cachedGrowthBookFeatures": {
    "tengu_copper_bridge": false
  }
}

If cachedGrowthBookFeatures already exists with other keys, just add/change tengu_copper_bridge to false.

Then restart your session:

claude --chrome

Why this works

Setting tengu_copper_bridge: false forces the MCP server to use the local Unix socket instead of the cloud WebSocket bridge. This completely bypasses the OAuth token validation that causes the "Invalid token or user mismatch" error. The local socket connects directly to the native host process — no cloud authentication needed.

Technical details

  • The binary function W9("tengu_copper_bridge", false) reads from QR().cachedGrowthBookFeatures in ~/.claude.json
  • The flag is periodically re-cached from Anthropic's GrowthBook servers, so it may revert to true — if the error returns, just set it back to false
  • This explains why some users see the issue intermittently: the flag value changes server-side via feature rollout
  • All the other workarounds (re-login, changing default browser, killing processes) are addressing symptoms of the cloud bridge auth, not the root cause

Environment where this was confirmed

  • macOS Darwin 25.3.0 (Apple Silicon)
  • Claude Code v2.1.42
  • Chrome extension v1.0.47+
  • OAuth authentication (claude.ai)

After applying this fix, all mcp__claude-in-chrome__* tools work immediately without any OAuth dance, browser restarts, or /login re-authentication.

romain-verbeke · 4 months ago

It looks like this file ~/.claude.json is being overwritten all the time by claude code, when i set tengu_copper_bridge to false, it is set back to true when i start claude --chrome

Nachx639 · 4 months ago

@AshDevFr Yeah, that's expected — Claude Code re-fetches GrowthBook feature flags from Anthropic's servers on every startup and overwrites cachedGrowthBookFeatures in ~/.claude.json.

Permanent fix: Add a SessionStart hook that patches it back automatically before the MCP connection attempt. In ~/.claude/settings.json:

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "sed -i '' 's/\"tengu_copper_bridge\": true/\"tengu_copper_bridge\": false/' ~/.claude.json"
          }
        ]
      }
    ]
  }
}
Note: On Linux, use sed -i (without the '') instead.

This runs on every session start (new, resume, clear, compact), so the flag is always false by the time Chrome tries to connect. No more manual edits.

patrick-work-syd · 4 months ago

Confirmed: competing native host registrations cause silent failures

patrick-work-syd · 4 months ago

Confirmed: competing native host registrations cause silent failures

On systems with both Claude Desktop (Cowork) and Claude Code installed, two native messaging hosts are registered:

  • com.anthropic.claude_browser_extension (Claude Desktop)
  • com.anthropic.claude_code_browser_extension (Claude Code)

The Chrome extension (fcoeoabgfenejglbffodgkkbkcdhcgfn) looks for com.anthropic.claude_browser_extension -- not the _code_ variant. If Claude Desktop's manifest points to an invalid path (e.g., after uninstall or update), the extension can't start the native host.

Fix: Ensure HKCU\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.anthropic.claude_browser_extension points to Claude Code's manifest at %USERPROFILE%\.claude\chrome\com.anthropic.claude_browser_extension.json.

However, this alone won't fix it if tengu_copper_bridge is true -- see #24935 for the complete solution.

ardianys · 4 months ago
{ "hooks": { "SessionStart": [ { "hooks": [ { "type": "command", "command": "sed -i '' 's/\"tengu_copper_bridge\": true/\"tengu_copper_bridge\": false/' ~/.claude.json" } ] } ] } }

@Nachx639 thank you very much, it helps me save lot of times

TheNapse · 4 months ago
RESOLVED — working fix: 1. Set Chrome as default browser (so /login opens OAuth in Chrome, not Safari/other) 2. Run /login to re-authenticate 3. Start a fresh session with claude --chrome The root cause: /login opens the OS default browser for OAuth. If that's not Chrome, the token is issued through a different browser session than where the extension lives, causing the bridge to reject with "Invalid token or user mismatch." Summary of full fix if Claude Desktop is also installed: 1. Disable Desktop's native messaging manifest (rename com.anthropic.claude_browser_extension.json to .disabled in Chrome's NativeMessagingHosts directory) 2. Set Chrome as default browser 3. /login to re-authenticate through Chrome 4. Restart Chrome 5. claude --chrome

Thanks @olegiv,

I had multiple Browser Profiles in Chrome. I was only able to connect Claude Code in one Profile, the other Profiles did not work and were unable to communicate with claude-code. Your solution via re-login and authenticate, then restart worked perfectly for me.

Specs:
MacOS 26.2
Chrome 145.0.7632.77
Claude Code 2.1.47
Claude Extension 1.0.53
Warp Terminal 145.0.7632.77

acud · 4 months ago

I'm having similar problems.

Setup:
Chrome - version 143.0.7499.192 (Official Build) (64-bit)
OS: Manjaro Sway 6.18.7-1-MANJARO
Claude Code v2.1.62, extension v1.0.56

Claude CLI reports the MCP is connected. Hitting reconnect shows all green and that reconnection has been successful, however interactions with the extension fail repeatedly. Restart Claude or Chrome doesn't help, however, the only workaround I've found so far is to tell the Claude extension to log in again. Furthermore, it appears to lose the login consistently (from one day to another, and sometimes intra-day).

patrick-work-syd · 4 months ago

Simplest fix is to have claude update any documentation in case of issues with resume (ok 9 times out of 10) then /exit and immediately log back in with the resume code, for example: claude --dangerously-skip-permissions --chrome --resume 957719b4-194a-4f57-90a1-8d269e3xxxx then /chrome then reconnect. The chrome extension should then work. If you have never used resume, it essentially allows you to continue your session without memory loss - very handy for this case!

sinhpn92 · 4 months ago
claude --dangerously-skip-permissions --chrome --resume

I have connected. But when I prompt open https://google.com, it says brower not connected

<img width="1579" height="240" alt="Image" src="https://github.com/user-attachments/assets/b95e7431-0642-48c5-a84f-79c89db269ee" />

bbopen · 4 months ago

Cross-posting a working fix from #24935: the sed / JSON-editing workarounds fail because the chrome MCP runs in-process (not as a child subprocess), so editing ~/.claude.json has no effect on the running GrowthBook in-memory state.

The reliable workaround is CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1, which prevents GrowthBook from initializing and keeps tengu_copper_bridge at its JSON-cached value (false):

sed -i '' 's/"tengu_copper_bridge": true/"tengu_copper_bridge": false/' ~/.claude.json
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 claude --chrome

Users with both Claude Desktop and Claude Code also need to disable Desktop's native messaging manifest — see full details in #24935.

houserooms · 3 months ago

Same issue here. macOS Sequoia, Claude Code desktop app, Chrome extension v1.0.63. Worked reliably for weeks, broke around 20 March. Extension shows connected in Chrome but tabs_context_mcp always returns not connected. Tried everything — restart Chrome, reconnect extension, switch orgs, create missing native messaging host file. Nothing works. Filed #38845 with full details.

TaikiSuga · 1 month ago

Root cause on the macOS Desktop app: bridge WebSocket TLS chain verification fails in the bundled Electron/Node runtime

Adding a precise, reproducible root-cause from the macOS Desktop app (distinct from the CLI / tengu_copper_bridge path discussed earlier in this thread).

Environment

  • Claude Desktop app 1.9659.2 (Electron), embedded claude-code 2.1.156
  • macOS 26.5 (arm64), Google Chrome 148, Claude extension 1.0.74
  • OAuth auth (keychain), no system proxy, Chrome is the default browser

Symptom (~/Library/Logs/Claude/main.log):

[Claude in Chrome] Connecting to bridge: wss://bridge.claudeusercontent.com/chrome/<id>
[Claude in Chrome] Bridge WebSocket error after ~30ms: unable to get issuer certificate; if the root CA is installed locally, try running Node.js with --use-system-ca
[Claude in Chrome] Bridge connection closed (code: 1006, duration: 0ms)

Retries every 30s indefinitely; list_connected_browsers and the Claude in Chrome tools return "not connected". The local native-messaging host (chrome-native-host) is healthy — the Control Chrome MCP (native-host path) works fine; only the cloud bridge WebSocket is affected.

Root cause
bridge.claudeusercontent.com serves a valid public chain:

claudeusercontent.com  ->  GTS WE1  ->  GTS Root R4  ->  GlobalSign Root CA   (cross-signed)

The macOS system trust store verifies this fine (openssl s_client … -> verify return:1), but the app's bundled Node/BoringSSL runtime cannot build the chain to the cross-signed anchor and fails with UNABLE_TO_GET_ISSUER_CERT. Reproduced with standalone Node v22.22.0 (both https and undici/fetch fail).

Why env-var workarounds do not fix the Desktop app

  • NODE_EXTRA_CA_CERTS=<macOS system roots PEM> makes standalone Node succeed (server returns HTTP 426 upgrade).
  • But setting it for the app via launchctl setenv does not help: the Electron main process inherits it, yet every Electron helper/utility process has it absent (ps eww shows no NODE_EXTRA_CA_CERTS on any Claude Helper). The bridge TLS runs in a helper whose environment Electron sanitizes, so the extra CA never reaches it.
  • --use-system-ca alone does not fix it on Node 22.x.

Suggested fix
Perform the bridge WebSocket TLS via the OS trust store (Chromium net verifier), or bundle/propagate the GTS Root R4 / GlobalSign Root CA cross-sign anchor into the helper process that performs the TLS. This was likely triggered by the recent rotation of bridge.claudeusercontent.com to a Google Trust Services certificate (leaf notBefore 2026-05-17).

Workaround for affected users: use the Control Chrome MCP tools (native messaging host path) — unaffected by this bug.