cdpfleet / 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.
- 6browsers with a cdpUrl
- anyPuppeteer or Playwright version
- 0browsers to install locally
Which browsers, and how to connect
cdp: trueworks 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 } })withpuppeteer-core— the browser runs on cdpfleet, nothing to download. - Playwright
connectOverCDPdoesn't need a client of the server's exact version, unlikeconnect(). You get the Chromium-level API (CDP & Puppeteer). - One URL that launches and connects: a Connect URL works for Playwright, Playwright Test and CDP clients that can only take a WebSocket address.
- Recordings: a headless session is recorded when it has
cdporlive_view(headless-recording recipe).
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 sessionWhat CDP adds
- Core Web Vitals in lab runs: LCP, CLS and TTFB come back from one
evaluatewith buffered observers, from all five languages; through a proxy, TTFB includes reaching the server via the proxy (case 55). - A slow phone on a fast server: one
newCDPSessioncall 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). Nocdp: trueneeded for that: Playwright'snewCDPSessionworks 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).
- 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).
What a page can tell
- The classic CDP tell is gone: the
Error.stackgetter trick fired in none of six setups — not over CDP, not with Playwright's protocol (case 43). - What remains is the browser, not the client: the
Error.messagegetter 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). - Headless itself is the bigger signal on real protected sites: what gets through where and what a page can read about your browser.