← Blog

BLOG

Playwright Or Selenium: Choosing a Browser Stack for Agents

Playwright or Selenium for AI agents and automation? Compare protocols, language support, and where a hosted Chromium runtime fits.

8 min readRemote Browser
Ivory computer towers connected across terracotta platforms in a quiet desert landscape
The infrastructure behind your browserREMOTE BROWSER / ILLUSTRATION

If you are deciding between Playwright or Selenium, the short answer is this: Playwright is the better default for new browser automation, especially anything driven by AI agents, because it speaks the Chrome DevTools Protocol directly, ships auto-waiting, and has first-class TypeScript support. Selenium still wins in specific situations — legacy suites, broad real-device grids, and teams standardized on WebDriver. This guide explains the trade-offs concretely, then shows how either stack connects to a hosted Chromium runtime so you are not managing browser infrastructure yourself.

The choice matters more than it used to. When a language model is issuing the commands, the cost of a flaky selector or a race condition compounds across every step. The protocol your tool speaks, and where the browser actually runs, determine whether your agent finishes tasks or stalls on a spinner.

Playwright vs Selenium: the core difference

Both tools drive a real browser, but they take different paths to it.

Selenium implements the W3C WebDriver standard. Your script sends HTTP commands to a driver process (chromedriver, geckodriver), which translates them into browser actions. It is a mature, language-agnostic protocol with bindings for Java, Python, C#, Ruby, JavaScript, and more.

Playwright talks to Chromium over the Chrome DevTools Protocol (CDP), and to Firefox and WebKit over their own patched protocols. It runs an in-process connection to the browser rather than routing through a separate driver binary. That gives it tighter control over network interception, request mocking, and execution context.

The practical consequence: Playwright can see and manipulate things WebDriver abstracts away — network requests, service workers, multiple browser contexts in one instance. Selenium's abstraction is the point; it is portable across browsers and vendors at the cost of depth.

Side-by-side comparison

DimensionPlaywrightSelenium
ProtocolCDP (Chromium), patched protocols (Firefox/WebKit)W3C WebDriver over HTTP
Auto-waitingBuilt in (actionability checks)Manual waits required
Language supportTypeScript/JS, Python, Java, .NETJava, Python, C#, Ruby, JS, and more
Browser coverageChromium, Firefox, WebKitChrome, Firefox, Edge, Safari, IE (legacy)
Network interceptionNative (page.route)Limited; needs proxy or CDP escape hatch
Multi-contextYes, isolated contexts per browserOne session per driver
Real device gridsLimitedStrong (Appium, cloud device farms)
Ecosystem maturityYounger, fast-movingVery mature, huge community
Best fitNew automation, agents, modern web appsLegacy suites, cross-vendor grids, mobile

Neither column is universally better. The table is a decision aid, not a verdict.

When Playwright is the right call

Choose Playwright when you are starting fresh or building agent-driven automation. The reasons are concrete:

  • Auto-waiting reduces flakiness. Playwright waits for elements to be visible, stable, and enabled before acting. With an LLM generating steps, you cannot hand-tune a sleep for every interaction. Built-in actionability checks absorb timing variance.
  • CDP access is native. Network interception, request mocking, and console capture are first-class. If your agent needs to read API responses the page fires, Playwright exposes them without a workaround.
  • Isolated contexts are cheap. You can spin up multiple BrowserContext objects in one browser instance, each with its own cookies and storage. That maps well to per-task isolation for agents.
  • TypeScript is a first-class citizen. Types for locators, pages, and responses catch errors at compile time — valuable when the code is generated or reviewed by a model.

If you are wiring Playwright to a remote browser, the connection is a single call. The Playwright CDP documentation covers connectOverCDP in detail.

import { chromium, Browser, Page } from 'playwright';

async function connectToHostedBrowser(wsEndpoint: string): Promise<void> {
  // Connect to a remote Chromium instance over CDP.
  const browser: Browser = await chromium.connectOverCDP(wsEndpoint);

  // Reuse the default context or create an isolated one per task.
  const context = await browser.newContext({
    viewport: { width: 1280, height: 800 },
  });
  const page: Page = await context.newPage();

  await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });

  // Auto-waiting: no manual sleep needed before interacting.
  await page.getByRole('link', { name: 'More information' }).click();

  const title = await page.title();
  console.log('Page title:', title);

  await context.close();
  await browser.close();
}

connectToHostedBrowser(process.env.BROWSER_WS_ENDPOINT!).catch(console.error);

The wsEndpoint comes from your runtime provider. With Remote Browser, you create a session through the API and receive a CDP WebSocket URL you pass straight into connectOverCDP. No local Chrome install, no driver binary to version-match.

When Selenium still makes sense

