← Blog

BLOG

Browserbase Vs Playwright: Which Fits Your Agent Stack

Browserbase vs Playwright compared for AI agents: what each layer does, where they overlap, and how to pick a remote browser runtime for production.

September 10, 20269 min readRemote Browser

# Browserbase Vs Playwright

Browserbase vs Playwright is not really a head-to-head contest, because the two things live at different layers of the stack. Playwright is a browser automation library you install and run. Browserbase is a hosted browser service you call over the network. The confusion comes from the fact that both end up in the same agent.run() loop, so people compare them as if you had to pick one.

You don't. In most production agent stacks you use both: Playwright (or Puppeteer, or raw CDP) as the client, and a hosted runtime as the browser. The real question is where that browser process runs, who patches it, who keeps it alive across retries, and what you pay when a task takes forty minutes instead of four seconds.

This post breaks down the actual decision: what Playwright gives you, what a hosted runtime like Browserbase or Remote Browser gives you, and the criteria that matter when you move from a laptop script to something that runs unattended.

What Playwright actually is

Playwright is an open-source automation library from Microsoft. You install it with npm i -D playwright (or pip install playwright), then run npx playwright install to download browser binaries for Chromium, Firefox, and WebKit. From there you write code that launches a browser, opens pages, and drives them.

import { chromium } from 'playwright';

const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());
await browser.close();

That's the whole model. Playwright owns the protocol layer: it speaks CDP to Chromium, a patched protocol to Firefox, and WebKit's inspector protocol to WebKit. It handles auto-waiting, actionability checks, network interception, tracing, and a test runner. It is genuinely excellent at all of that.

What Playwright does not do:

  • It does not host browsers for you. chromium.launch() spawns a process on whatever machine runs your code.
  • It does not manage browser binaries across a fleet. Every worker needs playwright install run against a matching version.
  • It does not give you persistent profiles, rotating outbound IPs, or session isolation as a service.
  • It does not survive your process dying. If the Node process exits, the browser context is gone.

Those gaps are not flaws. Playwright is a library, and libraries do library things. The gaps only matter when you run agents in production, where "the process died and lost the session" is a Tuesday.

What Browserbase actually is

Browserbase is a hosted browser infrastructure product. You send an API request, it returns a session with a CDP WebSocket URL, and you connect Playwright to that URL instead of launching locally.

import { chromium } from 'playwright';

const browser = await chromium.connectOverCDP(wsEndpoint);
const context = browser.contexts()[0];
const page = context.pages()[0] ?? await context.newPage();

The browser process runs in Browserbase's cloud. You get session lifecycle management, a live view URL for debugging, and some stealth and proxy configuration. It's a real product solving a real problem: nobody wants to run a Chromium fleet.

The trade-offs are the usual ones for managed infrastructure. You're paying per browser-hour, you're dependent on their uptime and their Chromium build, and your agent's network traffic now leaves your VPC. For a lot of teams that's fine. For teams with data residency constraints or unusual browser requirements, it's a blocker.

The comparison that actually matters

Here's the honest breakdown. "Browserbase vs Playwright" collapses into "hosted runtime vs self-managed runtime," and the client library is a separate axis.

DimensionPlaywright (self-hosted)Browserbase (hosted)
What you installplaywright npm package + browser binariesNothing; you call an API
Where Chromium runsYour machine, container, or VMTheir cloud
Session persistenceYou manage it; context dies with processSession survives client disconnects
Browser version controlYou pin it; you patch itThey pin it; you inherit it
Scaling modelAdd workers, manage memory per ChromiumRequest sessions; concurrency per plan
DebuggingLocal traces, headed mode, PWDEBUG=1Live view URL, session recordings
Network egressStays in your infraLeaves your infra
Cost shapeCompute you already pay forPer browser-hour, see /pricing
Best forLocal dev, CI tests, trusted sitesAgents hitting real sites at scale

The row people underestimate is session persistence. With local Playwright, if your agent crashes mid-task, the browser is gone and the login state with it. With a hosted runtime, the session can outlive the client, which means a retry can reconnect to the same context instead of starting over.

Where the client library still wins

If you're writing tests, stop reading. Playwright's test runner is the right tool and a hosted runtime adds latency and cost for no benefit. npx playwright test against local Chromium is faster, cheaper, and easier to debug.

Playwright also wins when:

  • You need Firefox or WebKit specifically. Hosted runtimes are almost universally Chromium-only, because CDP is the only protocol with broad remote support. See the Playwright CDP docs for the exact constraints.
  • You're automating an internal tool behind a VPN. Routing that through a third party is usually a non-starter.
  • You need a browser extension loaded. Extensions require a persistent context with specific launch flags, which is awkward to configure remotely.
  • You're prototyping. chromium.launch() in a script beats provisioning a session for a one-off check.

The pattern is consistent: the closer you are to development, the more local Playwright makes sense.

Where a hosted runtime wins

The calculus flips when the workload is long-running, unattended, and hitting sites you don't control.

