Skip to content
Glossary

CDP is the protocol under Playwright, Puppeteer and your agent

A JSON-RPC conversation over a websocket, organised into domains, with commands you send and events the browser emits. Every higher-level library is a wrapper around it.

The shape worth knowing even if you never write it directly

Domains, commands and events


The surface is grouped into domains such as Page, Network, Runtime, DOM and Target. You send commands and receive replies, and separately the browser pushes events. Most confusing behaviour comes from treating a reply as if it were an event.

Domains must be enabled


Several domains emit nothing and silently ignore configuration until you call their enable command. This is the single most common CDP mistake: the call returns successfully, and nothing happens, forever.

Targets and sessions


A browser is a tree of targets, one per tab, worker and out-of-process frame. Attaching gives a session id that scopes subsequent commands, which is why a command that worked on one tab appears to do nothing on another.

It is versioned by the browser, not by a spec


The stable domains are documented and change slowly; the experimental ones can change between Chrome releases without notice. Building on an experimental domain is a decision to track Chrome's release cadence.

CDP against the layers above it

Level Reach for it when
Raw CDP The wire itself You need a domain no library exposes
Puppeteer Thin wrapper, Chromium first You want CDP with ergonomics
Playwright Thicker, multi-engine You want auto-waiting and other engines
Selenium WebDriver A W3C standard, not CDP You need broad, long-lived compatibility
WebDriver BiDi Standardised bidirectional successor You want CDP-like events, portably
An agent framework A model on top of one of these The decisions should not be in your code

As of 2026-08-31 · Competitor details come from each vendor's published pricing page on that date.

Debugging a CDP call that does nothing

In this order. The first two explain most cases.

  1. Check you enabled the domain

    Call the domain's enable command before configuring it. Several commands are accepted and discarded when the domain is disabled, and the reply gives no hint.

  2. Check which session the command went to

    A command sent to the browser target does not reach a page target. If nothing seems to apply, the session id is the first thing to print.

  3. Check ordering against navigation

    Configuration applied after a navigation begins may land in the outgoing document. Anything that must apply to the next page has to be registered before the navigation is issued.

  4. Look at the raw traffic

    Every library can log the underlying protocol messages. Reading them is usually faster than reasoning about what the wrapper intended to send.

  5. Prefer returnByValue for real data

    Object previews are lossy by design and truncate deep structures. When you need the actual value rather than something to look at in a debugger, ask for it by value.

Common questions

Is CDP a standard?

No. It is Chromium's own protocol, documented but controlled by the Chromium project. WebDriver BiDi is the W3C effort to standardise the same capabilities across engines, and it is the direction the ecosystem is moving, though CDP remains what most tooling actually speaks today.

Can I use CDP over the network?

Yes, and that is exactly what a hosted browser endpoint is: the websocket is simply somewhere else. The consequence is latency per command, which is why chatty scripts feel slower remotely and batched ones barely change.

Does Firefox support CDP?

Partially, through a compatibility layer, and the coverage is incomplete. If cross-engine support matters, WebDriver BiDi or Playwright's own abstraction is a more durable choice than assuming CDP is portable.

Should I write CDP directly?

Rarely, and only for something the library above you does not expose. The wrappers exist because raw CDP requires you to manage sessions, ordering and enablement by hand, and most bugs in direct CDP code are in exactly those three areas.

A CDP endpoint you did not have to operate

Connect Playwright or Puppeteer to a remote websocket and keep the code you already have.