← Blog

BLOG

CDP Playwright: Connect to Remote Browsers Without Local Chrome

CDP Playwright lets you drive hosted Chromium remotely. Learn how connectOverCDP works, when to use it, and how to keep sessions alive in production.

September 3, 202611 min readRemote Browser

# CDP Playwright: Connect to Remote Browsers Without Local Chrome

Playwright's connectOverCDP method is the cleanest way to attach your automation code to an already-running browser instance. Instead of launching a fresh Chromium process on every test run, you connect to a remote Chrome that's already alive—whether it's running in a Docker container, on a cloud VM, or behind a hosted browser API. This pattern is essential for AI agents that need persistent sessions, for teams that want to scale browser workloads across workers, and for anyone tired of fighting Chrome installation issues in CI.

In this guide, you'll learn how CDP Playwright connections work, when connectOverCDP beats launch(), and how to use it with a hosted Chromium runtime for production workloads.

What Is CDP and Why Does It Matter for Playwright?

The Chrome DevTools Protocol (CDP) is the wire protocol that allows external tools to inspect, debug, and control Chromium-based browsers. Every Chrome tab, network request, DOM mutation, and JavaScript execution can be observed and manipulated through CDP endpoints.

Playwright has two ways to talk to browsers:

  1. `chromium.launch()` — Playwright spawns a new browser process, connects to it internally, and manages its lifecycle.
  2. `chromium.connectOverCDP(endpoint)` — Playwright attaches to an existing browser that's already listening on a CDP endpoint (usually http://localhost:9222 or a remote WebSocket URL).

The second approach is what makes CDP Playwright workflows possible. You don't need to install Chromium locally. You don't need to manage browser binaries. You just point your code at a URL and start automating.

Why Connect to an Existing Browser Instead of Launching One?

Most developers start with launch(). It's simple, and for local development it works fine. But production browser automation has different requirements.

Concernchromium.launch()chromium.connectOverCDP()
Browser lifecyclePlaywright owns it; dies when script endsExternal process owns it; survives script crashes
Session persistenceLost on every runCan persist across runs and workers
Resource cleanupManual; orphaned processes commonManaged by the browser host
ScalingOne browser per script; hard to shareMultiple scripts can attach to same browser
Local Chrome installRequiredNot required if browser is remote
DebuggingLimited to Playwright's inspectorFull CDP access; live viewer possible

For AI agents that need to maintain login state, keep cookies warm, or resume a task after a timeout, launch() is a poor fit. Every restart means a fresh browser profile, re-authentication, and potential bot detection triggers. CDP Playwright connections let you keep a browser alive and simply re-attach when your worker is ready.

How to Use Playwright connectOverCDP

Here's a minimal TypeScript example that connects to a remote Chromium instance via CDP:

import { chromium } from 'playwright';

// The CDP endpoint of your remote browser.
// For a local browser started with --remote-debugging-port=9222:
// const cdpUrl = 'http://localhost:9222';
//
// For a hosted browser API, this is typically a WebSocket URL:
const cdpUrl = 'wss://remote-browser.dev/cdp/your-session-id';

async function main() {
  // Connect to the existing browser instance.
  const browser = await chromium.connectOverCDP(cdpUrl);

  // Get the default context or create a new one.
  const context = browser.contexts()[0] ?? await browser.newContext();

  // Use a persistent page or open a new tab.
  const page = await context.newPage();
  await page.goto('https://example.com');

  // Do something useful.
  const title = await page.title();
  console.log(`Page title: ${title}`);

  // Don't close the browser — leave it running for the next worker.
  // await browser.close();
}

main().catch(console.error);

The key difference from a normal Playwright script: you don't call browser.close() at the end. The browser stays alive, and your next worker can connect to the same session.

CDP Playwright vs. Playwright's Own Server Mode

Playwright also offers playwright.connect() which uses its own wire protocol over WebSocket. This is different from connectOverCDP.

  • `connectOverCDP` speaks raw CDP. It works with any Chromium browser that exposes a CDP endpoint—including browsers launched by Selenium, Puppeteer, or even a regular Chrome instance started with --remote-debugging-port.
  • `playwright.connect()` requires a Playwright server running on the other end. It's more feature-rich (supports Firefox and WebKit) but locks you into Playwright's ecosystem.

