Connect Claude Code to an existing Chrome browser via CDP (Chrome DevTools Protocol). Zero dependencies — uses Node 22 built-in WebSocket. Attach to any Chrome running with --remote-debugging-port, then navigate, click, type, screenshot, evaluate JS, read accessibility tree, and monitor console/network. Use when you need to interact with a browser the agent already started, control an existing Chrome instance, or drive browser automation without Playwright MCP. Triggers on: cdp connect, connect to browser, connect to chrome, attach to browser, interact with browser, drive browser, browser automation, control chrome, connect 9222.
100
100%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Advisory
Suggest reviewing before use
Connect to an existing Chrome browser via Chrome DevTools Protocol. Zero dependencies — Node 22 built-in WebSocket only.
Chrome must be running with remote debugging enabled:
# Launched manually:
chrome --remote-debugging-port=9222
# Or by a dev server that launches Chrome:
npm run dev # if it opens Chrome with --remote-debugging-portif [[ -n "${CLAUDE_SKILL_DIR:-}" ]]; then
CDP_JS="${CLAUDE_SKILL_DIR}/scripts/cdp.js"
else
CDP_JS="$(command -v cdp.js 2>/dev/null || \
find ~/.claude -path "*/cdp-connect/scripts/cdp.js" -type f 2>/dev/null | head -1)"
fi
if [[ -z "$CDP_JS" || ! -f "$CDP_JS" ]]; then
echo "Error: cdp.js not found. Ask the user for the path." >&2
fiStore in CDP_JS and use for all commands below.
node "$CDP_JS" list # Show all tabs with IDs
node "$CDP_JS" navigate <url> [--id <tid>] # Navigate to URL
node "$CDP_JS" eval <expr> [--id <tid>] # Evaluate JavaScript
node "$CDP_JS" screenshot <path> [--id <tid>] # Save screenshot as PNG
node "$CDP_JS" ax-tree [--id <tid>] # Accessibility tree (primary)
node "$CDP_JS" dom [--id <tid>] # Full HTML (fallback)
node "$CDP_JS" click <selector> [--id <tid>] # Click element
node "$CDP_JS" type <sel> <text> [--id <tid>] # Type into element
node "$CDP_JS" console [--timeout 10] # Stream console events
node "$CDP_JS" network [--timeout 10] # Stream network eventsAll commands default to port 9222. Override with --port N.
Use --id <target-id> from list output to target a specific tab.
list to see tabs and their unique IDsax-tree for page structure (prefer over dom)navigate, click, type, eval as neededscreenshot /tmp/shot.png, then Read the PNGconsole or network to stream eventsax-tree is the primary way to understand page state — semantic
roles and names are more useful than raw HTML for an agent/tmp/ and use the Read tool to vieweval supports promises: eval "await fetch('/api').then(r=>r.json())"--timeout 15CDP_TIMEOUT=10000 env var overrides default 5s timeout globallylist first and use --id