← Blog

BLOG

Automation Web: A Production Runtime for Browser Agents

Automation web workloads need a real browser runtime. Learn how hosted Chromium, CDP, and persistent profiles make web automation reliable.

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

Automation web work — driving real sites to log in, fill forms, scrape data, or complete multi-step tasks — breaks down the moment you run it on a laptop or a single CI box. The browser is stateful, the sites are hostile to headless traffic, and the process has to survive restarts. This guide covers what "automation web" actually means in production, where local setups fail, and how a hosted Chromium runtime with CDP access, persistent profiles, and session isolation closes the gap. If you are wiring an AI agent or a scripted pipeline to the web, the runtime choice matters more than the framework.

What "automation web" means in practice

Automation web is the discipline of programmatically controlling a real browser to complete tasks on live websites. It is not the same as calling an API. When a site has no API, or the API is gated, or the workflow spans several sites with a login in between, you fall back to the browser. That fallback is where most teams spend their engineering time.

The workloads that show up most often:

  • Agent-driven tasks. An LLM decides the next click, the runtime executes it. The browser must expose a stable control surface (CDP) and survive long, unpredictable sessions.
  • Scripted pipelines. Playwright, Puppeteer, or Selenium scripts that run on a schedule — price checks, report pulls, form submissions.
  • Authenticated flows. Anything behind a login. This is where persistent profiles and cookie continuity decide whether the job succeeds.
  • Data extraction at volume. Many concurrent sessions hitting the same site, each needing isolation so one job's cookies do not leak into another.

Each of these has the same underlying requirement: a browser that behaves like a real user's browser, runs somewhere durable, and can be driven by code you already know.

Why local browsers fail at automation web scale

A local Chrome install works for a demo. It fails for a fleet. The failure modes are predictable:

  1. State lives on one machine. Cookies, localStorage, and logged-in sessions are tied to a profile directory on disk. Move the job to another worker and you start from zero.
  2. Concurrency is bounded by the host. Ten parallel sessions on a laptop is already painful. Hundreds is not a conversation.
  3. Headless detection. Default headless Chromium leaks signals that many sites flag. You end up maintaining a patchwork of launch flags.
  4. No observability. When a job fails at step 14, you have a stack trace and nothing else. You cannot watch the session or replay it.
  5. Restart fragility. A crashed worker takes the browser with it. There is no clean way to resume a half-finished flow.

None of these are framework problems. Playwright and Puppeteer are fine. The problem is that the browser is treated as a local dependency instead of infrastructure.

The runtime layer: hosted Chromium over CDP

The fix is to separate the browser from the code that drives it. A hosted Chromium runtime runs the browser on managed infrastructure and exposes it over the Chrome DevTools Protocol. Your script — or your agent — connects to a WebSocket endpoint and drives the session exactly as if the browser were local.

This is the model Remote Browser uses. You get:

  • Hosted Chromium sessions created per job, isolated from each other.
  • CDP access so Playwright, Puppeteer, Selenium, and raw CDP clients all work.
  • A live viewer so you can watch a session in real time and debug failures as they happen.
  • Persistent profiles so logins and cookies survive across sessions.
  • Configurable browser settings including proxy and stealth-related options.
  • Usage controls so you can meter and cap consumption.

The important part is that none of this changes your code. You still write Playwright. You just point it at a remote endpoint instead of launching a local binary.

Connecting Playwright to a hosted session

The connection is a single call. Here is a TypeScript example that connects over CDP, creates a context, and runs a task:

import { chromium, Browser, BrowserContext, Page } from "playwright";

interface SessionInfo {
  cdpUrl: string; // wss://... provided by the runtime
}

async function runAutomationWebTask(session: SessionInfo): Promise<void> {
  let browser: Browser | undefined;
  let context: BrowserContext | undefined;

  try {
    // Connect to the hosted Chromium instance over CDP.
    browser = await chromium.connectOverCDP(session.cdpUrl);

    // Reuse the default context or create a fresh one for isolation.
    context = browser.contexts()[0] ?? (await browser.newContext());

    const page: Page = await context.newPage();

    await page.goto("https://example.com/login", {
      waitUntil: "domcontentloaded",
      timeout: 30_000,
    });

    await page.fill("#email", process.env.SITE_EMAIL ?? "");
    await page.fill("#password", process.env.SITE_PASSWORD ?? "");
    await page.click("button[type=submit]");

    // Wait for a post-login signal rather than a fixed sleep.
    await page.waitForSelector("[data-testid=dashboard]", {
      timeout: 20_000,
    });

    const title = await page.title();
    console.log(`Logged in, landed on: ${title}`);
  } finally {
    // Close the page/context you created; let the runtime reclaim the session.
    await context?.close().catch(() => {});
    await browser?.close().catch(() => {});
  }
}

Two details matter here. First, connectOverCDP attaches to an existing browser rather than launching one, so lifecycle is managed by the runtime. Second, waiting on a real selector instead of a fixed timeout is what separates a script that survives production from one that flakes. The Playwright CDP documentation covers the connection semantics in more depth.

