[cdpfleet](https://cdpfleet.com/) / CDP & Puppeteer

Chrome DevTools Protocol

# Puppeteer, raw CDP, *remote browsers*.

Add `"cdp": true` to a launch and the response carries a `cdpUrl` next to `wsUrl`: a browser-level DevTools WebSocket for Puppeteer, Playwright's `connectOverCDP` in any version, or your own CDP client. The proxy, timeouts, threads and billing are the same as any other session.

[CDP docs](https://cdpfleet.com/docs/cdp)[Build the code](https://cdpfleet.com/docs/builder)

-   **6**browsers with a cdpUrl
-   **any**Puppeteer or Playwright version
-   **0**browsers to install locally

## Which browsers, and how to connect

-   **`cdp: true` works on** Chrome, Edge, Brave, Opera, Yandex and Chromium. Patchright, Rebrowser, Camoufox, Firefox and WebKit speak Playwright's own protocol only.
-   **Puppeteer:** `puppeteer.connect({ browserWSEndpoint: cdpUrl, headers: { "x-api-key": KEY } })` with `puppeteer-core` — the browser runs on cdpfleet, nothing to download.
-   **Playwright `connectOverCDP`** doesn't need a client of the server's exact version, unlike `connect()`. You get the Chromium-level API ([CDP & Puppeteer](https://cdpfleet.com/docs/cdp)).
-   **One URL that launches and connects:** a [Connect URL](https://cdpfleet.com/docs/connect) works for Playwright, Playwright Test and CDP clients that can only take a WebSocket address.
-   **Recordings:** a headless session is recorded when it has `cdp` or `live_view` ([headless-recording recipe](https://cdpfleet.com/docs/examples#headless-recording)).

```js
import puppeteer from 'puppeteer-core';
const KEY = process.env.CDPFLEET_API_KEY;
const res = await fetch('https://starter.cdpfleet.com/chrome/session', {
  method: 'POST',
  headers: { 'x-api-key': KEY, 'content-type': 'application/json' },
  body: JSON.stringify({ headless: 'new', cdp: true }),
});
const { cdpUrl } = await res.json();
const browser = await puppeteer.connect({ browserWSEndpoint: cdpUrl, headers: { 'x-api-key': KEY } });
const page = await browser.newPage();
await page.goto('https://example.com');
await browser.close(); // ends the session
```

## What CDP adds

-   **Core Web Vitals in lab runs:** LCP, CLS and TTFB come back from one `evaluate` with buffered observers, from all five languages; through a proxy, TTFB includes reaching the server via the proxy ([case 55](https://cdpfleet.com/docs/cases/core-web-vitals-via-cdp)).
-   **A slow phone on a fast server:** one `newCDPSession` call reaches DevTools' CPU throttling — the same workload ran 2.7–4.0× slower at 4× and 4.1–7.3× slower at 6× ([case 56](https://cdpfleet.com/docs/cases/cpu-throttling-via-cdp)). No `cdp: true` needed for that: Playwright's `newCDPSession` works over the normal connection.
-   **The cookie jar, read and edited:** filter by URL, change a value or expiry, delete one cookie, and carry a login to another session as about 150 bytes of JSON ([case 57](https://cdpfleet.com/docs/cases/inspect-and-edit-the-cookie-jar)).
-   **Block telemetry, keep the page:** news front pages sent dozens of analytics requests per load and kept reporting after the scraper left; blocking them changed no titles or headings ([case 59](https://cdpfleet.com/docs/cases/intercept-and-block-telemetry)).

## What a page can tell

-   **The classic CDP tell is gone:** the `Error.stack` getter trick fired in none of six setups — not over CDP, not with Playwright's protocol ([case 43](https://cdpfleet.com/docs/cases/cdp-detectability)).
-   **What remains is the browser, not the client:** the `Error.message` getter fires on every Chromium build, whether or not anything is listening, and logging a large object costs measurably more while a client receives the console ([case 43](https://cdpfleet.com/docs/cases/cdp-detectability)).
-   **Headless itself is the bigger signal** on real protected sites: [what gets through where](https://cdpfleet.com/bot-protection) and [what a page can read about your browser](https://cdpfleet.com/docs/fingerprinting).

## Related

Cases, recipes, posts and comparisons about this — updated as new ones are published.

### Reference docs

The details, options and errors.

-   [CDP & Puppeteer](https://cdpfleet.com/docs/cdp)cdpUrl, Puppeteer, connectOverCDP, raw CDP.
-   [Connect URL](https://cdpfleet.com/docs/connect)One wss:// URL that launches and connects.
-   [Recipe: Chrome over CDP](https://cdpfleet.com/docs/examples#chrome-cdp)connectOverCDP or Puppeteer.
-   [Recipe: Edge over CDP](https://cdpfleet.com/docs/examples#edge-cdp)The same on Edge.
-   [Recipe: Brave over CDP](https://cdpfleet.com/docs/examples#brave-cdp)Brave keeps its shields.
-   [Recipe: Opera over CDP](https://cdpfleet.com/docs/examples#opera-cdp)Opera with a cdpUrl.
-   [Recipe: Yandex over CDP](https://cdpfleet.com/docs/examples#yandex-cdp)Yandex with a cdpUrl.

### Cases 5

Real problems solved end to end, run on production in five languages.

-   [Case 55: Core Web Vitals from a remote browser: LCP, CLS and TTFB in lab runs](https://cdpfleet.com/docs/cases/core-web-vitals-via-cdp)Read LCP, CLS, FCP and TTFB from the page's performance timeline, plus Chromium's own counters over a CDP session — and see why TTFB through a proxy is mostly the proxy.[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/cases/55-core-web-vitals-via-cdp)
-   [Case 56: A slow phone on a fast server: CPU throttling over a CDP session](https://cdpfleet.com/docs/cases/cpu-throttling-via-cdp)Slow a remote Chromium's main thread 4× and 6× with Emulation.setCPUThrottlingRate, then time a JavaScript workload and a real page load — and see that it's per tab.[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/cases/56-cpu-throttling-via-cdp)
-   [Case 42: Puppeteer on real Google Chrome: cdpUrl, raw CDP and request interception](https://cdpfleet.com/docs/cases/puppeteer-on-real-chrome)Drive real Chrome on cdpfleet with Puppeteer (or any CDP client): what the browser reports, raw CDP calls, blocking images, and closing the session.[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/cases/42-puppeteer-on-real-chrome)
-   [Case 43: Can a page tell your automation client is listening? CDP and the console](https://cdpfleet.com/docs/cases/cdp-detectability)The old Error.stack trick no longer fires, but console.log still costs more when Playwright listens over CDP. Patchright avoids it; Camoufox isn't CDP.[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/cases/43-cdp-detectability)
-   [Case 26: Same Chrome, two doors: Playwright's protocol (wsUrl) or CDP (cdpUrl)](https://cdpfleet.com/docs/cases/playwright-vs-cdp)One Chrome launched twice — driven once through Playwright's own protocol and once over the Chrome DevTools Protocol — and what changes for your code and for the page.[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/cases/26-playwright-vs-cdp)

### Recipes 7

Complete programs for one setup each.

-   [Chrome over CDP (connectOverCDP or Puppeteer)](https://cdpfleet.com/docs/examples#chrome-cdp)Launch with `"cdp": true` and connect to `cdpUrl` with Playwright's `connectOverCDP` — no client version matching — or with Puppeteer. See [CDP & Puppeteer](https://cdpfleet.com/docs/cdp).[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/examples/recipes/chrome-cdp)
-   [Microsoft Edge over CDP (Puppeteer or connectOverCDP)](https://cdpfleet.com/docs/examples#edge-cdp)`"cdp": true` works on Edge as on Chrome: connect to `cdpUrl` with Playwright's `connectOverCDP` in any client version, or with Puppeteer. Pages see Edge's own brand…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/examples/recipes/edge-cdp)
-   [Brave over CDP (Puppeteer or connectOverCDP)](https://cdpfleet.com/docs/examples#brave-cdp)`"cdp": true` on Brave returns a `cdpUrl` for Puppeteer or Playwright's `connectOverCDP` in any version. Brave keeps its own identity over CDP too: the `Brave`…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/examples/recipes/brave-cdp)
-   [Opera over CDP (Puppeteer or connectOverCDP)](https://cdpfleet.com/docs/examples#opera-cdp)`"cdp": true` on Opera returns a `cdpUrl` for Puppeteer or Playwright's `connectOverCDP` in any version. Headless over CDP, open pages in a new context…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/examples/recipes/opera-cdp)
-   [Yandex Browser over CDP (Puppeteer or connectOverCDP)](https://cdpfleet.com/docs/examples#yandex-cdp)`"cdp": true` works on Yandex Browser as on Chrome: connect Puppeteer or Playwright's `connectOverCDP` (any client version) to `cdpUrl`. Handy when existing…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/examples/recipes/yandex-cdp)
-   [Microsoft Edge over CDP that survives a disconnect](https://cdpfleet.com/docs/examples#edge-keep-alive)`keep_alive: true` (dedicated threads) with `"cdp": true`: disconnect from `cdpUrl`, reconnect within `inactivity_timeout` and your pages are where you left them.…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/examples/recipes/edge-keep-alive)
-   [Headful Opera over CDP that survives a disconnect](https://cdpfleet.com/docs/examples#opera-keep-alive)`keep_alive: true` (dedicated threads) with `"cdp": true` on headful Opera: disconnect, reconnect to the same `cdpUrl` within `inactivity_timeout`, and the default…[Code on GitHub](https://github.com/cdpfleet/cdpfleet/tree/main/examples/recipes/opera-keep-alive)

## Read next

[Web scraping →](https://cdpfleet.com/web-scraping)[AI agents →](https://cdpfleet.com/ai-agents)[Bot protection →](https://cdpfleet.com/bot-protection)[Proxies →](https://cdpfleet.com/proxies)

---
Source: https://cdpfleet.com/cdp · Markdown: https://cdpfleet.com/cdp.md · All docs for AI tools: https://cdpfleet.com/llms.txt
