
browser-cdp
PopularUse this skill when you need to control a Chrome browser via CDP (Chrome DevTools Protocol) to reuse existing login sessions. Covers: launching Chrome in debug mode, opening URLs, waiting for page load, evaluating JavaScript, taking snapshots, and extracting auth tokens. Trigger phrases: browser automation, CDP, agent-browser, 浏览器操作, 操作浏览器, Chrome CDP, 复用登录态, extract token from browser.
Use this skill when you need to control a Chrome browser via CDP (Chrome DevTools Protocol) to reuse existing login sessions. Covers: launching Chrome in debug mode, opening URLs, waiting for page load, evaluating JavaScript, taking snapshots, and extracting auth tokens. Trigger phrases: browser automation, CDP, agent-browser, 浏览器操作, 操作浏览器, Chrome CDP, 复用登录态, extract token from browser.
Browser CDP Tool
Control Chrome via CDP to reuse existing login sessions and perform browser automation.
Prerequisites
- macOS / Linux / Windows (experimental), Google Chrome installed
- Node.js 12+
agent-browserinstalled:npm install -g agent-browser
⚠️ First launch will kill the user's regular Chrome. You must ask for user consent before starting (see "Launch Flow" below), otherwise the user may lose unsaved tabs/drafts.
Launch Flow (skill-mode mandatory steps)
Step 1: Detect current state (no side effects)
node {SKILL_DIR}/scripts/setup-cdp-chrome.js 9222 --detect-only
Output example:
CDP_STATUS=ready # Ready, can reuse directly
CDP_URL=http://127.0.0.1:9222/json/version
BROWSER=Chrome/148.0.7778.168
Or:
CDP_STATUS=needs-setup
CHROME_RUNNING=yes # User has Chrome running, launch will kill it
CHROME_PID_COUNT=3
Step 2: Branch based on detection result
CDP_STATUS=ready→ Useagent-browser --cdp 9222 ...directly, do not run setup.CDP_STATUS=needs-setupandCHROME_RUNNING=no→ Safe launch:node {SKILL_DIR}/scripts/setup-cdp-chrome.js 9222 --yesCDP_STATUS=needs-setupandCHROME_RUNNING=yes→ First ask user with AskUserQuestion: inform that N Chrome processes will be killed, may lose unsaved work; if user agrees, launch with--yes; if user refuses, abort automation.
Why not just --yes: In non-TTY (skill mode / Bash tool), if the script detects Chrome running without --yes, it exits with code 3 and NEEDS_CONSENT: ..., without silently killing processes. This is a safety net—but the skill flow should still ask the user first, not blindly pass --yes on seeing code 3.
Setup Script Options
| Option | Description |
|---|---|
--detect-only |
Only detect, no state changes (for skill use) |
--yes |
Consent obtained, skip interactive prompts |
--reset |
Clear ~/chrome-debug-profile before launch (use when login expires) |
--profile <name> |
Use a non-Default Chrome profile (e.g., "Profile 1") |
--dry-run |
Print steps to execute without running |
Exit codes: 0 success / 1 general error / 2 user refused (TTY) / 3 consent needed but --yes missing.
Common Operations
Open page and wait for load
agent-browser --cdp 9222 open "<URL>"
agent-browser --cdp 9222 wait 3000
Extract page text
agent-browser --cdp 9222 eval 'document.body.innerText.substring(0, 8000)'
Extract Auth Token
agent-browser --cdp 9222 eval 'localStorage.getItem("token") || document.cookie'
Complex JS (with quotes / $ / backticks)
Shell escaping is error-prone; use one of these methods:
# 1) base64 wrap
agent-browser --cdp 9222 eval -b "$(echo -n "document.querySelectorAll('a').length" | base64)"
# 2) heredoc + --stdin
cat <<'EOF' | agent-browser --cdp 9222 eval --stdin
const links = document.querySelectorAll('a');
links.length;
EOF
Page interaction (snapshot for element references)
agent-browser --cdp 9222 snapshot -i # Only interactive elements
agent-browser --cdp 9222 click "<CSS or @e1>"
agent-browser --cdp 9222 type "<sel>" "<text>"
Stop / Cleanup
- Close the debug Chrome window (or
pkill -9 -x 'Google Chrome'/taskkill /F /IM chrome.exe). - Login expired:
node {SKILL_DIR}/scripts/setup-cdp-chrome.js 9222 --reset --yes(note:--yesstill requires user consent first).
OpenCode Environment Notes
OpenCode lacks a background command execution tool; long CDP operations (e.g., waiting for page load, bulk data scraping) block the entire session, causing CLI unresponsiveness.
Timeout Wrapper
On Windows, use PowerShell Job to wrap CDP commands with timeout:
$job = Start-Job { agent-browser --cdp 9222 eval "window.location.replace('https://www.qidian.com/rank/')" }
Wait-Job $job -Timeout 30 | Out-Null
if ($job.State -eq 'Running') { Stop-Job $job; Write-Output "⏱ CDP operation timed out (30s), please retry or interrupt manually" }
else { Receive-Job $job }
Remove-Job $job -Force
On macOS / Linux, use the timeout command:
timeout 30 agent-browser --cdp 9222 eval "window.location.replace('https://www.qidian.com/rank/')" || echo "⏱ CDP operation timed out (30s), please retry or interrupt manually"
Known Limitations
Even with timeout wrappers, the following scenarios may still cause issues:
| Scenario | Risk | Mitigation |
|---|---|---|
| Page load timeout | eval command hangs indefinitely | Set 30s timeout, retry on timeout |
| Bulk data scraping | Cumulative wait too long across pages | Independent timeout per page, resume from breakpoint on failure |
| Chrome process stuck | CDP connection lost but process not exited | Clean up with pkill / taskkill then reconnect |
| Network fluctuation | Request hangs without timeout | Auto-retry once on timeout |
If an operation hangs persistently, press ESC in opencode to interrupt manually.
FAQ
| Problem | Solution |
|---|---|
NEEDS_CONSENT + exit code 3 |
Ask user with AskUserQuestion if they allow killing Chrome; if yes, rerun with --yes |
| CDP port not listening | Recheck with --detect-only; if port occupied, change port |
| Page redirects to login | Use snapshot -i to find login button and interact |
eval returns null |
Check localStorage key name; for JS with quotes, use eval -b or --stdin |
| Login expired | Run setup-cdp-chrome.js 9222 --reset --yes to recopy |
| Multiple Chrome profiles | Specify with --profile "Profile 1" |
| Chrome won't start (30s timeout) | Try --reset; check port conflicts; inspect ~/chrome-debug-profile/ for corruption |





