← Blog

BLOG

Playwright Control Existing Browser: Connect to Live Chrome via CDP

Learn how to use Playwright to control an existing browser via CDP, keep sessions alive across workers, and scale reliably with Remote Browser.

September 5, 20269 min readRemote Browser

# Playwright Control Existing Browser: Connect to Live Chrome via CDP

Playwright is the de facto standard for browser automation, but its default model assumes you launch a fresh browser instance from your script. When you need to control an existing browser—one that already has cookies, an authenticated session, or a live page state—the standard playwright.chromium.launch() call won't cut it. This guide explains how to use Playwright's connectOverCDP method to attach to a running Chrome instance, why you'd want to do this in production, and how to scale that pattern across cloud workers without reinventing infrastructure.

Why Control an Existing Browser?

Most automation scripts start with a clean slate. That's fine for CI tests, but production workloads—especially AI agents—rarely have that luxury. Consider these scenarios:

  • Session persistence: A user logged into a SaaS dashboard. You need to run a task in that same authenticated context without re-entering credentials.
  • State preservation: A multi-step workflow that spans hours. The browser holds in-memory state (e.g., a draft form, a WebSocket connection) that you can't serialize to disk.
  • Human-in-the-loop debugging: An operator is watching a live browser session. You want to inject automated steps without killing the tab they're viewing.
  • Resource efficiency: Launching a full browser per task is expensive. Reusing a warm browser avoids cold-start latency and memory churn.

The Chrome DevTools Protocol (CDP) makes this possible. It exposes a debugging endpoint that allows external clients to inspect and drive a browser. Playwright's connectOverCDP is the official bridge between your script and that live browser.

Playwright's connectOverCDP: The Core Mechanism

Playwright provides two ways to connect to an existing browser: chromium.connectOverCDP(endpoint) and browserType.connect(wsEndpoint). The former is for Chrome/Chromium instances with the remote debugging port enabled; the latter is for Playwright's own browser server.

Here's a minimal TypeScript example that attaches to a running Chrome instance:

import { chromium } from 'playwright';

async function attachToExistingBrowser() {
  // Assumes Chrome was launched with --remote-debugging-port=9222
  const browser = await chromium.connectOverCDP('http://localhost:9222');

  // Get the existing default context (includes all open tabs)
  const contexts = browser.contexts();
  const context = contexts[0] || await browser.newContext();

  // Pick an existing page or create a new one
  const pages = context.pages();
  const page = pages[0] || await context.newPage();

  // You now control the live page, not a fresh one
  await page.goto('https://example.com');
  console.log(await page.title());

  // The session state (cookies, localStorage) is preserved
  await browser.close(); // This disconnects, does NOT kill the browser
}

attachToExistingBrowser();

Key detail: browser.close() on a CDP connection only disconnects your client. The underlying Chrome process keeps running. This is the opposite of launch(), where closing the browser kills the process. That distinction is what makes connectOverCDP suitable for controlling long-lived sessions.

Local Setup vs. Production Reality

The example above works locally. You launch Chrome with --remote-debugging-port=9222, run your script, and you're done. But production introduces problems that local setups don't have:

ConcernLocal Chrome + connectOverCDPRemote Browser (hosted Chromium)
Session persistenceDies when your laptop sleepsPersistent profiles stored server-side
Multi-worker accessSingle machine, single portMultiple workers can attach to same session
ScalingManual, per-machine setupAPI-driven browser provisioning
Network egressYour IP, your riskConfigurable proxy/egress settings
Resource managementYou monitor memory/CPUHosted, metered per browser-hour
Live debuggingLocal DevTools onlyLive viewer accessible via URL

The local approach works for a script you run once. It breaks when you need a browser that stays alive across multiple cloud workers, or when your AI agent needs to resume a task hours after the original worker was decommissioned.

Keeping Browser Sessions Alive Across Cloud Workers

A common pattern in AI agent architectures is the "worker pool." You have N workers that pick up tasks from a queue. Each task might require browser access. The naive approach—launch a browser per task—is wasteful and slow. The better approach is to maintain a pool of warm browsers that workers attach to on demand.

The challenge: a browser running on Worker A is unreachable from Worker B unless you expose it over the network. That's where a hosted browser runtime changes the game.

With Remote Browser, each browser session is a first-class resource with a stable CDP endpoint. Any worker—whether it's a Node.js process, a Python script, or an AI agent runtime—can connect to that endpoint using connectOverCDP. The session outlives any single worker. If Worker A crashes mid-task, Worker B can attach to the same browser, inspect the current state, and resume.

This pattern is essential for long-running agent tasks. A web research agent that needs to maintain a login session across 50 sub-tasks shouldn't re-authenticate 50 times. It should hold one browser session and have each worker attach to it.

Scaling Playwright Browser Workloads Reliably

Scaling browser automation is not just about adding more workers. It's about managing browser lifecycle, state isolation, and failure recovery. Here are the production criteria we've seen matter most:

1. Session Isolation vs. Sharing

You need both. Some tasks require a clean, isolated browser (e.g., testing a logout flow). Others require a shared, persistent session (e.g., an agent that maintains a shopping cart). A good runtime lets you provision both without changing your Playwright code.

2. Connection Resilience

CDP connections drop. Networks blip. Workers restart. Your automation code should handle disconnected events and know how to re-establish a connection to the same browser session. The browser itself should survive your client's death.

