Quickstart

Install the cdp tools and confirm they can drive a browser, in about five minutes.

Install

The tools need Go 1.26 or later and a Chromium-based browser — Chrome, Chromium, Brave, Edge, Opera, or Vivaldi. They launch a browser you already have rather than downloading one.

go install github.com/tmc/cdp/cmd/cdp@latest
go install github.com/tmc/cdp/cmd/churl@latest
go install github.com/tmc/cdp/cmd/cdpscript@latest

These land in $(go env GOPATH)/bin, usually ~/go/bin. Make sure that is on your PATH.

Confirm a browser is found

cdp -list-browsers
Brave	/Applications/Brave Browser.app/Contents/MacOS/Brave Browser		Running
Brave	/Applications/Brave Browser.app/Contents/MacOS/Brave Browser	151.1.93.129	Installed
Chrome Canary	/Applications/Google Chrome Canary.app/…/Google Chrome Canary	canary	Installed

The columns are name, path, version, and whether that browser is running now. Your list will differ. If nothing is found, or you want a specific browser, pass -chrome-path to any command or set CHROME_PATH in the environment.

Extract something from a page

This runs headless, so no window appears:

cdp -headless -url 'data:text/html,<h1>Hi</h1>' -extract h1
"{\"text\":\"Hi\"}"

The result is a JSON string. -extract-mode selects what you get back — text, html, attr:name, or count.

Render a page as Markdown

cdp -headless -url 'data:text/html,<h1>Title</h1><p>Body <b>text</b>.</p>' -render body
# Title

Body **text**.

Confirm JavaScript actually runs

This is what separates these tools from curl. Serve a page whose content is built by JavaScript after load:

mkdir -p /tmp/cdp-demo/api && cd /tmp/cdp-demo
echo '{"count":3}' > api/items
cat > index.html <<'HTML'
<!doctype html><title>Demo</title><h1>Demo site</h1>
<script>fetch('/api/items').then(r=>r.json()).then(d=>{
  document.body.insertAdjacentHTML('beforeend','<div id=done>'+d.count+'</div>')})</script>
HTML
python3 -m http.server 8099 &

Now fetch it:

churl http://localhost:8099/
<html><head><title>Demo</title></head><body><h1>Demo site</h1>
<script>fetch('/api/items').then(r=>r.json()).then(d=>{
  document.body.insertAdjacentHTML('beforeend','<div id=done>'+d.count+'</div>')})</script>
<div id="done">3</div></body></html>

The <div id="done">3</div> does not exist in the served HTML — the page’s own JavaScript fetched it and inserted it. curl http://localhost:8099/ does not show it. Keep this server running if you want to follow the capture guide; otherwise stop it with pkill -f 'http.server 8099'.

You are now in /tmp/cdp-demo, so anything you capture or screenshot next lands there. cd - to go back.

Take a screenshot

cdp -headless -url 'data:text/html,<h1>Hi</h1>' -screenshot 'full shot.png'
Screenshot saved to: shot.png (3119 bytes)

The byte count will differ on your machine; fonts and device pixel ratio change the rendering.

Next steps

Last updated: 2026-09-23