Automation CDP Tutorial

Automate Any Browser with CDP

2026-06-05 · Jay Drake · 8 min read

Selenium is dead. Playwright is heavy. Puppeteer is Google-only. If you want real browser automation — the kind that runs on your own hardware, with your own browser, under your own control — you use CDP.

CDP stands for Chrome DevTools Protocol. It is the same protocol Chrome uses to talk to its developer tools. It is also the protocol you can use to talk to Chrome directly. No middleman. No abstraction. Just you and the browser.

Why CDP?

Most browser automation tools wrap CDP in layers. Each layer adds weight, failure points, and dependencies. CDP is the layer beneath all of them. When you learn CDP, you no longer need Playwright, Puppeteer, or Selenium. You can control any Chromium browser — Chrome, Brave, Edge, Opera — with a few HTTP requests and WebSocket messages.

The benefits:

Starting the Browser

First, launch your browser with remote debugging enabled:

brave-browser-stable \
  --remote-debugging-port=9223 \
  --remote-debugging-address=127.0.0.1 \
  --no-first-run \
  --no-default-browser-check \
  about:blank

This starts Brave with a CDP server listening on 127.0.0.1:9223. You can replace brave-browser-stable with google-chrome-stable or chromium and it will work the same way.

Getting the Debug URL

Once the browser is running, visit http://127.0.0.1:9223/json/version to verify CDP is active. Then visit http://127.0.0.1:9223/json/list to see all open tabs and their WebSocket debugger URLs.

import requests
r = requests.get('http://127.0.0.1:9223/json/list')
tabs = r.json()
ws_url = tabs[0]['webSocketDebuggerUrl']
print(ws_url)

Connecting via WebSocket

With the WebSocket URL, you can send CDP commands directly to the browser:

import websocket, json

ws = websocket.create_connection(ws_url)

def send(cmd, params=None):
    msg = {"id": 1, "method": cmd, "params": params or {}}
    ws.send(json.dumps(msg))
    return json.loads(ws.recv())

# Navigate to a page
send("Page.navigate", {"url": "https://example.com"})

# Take a screenshot
result = send("Page.captureScreenshot")
img_data = result["result"]["data"]
with open("screenshot.png", "wb") as f:
    f.write(base64.b64decode(img_data))

Common Commands

Here are the CDP commands I use most often:

Practical Example: Screenshot + Click

import requests, websocket, json, base64

# Connect to CDP
tabs = requests.get('http://127.0.0.1:9223/json/list').json()
ws = websocket.create_connection(tabs[0]['webSocketDebuggerUrl'])

def cdp(method, params=None, msg_id=1):
    ws.send(json.dumps({"id": msg_id, "method": method, "params": params or {}}))
    return json.loads(ws.recv())

# Navigate and wait for load
cdp("Page.navigate", {"url": "https://gumroad.com"})
cdp("Page.enable")

# Evaluate JS to find a button's coordinates
js = """document.querySelector('button.primary').getBoundingClientRect()"""
result = cdp("Runtime.evaluate", {"expression": js, "returnByValue": True})
rect = result["result"]["value"]

# Click it
cdp("Input.dispatchMouseEvent", {
    "type": "mousePressed",
    "x": rect["x"] + rect["width"]/2,
    "y": rect["y"] + rect["height"]/2,
    "button": "left",
    "clickCount": 1
})
cdp("Input.dispatchMouseEvent", {
    "type": "mouseReleased",
    "x": rect["x"] + rect["width"]/2,
    "y": rect["y"] + rect["height"]/2,
    "button": "left",
    "clickCount": 1
})

# Screenshot
screenshot = cdp("Page.captureScreenshot")
with open("result.png", "wb") as f:
    f.write(base64.b64decode(screenshot["result"]["data"]))

ws.close()

Why This Matters

The modern web is built on browsers. If you can control a browser programmatically, you can automate almost anything: publishing, scraping, testing, monitoring, purchasing, data extraction. And if you do it with CDP, you are not dependent on any vendor's API or pricing.

This is the foundation of the income automation system we run at Drake Enterprise. Products upload themselves. Descriptions update themselves. The browser becomes a node in the mesh, not a tool for human browsing.

Going Deeper

If you want the full course on CDP automation — including network interception, request modification, PDF generation, headless operation, and integration with the Drake Enterprise mesh — it is part of the Technical Academy.

The browser is yours. Control it directly.