The Problem That Started It
I wanted Claude to control my Brave browser. Not a headless zombie browser that gets blocked everywhere — my real browser, with my real sessions, real cookies, real logged-in accounts.
Every existing tool uses Chrome DevTools Protocol (CDP). CDP sets navigator.webdriver = true. LinkedIn detects it and locks your account. X throws captchas. Gmail flags you as suspicious. Your "automation" gets blocked before it does anything useful.
The Wall. CDP and headless browsers are external tools controlling a browser. Sites detect them because they're supposed to. Extensions are part of the browser itself — same APIs that 1Password and Grammarly use. No site blocks those.
So I built BraveBridge — a Manifest V3 Chrome extension that connects to Claude Code via MCP through a WebSocket bridge. The idea was simple: let AI agents use your real browser sessions without detection.
What I Built
BraveBridge had three components:
AI Agent (Claude Code)
→ MCP Server
→ WebSocket (localhost)
→ BraveBridge Extension
→ Your Browser (Real Sessions)
I exposed 13 MCP tools: navigate, click, type, read_page, screenshot, scroll, key, select_all, read_elements, switch_tab, get_tabs, wait_for, and execute_script.
It worked. Claude could navigate to sites, read pages, click buttons, take screenshots, and type into inputs. I used it to browse X, read LinkedIn feeds, and interact with web apps.
The Hard Lessons
1. Manifest V3 kills your service worker
Chrome's Manifest V3 terminates service workers after 30 seconds of inactivity. Your WebSocket connection just dies. I had to add keepalive hacks: setInterval pings every 20 seconds plus chrome.alarms as a backup. It felt like duct tape.
2. CSS selectors are the wrong abstraction
LinkedIn's post composer? No standard selectors. X's tweet box? React contentEditable wrapped in proprietary components. I couldn't even find the text input on LinkedIn — their editor is completely invisible to CSS selector queries.
I tried every approach: [contenteditable], [role='textbox'], .ql-editor, [data-placeholder]. Nothing worked on modern React SPAs.
3. React contentEditable is a nightmare
On X, typing into the tweet composer garbled text. Hashtags duplicated, words jumbled. React doesn't handle dispatchEvent('input') properly on contentEditable elements. I ended up using a clipboard paste hack with DataTransfer and ClipboardEvent. It worked, but barely.
4. CSP blocks eval on major sites
My execute_script tool used eval() internally. X's Content Security Policy blocks it. I had to refactor to pre-compiled named functions passed to chrome.scripting.executeScript. Every "simple" feature had edge cases.
The Discovery
While debugging LinkedIn's impenetrable composer, I wondered: how does Anthropic's own Chrome extension handle this? They must have solved the same problems.
So I reverse-engineered it.
Key Finding. Claude's "Claude in Chrome" extension uses an accessibility tree instead of CSS selectors. It maps every interactive element to semantic roles (button, link, textbox) with ref IDs. No fragile selectors. No shadow DOM issues. No LinkedIn composer mystery.
Here's what I found when I dug into the extension files:
| BraveBridge (mine) | Claude in Chrome | |
|---|---|---|
| Transport | WebSocket (keepalive hacks) | Native Messaging (stdio) |
| Element targeting | CSS selectors (breaks on SPAs) | Accessibility tree + ref IDs |
| Tools | 13 primitives | 22 tools + GIF recording |
| Page reading | DOM-based (fragile) | Semantic roles (robust) |
| Service worker sleep | Manual keepalive | Native messaging keeps alive |
| Setup | Manual MCP config + server | claude --chrome |
The kill shot
I checked Brave's native messaging directory:
# Brave already has Claude's native messaging config
~/Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts/
com.anthropic.claude_browser_extension.json
The Claude Chrome extension installs in Brave. The native messaging host is already configured. It just works.
Anthropic's docs say "not yet supported on Brave" — but that's just cautious messaging. The config is there. The extension installs. The connection works.
Verdict. I spent days building something that already exists and works better. Classic solo builder mistake: building before researching deeply enough.
Use Cases for AI Browser Automation
Even though BraveBridge is dead, the use cases are very much alive. Here's what AI + real browser access enables:
- Social media automation with your real accounts. Post on LinkedIn, reply to tweets, engage with content — all through natural language commands. No API keys, no OAuth flows, no rate limits. Just your real logged-in session.
- Live debugging web apps. Tell Claude "open localhost:3000, fill the form with invalid data, check if errors appear." It reads console errors, DOM state, and network requests, then fixes your code.
- Authenticated web app automation. Interact with Google Docs, Gmail, Notion, Jira — any app you're logged into. No API connectors needed. Claude uses the same UI you do.
- Data extraction at scale. Pull structured data from web pages, compare prices across sites, monitor competitor changes. Save results as CSV or JSON locally.
- Multi-site workflows. "Check my calendar for tomorrow's meetings, look up each attendee's company, draft prep notes." Claude works across tabs to gather and synthesize information.
- Form filling and data entry. Feed Claude a spreadsheet and tell it to fill a CRM. It reads your CSV, navigates the web interface, and enters data for each record. Hours of work in minutes.
- Design verification. Build a UI from a Figma mock, then ask Claude to open it in the browser, screenshot it, and compare. Catch visual regressions before deployment.
How to Set It Up (The Right Way)
Don't build what I built. Use Claude's official Chrome integration — and yes, it works on Brave.
The Brave Trick. Anthropic's docs say "not yet supported on Brave." But here's what actually works: install the Claude extension in Brave, close Chrome completely, then run
claude --chrome. It connects to Brave instead. Your real Brave sessions, your real logins, fully working. I tested it — posted on LinkedIn with an image, all through natural language.
# 1. Install "Claude" extension from Chrome Web Store into Brave
# 2. Close Chrome completely (important!)
# 3. Launch Claude Code with Chrome flag
claude --chrome
# 4. Ask Claude to do anything in your browser
"Open LinkedIn and post about my latest project"
"Go to localhost:3000 and check for console errors"
"Extract all product prices from this page into a CSV"
That's it. No MCP server setup, no WebSocket bridges, no keepalive hacks. It uses native messaging (rock solid), accessibility trees (works on any site), and your real browser sessions (no detection).
What I Actually Learned
- Research before building. I could have found Claude's Chrome extension in 10 minutes. Instead I spent days building an inferior version. Always check if the problem is already solved.
- Accessibility trees beat CSS selectors. For any kind of browser automation, semantic element targeting is more robust than CSS selectors. LinkedIn's composer is invisible to CSS queries but fully visible in the accessibility tree.
- Native messaging beats WebSocket for extensions. No keepalive hacks, no service worker sleep issues, no port conflicts. Stdio transport is the right choice for extension-to-host communication.
- Kill your darlings fast. The moment I realized Claude's extension works on Brave, I killed BraveBridge. No sunk cost fallacy. The code taught me things; shipping it would teach me nothing new.
- Building "useless" things isn't useless. I now deeply understand Manifest V3, Chrome extension APIs, MCP protocol, WebSocket bridges, content script injection, and accessibility trees. That knowledge compounds.
Sometimes the best outcome of a project is knowing you don't need to build it.
Update: BraveBridge Is Back (April 17, 2026)
Plot twist. Two weeks after killing BraveBridge, I brought it back.
Here's what happened: I actually tried using Chrome DevTools MCP for real work. Logging into sites. Testing my own projects. Checking dashboards. And every session hit the same wall — the browser it opens is sandboxed. No saved cookies. No logged-in sessions. Cloudflare challenges on every major site.
The "Claude in Chrome" extension works on Brave, yes. But Chrome DevTools MCP — the tool that actually controls browser tabs — launches its own environment. That environment doesn't have your cookies. You're not logged in anywhere. Every Cloudflare-protected site throws a captcha. It's a clean room when you need a workshop.
The Comeback. BraveBridge's core advantage was always real: it connects to your actual browser. Same cookies, same sessions, same fingerprint. I just needed to close the feature gap. So I did.
What changed in v0.3.0
I took every capability that made Chrome DevTools MCP superior and built it into BraveBridge:
- Accessibility tree snapshots — the exact feature I called "the kill shot" in the original post. BraveBridge now builds a full a11y tree with UIDs (
ref1,ref2, etc.) that you can use to target elements. No more fragile CSS selectors. - UID-based interaction — every tool (click, type, hover, drag) accepts UIDs from the snapshot. Take a snapshot, see
button [ref7] "Submit", callclick(uid: "ref7"). - Console capture — intercept console.log/warn/error/info and uncaught exceptions. Get them back with type filtering and pagination.
- Dialog handling — auto-handle alert/confirm/prompt with configurable responses.
- Drag and drop, hover, double-click — full interaction primitives.
- File upload — upload local files through file inputs (server reads file, sends to extension, extension creates File objects via DataTransfer).
- Form batch-fill — fill multiple fields at once, handling inputs, selects, checkboxes, radios, and contentEditable.
- Device emulation — dark/light mode, viewport resize, user agent override.
- Navigation history — back, forward, reload.
- Tab management — close tabs, resize windows.
- Screenshot upgrades — full page capture, JPEG/WebP format, quality control, element-targeted screenshots.
BraveBridge went from 13 tools to 29 tools. Every Chrome DevTools MCP capability that's possible without the debugger permission is now in BraveBridge.
| BraveBridge v0.3.0 | Chrome DevTools MCP | |
|---|---|---|
| Browser context | Real browser (cookies, sessions) | Sandboxed (no saved state) |
| Cloudflare/captchas | Rarely triggered | Frequently triggered |
| Element targeting | A11y tree + UIDs + CSS selectors | A11y tree + UIDs |
| Tools | 29 tools | 25 tools |
| Performance tracing | Not yet (needs debugger API) | Full CDP access |
| Setup | Extension + MCP config | claude --chrome |
Lesson Updated. "Kill your darlings fast" is still right. But so is "revive them when the landscape changes." The sandbox limitation of Chrome DevTools MCP wasn't obvious until I hit it in real workflows. BraveBridge's core bet — real browser, real sessions — turned out to matter more than I thought.
BraveBridge is now open source on GitHub. MIT licensed. If you want AI agents controlling your actual browser with your actual sessions, it's ready.