Chrome DevTools CLI (cdp-cli)
CLI for Chrome DevTools Protocol. All list commands output NDJSON (one JSON object per line) — grep/tail/jq friendly. Requires Chrome running with remote debugging.
Prerequisites
Chrome must be running with --remote-debugging-port:
cdp-cli launch # macOS: launches Chrome with debugging on :9223
Or start Chrome manually with --remote-debugging-port=9222 and pass
--cdp-url http://localhost:9222.
Page Identification
All commands taking <page> accept a page ID or a title substring.
Use cdp-cli tabs to discover pages.
cdp-cli tabs # List all open pages (NDJSON)
cdp-cli tabs | grep "example" # Find by title
Token-Conscious Defaults (Critical)
cdp-cli is designed to minimize token usage by default:
- console returns bare strings (not JSON objects) and only the last 10
messages. Add
--with-type,--with-timestamp,--with-sourceonly when needed. Use-vfor all fields. - snapshot defaults to accessibility tree (
--format ax) which is compact. Use--format textfor plain text,--format domfor full DOM (heavy). - network collects for only 0.1s by default. Increase with
--duration.
Strategy: Start with defaults, add verbosity flags only when needed.
Commands
Page Management
cdp-cli tabs # List all pages (NDJSON)
cdp-cli new "https://example.com" # Open new tab
cdp-cli new # Open empty tab
cdp-cli go "<page>" "https://url.com" # Navigate to URL
cdp-cli go "<page>" back # History back
cdp-cli go "<page>" forward # History forward
cdp-cli go "<page>" reload # Reload
cdp-cli close "<page>" # Close tab
Snapshot & Evaluation
cdp-cli snapshot "<page>" # Accessibility tree (default, compact)
cdp-cli snapshot "<page>" -f text # Plain text content
cdp-cli snapshot "<page>" -f dom # Full DOM tree (JSON, heavy)
cdp-cli eval "<page>" "document.title" # Evaluate JS expression
cdp-cli eval "<page>" "Array.from(document.querySelectorAll('h1')).map(h => h.textContent)"
Use the accessibility tree to discover elements by role/name, then construct CSS selectors for click/fill.
Console
cdp-cli console "<page>" # Last 10 messages, bare strings
cdp-cli console "<page>" -n 50 # Last 50 messages
cdp-cli console "<page>" --all # All messages (or -n -1)
cdp-cli console "<page>" -t error # Filter by type (log/error/warn/info)
cdp-cli console "<page>" -d 2 # Collect for 2 seconds
cdp-cli console "<page>" -i # --inspect: expand nested objects/arrays
cdp-cli console "<page>" -v # --verbose: all fields (type, timestamp, source)
cdp-cli console "<page>" --with-type # Add type field only
cdp-cli console "<page>" --with-source # Add source location (url, line)
When truncated, stderr shows: (N messages skipped. Use --tail M or --all to see more)
Network
cdp-cli network "<page>" # Requests in last 0.1s (NDJSON)
cdp-cli network "<page>" -d 5 # Collect for 5 seconds
cdp-cli network "<page>" -t fetch # Filter by type (xhr, fetch, script, etc)
cdp-cli network "<page>" -d 5 -t fetch # Combine filters
Filter results with grep:
cdp-cli network "<page>" | grep '"status":4' # 4xx errors
cdp-cli network "<page>" | grep '"status":404' # 404s specifically
Input Automation
cdp-cli click "<page>" "button" # Click by CSS selector
cdp-cli click "<page>" "button" -d # Double click
cdp-cli click "<page>" "button" -g # --user-gesture: required for
# WebXR, fullscreen, and other
# activation-gated APIs
cdp-cli click "<page>" --node 42 # Click by backend DOM node ID
cdp-cli click "<page>" "button" -w 5000 # Wait up to 5s for selector
cdp-cli fill "<page>" "user@example.com" "input[name='email']"
cdp-cli fill "<page>" "secret" "input[type='password']"
cdp-cli key "<page>" enter
cdp-cli key "<page>" tab
cdp-cli key "<page>" escape
Screenshots
cdp-cli screenshot "<page>" screenshot.jpg # Save JPEG (default)
cdp-cli screenshot "<page>" out.png -f png # PNG format
cdp-cli screenshot "<page>" out.webp -f webp # WebP format
cdp-cli screenshot "<page>" out.jpg -q 50 # Lower quality (0-100)
Error Handling
All errors output NDJSON with "error": true:
{ "error": true, "message": "Page not found: example", "code": "PAGE_NOT_FOUND" }
Common Workflows
Inspect and Interact
cdp-cli tabs | grep "example" # Find page
cdp-cli snapshot "example" # Get accessibility tree
# Identify selectors from the tree, then:
cdp-cli fill "example" "query" "input"
cdp-cli click "example" "button[type='submit']"
cdp-cli screenshot "example" result.jpg
Debug Console Errors
cdp-cli console "localhost" -t error -d 10 # Errors over 10 seconds
cdp-cli console "localhost" -t error -v # With full source location
Monitor Network
cdp-cli network "localhost" -d 5 | grep '"status":4' # Failed requests
cdp-cli network "localhost" -d 5 -t fetch # API calls only
Form Automation
cdp-cli new "http://localhost:3000/login"
cdp-cli fill "localhost" "user@example.com" "#email"
cdp-cli fill "localhost" "password123" "#password"
cdp-cli click "localhost" "button[type=submit]"
sleep 2
cdp-cli eval "localhost" "document.querySelector('.success')?.textContent"
Global Options
| Option | Default | Description |
|---|---|---|
--cdp-url |
http://localhost:9223 |
Chrome DevTools Protocol URL |
--help |
— | Show help |
--version |
— | Show version |