If you need to control a browser that wasn't launched by Playwright—say, a browser started by your AI agent framework or a cloud browser service—connectOverCDP is the right choice.

Firefox and connectOverCDP: What's Supported?

A common question is whether connectOverCDP works with Firefox. The short answer: no, not for Firefox. CDP is a Chromium-specific protocol. Firefox uses the Remote Protocol (formerly Marionette), which is not wire-compatible with CDP.

Playwright's official docs state that connectOverCDP is only supported for Chromium-based browsers. If you need to automate Firefox remotely, you have two options:

  1. Use playwright.connect() with a Playwright server that launches Firefox.
  2. Use Selenium's WebDriver protocol, which Firefox supports natively.

For most AI agent and browser automation workloads, Chromium is the pragmatic default. It has the largest market share, the most mature CDP tooling, and the best stealth-related capabilities. If Firefox support is a hard requirement, plan for a separate infrastructure path.

Keeping Browser Sessions Alive Across Cloud Workers

One of the hardest problems in production browser automation is session persistence. You have a queue of tasks, multiple workers, and each task needs the same logged-in session. With local launch(), each worker starts fresh—and your login flow becomes a bottleneck.

CDP Playwright solves this by decoupling the browser from the worker. Here's the pattern:

  1. Start a persistent browser in a long-running process or a hosted browser service.
  2. Expose its CDP endpoint (e.g., ws://browser-host:9222/devtools/browser/...).
  3. Workers connect via connectOverCDP when they need to run a task.
  4. Workers disconnect when done, but the browser stays alive.

This works well for:

  • AI agents that need to resume a task after an API timeout.
  • Cron jobs that run periodically against the same authenticated session.
  • Multi-worker scraping where each worker handles a subset of URLs but shares cookies and local storage.

The catch: you need a browser host that stays up. Running a dedicated VM just for Chrome is possible but wasteful. A hosted browser API like Remote Browser handles this for you—it keeps Chromium sessions alive, exposes CDP endpoints, and lets you connect from any worker.

How to Give Your AI Agent Browser Access in Production

AI agents (like those built on LangChain, CrewAI, or custom LLM loops) need browser access to complete tasks: filling forms, clicking through paginated results, extracting data behind login walls.

The naive approach is to install Playwright in the agent's runtime and call launch() on demand. This works in demos but breaks in production:

  • Cold starts: Launching Chromium takes 2-5 seconds. Agents that make many small browser calls pay this tax repeatedly.
  • Memory pressure: Each browser instance uses 300-500 MB. A single agent with multiple parallel tasks can exhaust memory quickly.
  • Session loss: If the agent process crashes, the browser dies with it. No recovery.

CDP Playwright fixes all three. Your agent connects to a pre-warmed remote browser, uses it for the task, and disconnects. The browser stays warm for the next call.

Here's what a production setup looks like:

  1. Provision a remote browser with a persistent profile.
  2. Get the CDP WebSocket URL from your browser service.
  3. In your agent code, connect via connectOverCDP, execute the task, and disconnect.
// Inside your agent's tool-calling loop:
async function browse(url: string, cdpEndpoint: string) {
  const browser = await chromium.connectOverCDP(cdpEndpoint);
  const context = browser.contexts()[0];
  const page = await context.newPage();
  await page.goto(url, { waitUntil: 'networkidle' });
  const content = await page.content();
  await page.close();
  // Do NOT close the browser. Let the next tool call reuse it.
  return content;
}

This pattern gives your agent a "warm" browser that maintains cookies, local storage, and even tab state between tool calls.

Scaling Playwright Browser Workloads Reliably

Scaling browser automation is harder than scaling stateless APIs. Each browser is a heavyweight process with its own memory, GPU, and network stack. If you run 50 Playwright instances on one machine, you'll hit resource limits fast.

CDP Playwright enables a different scaling model: many workers, fewer browsers.

Instead of launching one browser per task, you maintain a pool of persistent browsers. Workers connect to an available browser, run their task, and disconnect. This model:

  • Reduces total memory usage (browsers are reused, not spawned).
  • Eliminates cold start latency.
  • Allows session state to persist across tasks.

The trade-off is concurrency. A single browser can handle multiple CDP connections, but each page/tab consumes resources. If you need true parallelism, you need multiple browser instances—which brings you back to infrastructure management.

This is where hosted browser services shine. They handle the browser pool for you, exposing CDP endpoints per session. You scale your workers independently of your browser infrastructure.

When to Use a Hosted Browser API vs. Self-Hosted CDP

Self-hosting CDP endpoints is viable if you have dedicated infrastructure and an SRE team. You need to:

  • Maintain Chrome installations across OS versions.
  • Handle browser crashes and restarts.
  • Manage network egress (residential vs. datacenter IPs).
  • Implement session persistence and profile storage.
  • Monitor memory and CPU usage per browser.

For most teams, this is a distraction. A hosted browser API abstracts these concerns:

ConsiderationSelf-Hosted CDPHosted Browser API (e.g., Remote Browser)
Chrome installationManual; version pinning requiredManaged by provider
Session persistenceBuild your own profile storageBuilt-in persistent profiles
ScalingManual; capacity planning neededOn-demand browser sessions
IP diversitySingle datacenter IPConfigurable proxy settings
Live debuggingBuild your own viewerIncluded in dashboard
MaintenanceYour team's responsibilityProvider's responsibility

If browser automation is your core product, self-hosting might make sense. If it's a supporting capability—say, your AI agent needs to browse the web—a hosted API is almost always the better trade-off.

CDP Playwright with Remote Browser

Remote Browser provides hosted Chromium sessions that you can connect to via CDP. The workflow is straightforward:

  1. Create a browser session through the API or dashboard.
  2. Get the CDP endpoint (WebSocket URL) for that session.
  3. Connect with Playwright using chromium.connectOverCDP().
  4. Run your automation with full Playwright API access.

Because Remote Browser manages the underlying Chromium instances, you get:

  • Persistent profiles that survive session restarts.
  • Live viewer to watch what your browser is doing in real time.
  • Session isolation so one workload doesn't interfere with another.
  • Configurable browser settings for proxy and stealth-related needs.

This means you can use standard Playwright code—no custom drivers, no protocol shims—and still get the benefits of a managed browser runtime.

Common Pitfalls with connectOverCDP

Even with a solid setup, CDP Playwright connections have edge cases worth knowing:

1. Context vs. Browser lifecycle. When you connect to an existing browser, you don't control its launch flags. If the browser was started with a specific profile, you're bound to that profile. Creating a new context within a connected browser works, but it inherits the browser's launch options.

2. Multiple connections to the same browser. CDP allows multiple clients to connect to one browser. But if two workers try to use the same page simultaneously, you'll get race conditions. Use separate pages/tabs per worker, or use separate browser sessions.

3. WebSocket stability. CDP connections are WebSocket-based. If your worker loses network connectivity, the connection drops. The browser stays alive, but your Playwright objects become stale. Always wrap your automation in try/catch and reconnect on failure.

4. Version mismatches. Playwright expects a certain CDP version. If your remote browser is significantly older or newer than your Playwright version, you may hit protocol errors. Use a recent Playwright version and keep your browser host updated.

Production Checklist for CDP Playwright

Before you deploy CDP Playwright to production, verify these:

  • [ ] Browser host is stable — it should survive worker crashes and network blips.
  • [ ] CDP endpoint is secured — don't expose debugging ports to the public internet without authentication.
  • [ ] Session persistence is configured — cookies and local storage survive browser restarts.
  • [ ] Resource limits are set — cap the number of pages per browser and browsers per host.
  • [ ] Error handling is robust — reconnect logic for dropped WebSocket connections.
  • [ ] Monitoring is in place — track browser memory, CPU, and session age.

Conclusion

CDP Playwright is the missing link between your automation code and a browser that's already running. Whether you're building AI agents that need persistent sessions, scaling browser workloads across workers, or just tired of managing local Chrome installations, connectOverCDP gives you a clean path forward.

The pattern is simple: run a browser somewhere, expose its CDP endpoint, and connect to it from anywhere. For teams that don't want to build and maintain browser infrastructure, a hosted runtime like Remote Browser provides the persistent sessions, live debugging, and session isolation that production workloads require.

Start with a local Chrome instance and connectOverCDP to understand the model. Then move to a hosted solution when you need reliability at scale. Your future self—and your CI budget—will thank you.

For more on remote browser architectures, see our guides on remote browser APIs and controlling browsers remotely. And check the official Playwright CDP documentation for protocol details.