Selenium is not obsolete. It is the right tool in several real scenarios:

  • You have a large existing suite. Rewriting thousands of Selenium tests into Playwright is rarely worth it unless flakiness is actively costing you. Migrate incrementally.
  • You need real mobile devices. Selenium pairs with Appium for native and mobile web testing across device farms. Playwright's mobile emulation is viewport-level, not real hardware.
  • Your team is standardized on WebDriver. If your CI, reporting, and grid infrastructure are built around Selenium Grid, the switching cost is real.
  • You need the widest language coverage. Selenium's Ruby and legacy bindings have no Playwright equivalent.

For agent workloads specifically, Selenium is workable but requires more scaffolding. You will write explicit waits, manage driver lifecycles, and often reach for CDP anyway when you need network-level visibility. That is friction an LLM-driven loop does not handle gracefully.

The runtime question matters as much as the framework

Here is the part most comparisons skip: the framework is only half the decision. Where the browser runs determines reliability, cost, and how much infrastructure you maintain.

Running Playwright or Selenium locally means installing browser binaries, matching versions to your driver, and provisioning machines that can handle concurrent sessions. At scale — many agents running in parallel — that becomes a scheduling and isolation problem. Headless Chromium is memory-hungry, and a crashed browser takes its session with it.

A hosted Chromium runtime moves that layer off your plate. You get:

  • CDP access over a WebSocket endpoint that Playwright, Puppeteer, or Selenium can connect to.
  • Session isolation so one agent's cookies and storage do not leak into another's.
  • Persistent profiles for workflows that need to stay logged in across sessions.
  • A live viewer so you can watch and debug a session in real time instead of reading logs.
  • Configurable browser settings for proxy and stealth-related behavior, within what the provider supports.

This is where the Playwright-or-Selenium question connects to a bigger one: do you want to run browsers, or do you want to run tasks? For most agent teams, the answer is tasks. The remote browser for AI agents guide covers the runtime layer in depth.

Connecting Selenium to a remote browser

Selenium can also drive a remote browser, though the path is different. You point the WebDriver at a remote endpoint using RemoteWebDriver, or you use CDP through Selenium 4's ChromiumDriver to attach to an existing session. The latter gives you network and console access that plain WebDriver lacks.

The trade-off is the same as locally: Selenium's abstraction means more manual waiting and less native control. If you are starting an agent project today, Playwright's ergonomics will save you time. If you are extending an existing Selenium suite, connect it to a hosted runtime rather than provisioning your own grid — you keep your tests and drop the infrastructure burden.

Production criteria to evaluate

Whichever framework you pick, judge the runtime against these criteria before committing:

  1. Protocol fidelity. Does the provider expose a real CDP endpoint, or a lossy wrapper? Test connectOverCDP and confirm network events fire.
  2. Session lifecycle. Can you create, reuse, and tear down sessions programmatically? Are persistent profiles available for login-dependent flows?
  3. Isolation. Are sessions truly separate, or do they share a browser process? Shared processes mean shared failure domains.
  4. Observability. Is there a live viewer? Can you capture console logs, network traces, and screenshots mid-session?
  5. Usage controls. How is consumption metered, and can you cap it? Check /pricing for current details rather than assuming a rate.
  6. Proxy and network settings. If your tasks need specific egress, confirm what is configurable.

These criteria apply whether you are running a test suite or an autonomous agent. The difference is that agents hit edge cases more often, so observability and isolation matter more.

A note on browser control and MCP

If you are building agents that control a browser through a tool interface, you may encounter MCP-based browser servers — Chrome MCP extensions, browser MCP tools, and similar. These wrap browser control in a protocol an LLM can call. They are useful for prototyping, but they inherit the reliability of whatever browser they drive.

The framework underneath still matters. An MCP server that drives Playwright over CDP against a hosted Chromium session is more robust than one that drives a local browser through an extension, because the session is isolated, observable, and does not depend on a user's desktop being awake. If you are evaluating browser control approaches, read remote control browser for how the pieces fit.

Recommendation

For new projects — especially agent-driven automation — start with Playwright. Its auto-waiting, native CDP access, and TypeScript support reduce the failure modes that plague LLM-generated steps. Connect it to a hosted Chromium runtime so you are not provisioning browsers.

For existing Selenium suites, do not rewrite for its own sake. Connect your suite to a hosted runtime, keep your tests, and shed the grid maintenance. Migrate to Playwright incrementally if flakiness becomes a real cost.

The framework choice is reversible. The runtime choice compounds. Pick a runtime that exposes real CDP, isolates sessions, and gives you a live view — then let the framework follow. Start with the documentation to see how a session is created and connected, and review /pricing for current usage details before you scale.

Playwright or Selenium is a real question, but it is not the only one. Answer it, then answer where the browser runs. That second answer is what keeps your agents finishing tasks in production.