Comparing local and hosted runtimes for web automation

The trade-offs are concrete. This table is the decision most teams actually face:

CriterionLocal Chrome / CI boxHosted Chromium runtime
Session stateTied to one machine's profile dirPersistent profiles, portable across workers
ConcurrencyBounded by host CPU/RAMScaled by the provider; capped by your plan
Headless detectionManual flag tuningConfigurable browser settings, proxy options
DebuggingLogs and stack traces onlyLive viewer plus CDP access
Restart behaviorBrowser dies with the workerSessions isolated; reconnect or recreate
Ops burdenYou patch, scale, and monitor ChromeProvider handles the browser layer
Cost modelFixed infra + your timeMetered per browser-hour (see /pricing)

The hosted column is not free of trade-offs. You take on a network dependency, and you need to think about data handling and where sessions run. For teams running a handful of jobs a week, local is fine. For anything that runs continuously, spans authenticated flows, or needs to be debugged after the fact, the hosted model pays for itself in engineering time alone.

Production criteria for website automation

Before committing to a runtime, evaluate it against the things that actually break in production. These are the questions worth asking.

Session isolation

Every job should get its own browser context or session. If two jobs share cookies, one job's login can corrupt another's. Isolation is not a nice-to-have when you run concurrent website automation against the same domain.

Persistent profiles

Authenticated flows are the hardest part of web page automation. A persistent profile lets you log in once, save the state, and reuse it. Without this, every run pays the login tax — and some sites will rate-limit or challenge repeated logins. Profiles also let you keep per-tenant state separate when you run automation on behalf of multiple customers.

Control surface

CDP is the lowest common denominator. If a runtime speaks CDP, it works with Playwright, Puppeteer, Selenium, and any agent framework that drives a browser. If it only exposes a proprietary API, you are locked in. Prefer runtimes that let you connect with the tools you already use.

Observability

A live viewer changes debugging from guesswork into inspection. When an agent gets stuck on a modal or a script fails on a selector, you want to see the page. Pair that with session recordings or logs and you can diagnose failures without reproducing them locally.

Usage controls

Metered browser-hours are the standard model. What matters is whether you can see consumption, cap it, and predict cost. Check /pricing for current rates and limits rather than assuming a number — pricing changes and the details are what count.

Network and proxy settings

Many automation web workloads need specific egress IPs or geographic presence. Configurable proxy settings matter. Be careful with claims about stealth or anti-detection — evaluate what a provider actually documents rather than what a marketing page implies.

Where AI agents fit into automation web

The rise of AI agents has changed the shape of web automation. Instead of a fixed script, an LLM observes the page and decides the next action. That model has different runtime requirements:

  • Long, unpredictable sessions. An agent may take fifty steps or five hundred. The browser must stay alive and reconnectable.
  • Stable observation. Agents need a reliable view of the DOM or a screenshot stream. CDP gives you both.
  • Recovery from dead ends. When an agent clicks into a bad state, you need to reset the context without tearing down the whole session.
  • Human handoff. A live viewer lets a person take over when the agent is stuck, which is often cheaper than retraining the agent.

This is why hosted runtimes and agent frameworks have converged. The agent supplies the reasoning; the runtime supplies a durable, observable browser. For a deeper look at that split, see Remote Browser for AI agents.

A practical migration path

If you are moving from local scripts to a hosted runtime, do it in stages.

  1. Abstract the connection. Put browser creation behind a function that returns a connected Browser. Swap the implementation from chromium.launch() to chromium.connectOverCDP() without touching call sites.
  2. Move one workload. Pick a single authenticated flow and run it on the hosted runtime. Measure failure rate and time-to-debug before and after.
  3. Add persistent profiles. Once the flow is stable, save and reuse profile state so logins stop being a per-run cost.
  4. Instrument usage. Track browser-hours per job so you can forecast cost. Compare against /pricing as volume grows.
  5. Scale concurrency. Only after a single workload is reliable should you fan out. Concurrency multiplies both throughput and the cost of a bad selector.

If you want a lower-commitment starting point, running a remote browser online covers the minimal setup. For teams comparing control models, remote control browser explains when code versus an agent should drive the session.

Common mistakes to avoid

  • Fixed sleeps instead of waits. waitForTimeout(5000) is the most common cause of flaky automation web jobs. Wait on selectors or network idle.
  • Sharing one context across jobs. Isolation is cheap; debugging cross-contaminated cookies is not.
  • Ignoring session lifecycle. Close contexts you create. Leaked sessions burn browser-hours.
  • Treating the runtime as magic. A hosted browser does not fix a bad selector or a race condition. It removes infrastructure pain, not logic bugs.
  • Assuming pricing is static. Always check /pricing for the current model before you build a cost projection.

Conclusion

Automation web is less about the framework and more about the runtime underneath it. Local Chrome gets you to a demo; a hosted Chromium runtime with CDP access, persistent profiles, session isolation, and a live viewer gets you to production. The migration is mostly mechanical — swap launch for connectOverCDP, move one workload, then scale. Start with the documentation to see the connection model, and check /pricing for current rates before you plan capacity.