Session lifetime. An agent researching a topic might run for twenty minutes across forty page loads. Locally, that's a process you have to babysit. On a hosted runtime, the session is a resource with a lifecycle, and your worker can be stateless.

Isolation. Running ten agents in one Chromium process means shared cookies, shared storage, and cross-contamination when one agent logs into the wrong account. Hosted runtimes give each session its own browser context by default. If you're doing this locally you need to build it yourself with browser.newContext() and careful cleanup.

Browser binary drift. playwright install downloads ~400MB per browser. Multiply by your CI matrix and your worker fleet and you have a real maintenance surface. Hosted runtimes absorb that. You also stop hitting the classic "playwright uninstall browsers" cleanup problem on ephemeral runners.

Configurable browser settings. Hosted runtimes typically expose proxy configuration, user-agent overrides, viewport, timezone, and locale as session parameters. Doing this locally means threading launch options through your code and keeping them consistent across workers. Playwright's browser launch options are powerful but they're per-process, not per-tenant.

Live debugging. When an agent fails at step 34 of a 40-step task, a screenshot is not enough. A live viewer that lets you attach to the running session and see what the agent sees is worth more than any trace file. Remote Browser exposes this through the session API; see /blog/remote-control-browser for how it works in practice.

The architecture that most teams land on

The production pattern is boring and it works:

  1. Your agent code uses Playwright as the client. No change to how you write selectors or waits.
  2. Instead of chromium.launch(), you call your runtime's session API and get a CDP endpoint.
  3. You connectOverCDP() and run the same code.
  4. Session lifecycle, proxies, and profile persistence are handled by the runtime.
  5. Your worker is stateless and can be killed and restarted without losing the browser.
import { chromium, Browser, Page } from 'playwright';

async function runTask(taskId: string, wsEndpoint: string) {
  const browser: Browser = await chromium.connectOverCDP(wsEndpoint);
  const context = browser.contexts()[0];
  const page: Page = context.pages()[0] ?? await context.newPage();

  try {
    await page.goto('https://example.com/login');
    await page.fill('#email', process.env.AGENT_EMAIL!);
    await page.fill('#password', process.env.AGENT_PASSWORD!);
    await page.click('button[type=submit]');
    await page.waitForURL('**/dashboard');
    // ... agent work
  } finally {
    // Disconnect without killing the remote browser.
    await browser.close();
  }
}

Note the finally block. With connectOverCDP, browser.close() disconnects your client; it does not necessarily terminate the remote browser. That distinction is the whole point of the hosted model. Your worker can die and the session keeps running.

Choosing between Browserbase and Remote Browser

If you've decided you want a hosted runtime, the next question is which one. The honest answer is that the category is converging and the differences are in the details.

Things worth evaluating:

  • CDP compatibility. Can you connect with stock Playwright, or do you need their SDK? Remote Browser exposes standard CDP, so connectOverCDP works unmodified. That matters if you want to keep your code portable.
  • Profile persistence. Can you reuse a logged-in profile across sessions, or do you re-authenticate every time? Persistent profiles are the difference between a demo and a product.
  • Live viewer. Can you attach to a running session and take over? This is the single biggest debugging accelerator for agent work.
  • Pricing model. Per browser-hour is standard. Watch for whether idle time counts and whether there's a minimum. See /pricing for current Remote Browser rates.
  • Egress and data handling. Where does traffic originate, and what's logged?

For a deeper look at the runtime layer itself, /blog/remote-browser-for-ai-agents covers the architecture in more detail, and /blog/remote-browser-online walks through getting a session running without local setup.

Common migration mistakes

A few things bite people moving from local Playwright to a hosted runtime:

Assuming `browser.close()` kills the session. It doesn't. You need an explicit session-terminate call, or you'll leak browser-hours. Check your runtime's API for the terminate endpoint.

Forgetting that `contexts()[0]` may be empty. Some runtimes return a browser with no default context. Always fall back to newPage().

Re-running `playwright install` in the worker. You don't need browser binaries if you're connecting over CDP. Skipping the install cuts your container image by a large margin and removes a whole class of version-mismatch bugs.

Ignoring timeouts. Remote sessions have network latency between your client and the browser. Playwright's default timeouts are tuned for localhost. Bump them, or you'll get spurious failures on slow pages.

Not pinning the Playwright version. CDP is mostly stable but not perfectly. If your runtime upgrades Chromium and you're on an old Playwright, you can hit protocol mismatches. Pin both sides.

The short version

Playwright is a client library. Browserbase is a hosted browser service. They solve different problems and you will probably use both.

Use local Playwright for tests, prototyping, internal tools, and anything that needs Firefox or WebKit. Use a hosted runtime when your agents run unattended, need persistent sessions, hit sites you don't control, or when maintaining a Chromium fleet has become someone's job.

If you want the hosted side without changing your Playwright code, Remote Browser exposes standard CDP endpoints you can connectOverCDP into, with persistent profiles, session isolation, a live viewer, and configurable browser settings. Start with the documentation to get a session running, then check /pricing to see how browser-hours are metered.