BLOG
Playwright Attach to Existing Browser: A Practical Guide
Learn how to use Playwright attach to existing browser sessions via CDP for AI agents and automation. A practical guide to remote browser connections.
# Playwright Attach to Existing Browser: A Practical Guide
If you've ever tried to run a Playwright script against a browser that's already open, you know the default behavior: Playwright launches its own browser instance, runs your script, and tears everything down. That works fine for simple tests, but it falls apart when you need to attach to an existing browser session—especially in production AI agent workloads where you need persistent sessions, live debugging, or state that survives across multiple workers.
This guide covers how to use Playwright attach to existing browser via the Chrome DevTools Protocol (CDP), why you'd want to do it, and how hosted browser runtimes make this pattern practical at scale.
Why Attach to an Existing Browser?
The standard Playwright workflow is straightforward: chromium.launch() creates a fresh browser, browser.newPage() opens a tab, and you run your automation. But this model has real limitations:
- No persistence. When the script ends, the browser dies. Any cookies, localStorage, or session state is gone.
- No external control. You can't open a browser in one process and drive it from another.
- No live debugging. You can't watch what the browser is doing in real time unless you're running headed locally.
- No cross-worker state. If you're running automation across multiple cloud workers, each worker gets a fresh browser with zero shared state.
Attaching to an existing browser solves these problems. Instead of launching a new browser, you connect to one that's already running—either locally or remotely—and drive it via CDP.
How Playwright Attach to Existing Browser Works
Playwright provides two ways to connect to an existing browser:
1. chromium.connectOverCDP()
This is the most common approach. It connects to a browser that's already running with a CDP endpoint exposed. Here's the basic pattern:
import { chromium } from 'playwright';
// Connect to an existing browser via CDP
const browser = await chromium.connectOverCDP('http://localhost:9222');
// Get the default context or create a new one
const context = browser.contexts()[0] || await browser.newContext();
const page = await context.newPage();
// Now you're driving the existing browser
await page.goto('https://example.com');
await page.screenshot({ path: 'example.png' });
// Don't close the browser—you're attached to it
await browser.close();The key difference: browser.close() here only disconnects your client. It doesn't kill the underlying browser process. That's the whole point of attaching.
2. chromium.connect()
This connects to a browser launched with --remote-debugging-pipe or via a WebSocket endpoint. It's less common for attaching to existing sessions because it requires the browser to be launched with specific flags.
The CDP Connection Details
When you launch Chromium with remote debugging enabled, it exposes a CDP endpoint. The standard way to launch a browser for external attachment:
chromium --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-profileThis starts Chromium with a debugging port. You can then connect from Playwright using connectOverCDP('http://localhost:9222').
For remote browsers, the endpoint is typically a WebSocket URL like wss://browser.example.com/devtools/browser/.... Playwright's connectOverCDP() accepts both HTTP and WebSocket URLs.
The Problem: Local Attach Doesn't Scale
Attaching to a local browser works fine for development. But in production, you run into issues:
- Where does the browser live? If you're running automation on a server, the browser needs to be on that server—or reachable over the network.
- How do you keep it alive? A browser process that crashes or gets killed by the OS needs to be restarted.
- How do you manage multiple sessions? If you have multiple agents or test suites, each needs its own browser instance with isolated state.
- How do you handle proxies and IP rotation? If your automation needs different IPs per session, a single local browser won't cut it.
This is where hosted browser runtimes come in. Instead of managing your own Chromium instances, you use a service that provides remote browsers with CDP endpoints you can attach to from anywhere.
Remote Browser: Attach to Existing Sessions in the Cloud
Remote Browser provides hosted Chromium sessions that you can attach to via CDP, Playwright, Puppeteer, or Selenium. The workflow is similar to connecting to a local browser, but the browser lives in the cloud.
Here's what that looks like in practice:
import { chromium } from 'playwright';
// Connect to a hosted browser session via CDP
const browser = await chromium.connectOverCDP('wss://remote-browser.dev/cdp/session-123');
// The session persists—you can reconnect from any worker
const context = browser.contexts()[0];
const page = await context.newPage();
// Run your automation
await page.goto('https://example.com');
const title = await page.title();
console.log(title);
// Disconnect—the browser stays alive for the next worker
await browser.close();The critical difference: the browser session persists after you disconnect. You can attach from one worker, disconnect, and reattach from another worker later. This is what makes Playwright attach to existing browser viable for production AI agent workloads.
Comparison: Local vs. Hosted Browser Attachment
| Aspect | Local Browser Attach | Remote Browser (Hosted) |
|---|---|---|
| Setup | Launch Chromium with --remote-debugging-port | Create a session via API |
| Persistence | Dies with the process | Session persists until explicitly ended |
| Cross-worker access | Not possible (single machine) | Yes—attach from any worker |
| Live debugging | Local only | Live viewer in browser |
| Proxy support | Manual configuration | Configurable per session |
| Scaling | Limited to one machine | Horizontal scaling |
| Session isolation | Manual (user-data-dir) | Built-in per session |
| Infrastructure | You manage it | Managed by the provider |
When to Use Playwright Attach to Existing Browser
This pattern is useful in several scenarios:
AI Agents with Long-Running Tasks
AI agents often need to maintain browser state across multiple steps or even multiple API calls. Instead of launching a fresh browser for each step, you attach to a persistent session. This preserves login state, cookies, and page context.
Multi-Worker Automation
If you're processing a queue of tasks across multiple workers, each worker can attach to the same browser session (or different sessions) without losing state. This is especially useful for tasks that require a consistent identity or session.
Live Debugging and Monitoring
When you attach to a browser session, you can watch what's happening in real time. Remote Browser provides a live viewer for this purpose. You can see exactly what your agent is doing, intervene if needed, and record sessions for later analysis.
Session Reuse Across Retries
If an automation task fails midway, you can reattach to the same browser session and resume from where you left off—rather than starting from scratch.
Production Considerations for Browser Attachment
Before you build your automation around attaching to existing browsers, consider these factors:
Session Lifecycle Management
When you attach to a browser, you need to decide when the session ends. Options include:
- Time-based expiry. Sessions automatically terminate after a set duration.
- Idle timeout. Sessions end after a period of inactivity.
- Explicit termination. You call an API to end the session.
Remote Browser supports configurable session lifetimes. Check the documentation for specifics on session management.
State Isolation
If you're running multiple agents or test suites, you need to ensure they don't interfere with each other. Each session should have isolated state—separate cookies, localStorage, and cache. Remote Browser provides session isolation by default.
Network and Proxy Configuration
Some automation tasks require specific IP addresses or proxy configurations. When attaching to a remote browser, you need to ensure the browser session has the right network settings. Remote Browser allows you to configure proxy settings per session.
Resource Usage
Each browser session consumes memory and CPU. If you're running many concurrent sessions, you need to monitor resource usage and scale accordingly. Remote Browser provides usage controls to help you manage this.
Code Example: Attaching to a Remote Browser with Playwright
Here's a complete example of attaching to a remote browser session using Playwright:
import { chromium } from 'playwright';
async function attachToRemoteBrowser(wsEndpoint: string) {
// Connect to the existing browser session
const browser = await chromium.connectOverCDP(wsEndpoint);
try {
// Get the existing context or create a new one
const context = browser.contexts()[0] || await browser.newContext();
// Create a new page in the existing session
const page = await context.newPage();
// Navigate and interact
await page.goto('https://example.com');
await page.fill('input[name="q"]', 'playwright attach to existing browser');
await page.press('input[name="q"]', 'Enter');
await page.waitForLoadState('networkidle');
// Extract data
const results = await page.$$eval('h3', els => els.map(el => el.textContent));
console.log('Search results:', results);
// The session persists after we disconnect
} finally {
// This only disconnects the client—it doesn't kill the browser
await browser.close();
}
}
// Usage
const wsEndpoint = 'wss://remote-browser.dev/cdp/session-abc123';
await attachToRemoteBrowser(wsEndpoint);Common Pitfalls and How to Avoid Them
Closing the Browser When You Mean to Disconnect
The most common mistake is calling browser.close() and expecting the session to persist. With connectOverCDP(), browser.close() only disconnects your client. But if you're using chromium.launch() and then trying to attach, you'll kill the browser.
Fix: Always use connectOverCDP() or connect() when attaching to an existing browser.
Assuming the Default Context Exists
When you attach to a browser, it may not have any contexts yet. Always check browser.contexts() and create a context if needed.
Ignoring Session Timeouts
Remote browser sessions don't last forever. If your automation runs longer than the session lifetime, you'll lose the connection. Plan for session renewal or reattachment.
Not Handling Disconnects Gracefully
Network issues can cause your client to disconnect from the browser. Your code should handle reconnection logic, especially for long-running tasks.
The Browser-as-a-Service Advantage
Using a hosted browser runtime like Remote Browser eliminates the infrastructure burden of managing your own Chromium instances. Instead of worrying about browser versions, security patches, and resource allocation, you focus on your automation logic.
For AI agents, this is particularly valuable. Your agent can attach to a browser session, perform tasks, disconnect, and reattach later—all without managing browser infrastructure. This is the pattern behind many production AI web agents.
If you're building an AI agent that needs browser access, check out our guide on remote browsers for AI agents for a deeper dive.
Getting Started
To start using Playwright attach to existing browser with Remote Browser:
- Create a session. Use the API to create a browser session and get a CDP WebSocket endpoint.
- Connect from Playwright. Use
chromium.connectOverCDP()with the endpoint. - Run your automation. Drive the browser as you normally would.
- Disconnect and reattach. The session persists for future connections.
For pricing and session limits, see the pricing page. For detailed API documentation, visit the documentation.
Conclusion
Playwright attach to existing browser is a powerful pattern for persistent browser automation. It enables stateful sessions, cross-worker coordination, and live debugging—capabilities that are essential for production AI agents and complex automation workflows.
The key is using CDP to connect to a browser that's already running, rather than launching a new one. Locally, this works for development. In production, a hosted browser runtime makes this pattern scalable and reliable.
Whether you're building an AI agent, a web scraping pipeline, or a complex test suite, attaching to existing browser sessions gives you the persistence and control you need. For more context on how remote browsers fit into your stack, see our overview of remote browser infrastructure and remote control browser patterns.
For the technical details on CDP, refer to the Chrome DevTools Protocol documentation.