Use the browser you already have open.
Your agent already has Chrome. What it usually gets is a fat page snapshot, or a fresh automated browser that is not the tab with your cookies. chrome-cdp-ex attaches to that live session and does the common jobs in one step, with a short receipt.
Playwright is for clean isolated tests. This is for the session that already has your login.
Needs Node.js 22 (built-in WebSocket). This project does not publish to the npm registry.
From a checkout or unpacked release:
./bin/chrome-cdp doctor
./bin/chrome-cdp listlist prints target prefixes. Perceive the tab, act once, read the one-line receipt, then stop when done.
./bin/chrome-cdp perceive <target> -C -d 8
./bin/chrome-cdp click <target> @ref
./bin/chrome-cdp fill <target> @ref "you@example.com"
./bin/chrome-cdp press <target> Enter
./bin/chrome-cdp stopclick, fill, and press print a one-line receipt with URL, outcome, and next command. A failed action prints Error:, a Kind: (for example covered, disabled, stale-ref) and a runnable Next:, and exits 1.
If node -v is older than 22, doctor prints a Node 22 path that ./bin/chrome-cdp re-execs.
Get the files (tarball or git clone)
Pinned v2.20.0 tarball:
curl -L -o pi-chrome-cdp-2.20.0.tgz https://github.com/EndeavorYen/chrome-cdp-ex/releases/download/v2.20.0/pi-chrome-cdp-2.20.0.tgz
mkdir -p chrome-cdp-ex-v2.20.0
tar -xzf pi-chrome-cdp-2.20.0.tgz -C chrome-cdp-ex-v2.20.0 --strip-components=1
cd chrome-cdp-ex-v2.20.0Checksum is on the GitHub Release.
Current main:
git clone https://github.com/EndeavorYen/chrome-cdp-ex.git
cd chrome-cdp-exSKILL.md · docs/reference.md · docs/pk-324-board.md · INTEGRATIONS.md · Grok Bot from-zero
- See the page cheaply.
perceiveprints the accessibility tree with@refhandles, layout hints and the controls that matter, bounded for tokens.perceive --since-actionshows only what the last action changed.text --autoreads the main content;shot,elshot,scanshotandresponsive-auditcapture pixels, including Electron pages with live WebGL canvases. - Act like a person, report like a test.
click,fill,pressanddragsend real CDP input events;select,scrollanddismiss-modalcover the rest.clickandfillon a selector wait briefly for the target to be attached, visible and enabled (select: attached and enabled), a click refuses to land on a covering element, and every action returns a receipt: what changed, any dialog it answered, any download it saved (click --expect-download), and the next command. - Debug the live app.
consoleandstatusprint source-mapped stack frames (src/Foo.tsx:42:7),netlog --id Nshows one request's status, timing, headers and a bounded body, andstatus --vitalsreports LCP, CLS, INP and long tasks. - Drive it from any agent. It is a Claude Code skill, a plain CLI any agent can shell out to, and a stdio MCP server. MCP results carry screenshots as image blocks, versioned JSON as
structuredContent, and tool hints derived from the command catalog. See INTEGRATIONS.md.
This runs against the browser you are logged into, so the defaults lean careful:
- Background by default. Commands do not focus tabs or raise the browser over your work. A screenshot of a truly hidden tab (a background tab, a minimized window) that Chrome will not render fails within about 3 s with
Kind: hidden-taband a rerun hint instead of hanging; other commands on a hidden tab can drop input.CDP_BACKGROUND=0restores the old activate-the-tab behaviour. See Background mode. - Redacted by default. Tokens in URLs (
access_token,client_secret, signed URLs), auth headers, cookie headers, JWTs, values typed into secret-named fields and nested JSON secrets are replaced with<redacted>in action receipts,netlog,report,record-actionsand session logs. Not covered yet:consoletext, thecookiescommand, and the page URL printed byperceive,statusandlist.--unsafe-fulllifts redaction onnetlog,checkpointandcomponents. - Secrets stay out of the transcript.
fill <target> <sel> --secret NAMEtypes the value ofCDP_SECRET_<NAME>(orNAMEfromCDP_SECRETS_FILE); output shows<secret:NAME>. - Opt-in guardrails.
CDP_CONTENT_BOUNDARIES=1wraps page text in nonce-marked untrusted-content fences,CDP_ALLOWED_ORIGINSlimits where navigation may go,CDP_DENY_ACTIONSrefuses chosen commands (and the commands that do the same job), andCDP_ISOLATED_ONLY=1refuses to attach to a daily browser profile. They are defense-in-depth for agents, not a security boundary.
From Chrome 136, --remote-debugging-port is ignored on the default profile. chrome-cdp-ex cannot silently attach to an already-running default Chrome or Edge. Use a persistent non-default user-data-dir that you always launch with remote debugging, then sign in once. See Daily browser CDP for the launch line (it includes --disable-backgrounding-occluded-windows, so a browser window behind your terminal keeps rendering).
Grok Bot from-zero setup (replace computer use / browser use): docs/integrations/grok-bot.md.
For Electron, launch with a remote debugging port. Set CDP_PORT to that port. Use 9333 as the example, not daily Chrome 9222.
CDP_PORT=9333 ./bin/chrome-cdp listmacOS, Linux, Windows and WSL2 (a Windows-side Node bridges the WSL↔Windows gap). CI runs the full test suite on Linux and Windows for every pull request to main.
Built on pasky/chrome-cdp-skill by Petr Baudis. Contributors: ynezz, Jah-yee, Rolf Fredheim, hussainweb.