3. Resource Governance

Browsers consume memory. An idle browser that stays alive for days is a cost leak. You need controls to set session timeouts, maximum idle durations, and concurrent session limits. Without these, your cloud bill grows linearly with forgotten sessions.

4. Observability

When a task fails, you need to see what the browser was looking at. A live viewer or session recording is not a luxury; it's a debugging necessity. Screenshots help, but video or live DOM inspection is better.

How Remote Browser Implements This

Remote Browser provides hosted Chromium sessions that are accessible via CDP. This means your existing Playwright code works with minimal changes. Instead of launching a browser locally, you connect to a remote endpoint.

The workflow looks like this:

  1. Provision a browser session via the Remote Browser API or dashboard. You get a CDP endpoint URL.
  2. Connect with Playwright using chromium.connectOverCDP(your_endpoint).
  3. Run your automation exactly as you would locally.
  4. Disconnect when done. The session persists (or terminates, based on your configuration).

This approach solves the multi-worker problem because the browser lives in Remote Browser's infrastructure, not on any single worker. It solves the session persistence problem because profiles are stored and can be reattached. And it solves the scaling problem because you provision browsers via API, not by manually configuring machines.

For AI agents specifically, this pattern is critical. An agent that uses browser-use or similar frameworks needs a browser that can be paused, resumed, and inspected. The connectOverCDP pattern gives you that control.

Comparison: Playwright Launch vs. ConnectOverCDP

Aspectchromium.launch()chromium.connectOverCDP()
Browser lifecycleManaged by PlaywrightManaged externally (you or a runtime)
Session stateFresh each launchPreserved from existing browser
Use caseCI tests, isolated tasksPersistent sessions, live debugging
ScalingPer-task browser spin-upReuse warm browsers across tasks
Failure recoveryRestart from scratchReattach to existing session
Resource costHigh per taskLower per task after warm-up

Security Considerations for Remote Browser Control

Exposing a browser over CDP is a security-sensitive operation. Anyone with access to the CDP endpoint can control the browser, read cookies, and exfiltrate session data. When you run a local browser with --remote-debugging-port, you're exposing it to anything on your local network. That's acceptable for a dev machine, not for production.

When using a hosted runtime, look for:

  • Authentication on the CDP endpoint: The endpoint should require a token or API key, not just be an open port.
  • Network isolation: The browser should not be reachable from the public internet without credentials.
  • Session isolation: Different tasks should not accidentally share browser contexts unless explicitly configured.
  • Audit logs: You should be able to see who connected to a session and when.

Remote Browser implements these controls. Each session endpoint is authenticated, and you can configure session isolation per task. For more details on the security model, see our documentation.

Practical Example: AI Agent with Persistent Login

Let's put this together. Suppose you're building an AI agent that monitors a competitor's pricing page. The page requires login. You don't want the agent to log in every time it checks prices—that's slow and might trigger anti-bot measures.

Here's the architecture:

  1. Provision a browser session with a persistent profile.
  2. Manually log in once (or via an initial automation script).
  3. Store the session ID in your agent's state.
  4. On each task, connect to the existing session via CDP, navigate to the pricing page, extract data, and disconnect.

The agent never re-authenticates. The session stays warm. Each task is fast because the browser is already running.

This pattern works with any Playwright-compatible tooling. If you're using browser-use or a similar agent framework, the same principle applies: connect to a remote browser rather than launching a fresh one.

When Not to Use connectOverCDP

connectOverCDP is not always the right answer. Consider alternatives when:

  • You need a clean state for every test: Use launch() to guarantee isolation.
  • You're running thousands of parallel, independent tasks: A pool of fresh browsers might be simpler than managing shared sessions.
  • Your browser version is non-standard: CDP is Chromium-specific. If you need Firefox or WebKit, Playwright's connect() method (not connectOverCDP) is the path, but it requires a Playwright-managed browser server.

For Firefox specifically, CDP support is limited. Playwright's official docs note that connectOverCDP is Chromium-only. If you need cross-browser support, you'll need a different approach.

Production Checklist for Playwright + Existing Browser

Before you deploy a system that controls existing browsers, verify these points:

  • [ ] Reconnection logic: Your code handles browser.on('disconnected') and reconnects.
  • [ ] Session timeouts: Idle sessions are terminated to control costs.
  • [ ] Error recovery: If a page is in a bad state, you can reset the context without killing the browser.
  • [ ] Credential storage: Login tokens are stored securely, not in the browser profile that might be inspected.
  • [ ] Concurrency limits: You know how many sessions you can run simultaneously without exhausting memory.

Conclusion

Playwright's connectOverCDP is the correct tool when you need to control an existing browser rather than launch a fresh one. It enables session persistence, multi-worker access, and live debugging. But the local version of this pattern doesn't scale to production.

Remote Browser provides the hosted runtime that makes this pattern viable at scale. By provisioning Chromium sessions as API resources, you get the benefits of connectOverCDP without the operational burden of managing browser processes yourself. Your Playwright code stays the same; only the connection target changes.

If you're building an AI agent that needs reliable browser access, or you're scaling Playwright workloads beyond a single machine, the ability to control an existing browser is not optional—it's the difference between a demo and a production system. For pricing and session limits, check the pricing page. To understand how this fits into a broader agent architecture, read our guide on remote browsers for AI agents.

For the official CDP connection details, refer to the Playwright documentation on connectOverCDP.