← Blog

BLOG

Browser Use Production Examples: Real Agent Workflows

Concrete browser use production examples for AI agents: login flows, data extraction, and CI checks on hosted Chromium with CDP and Playwright.

September 22, 20268 min readRemote Browser

# Browser Use Production Examples: Real Agent Workflows

Most browser use production examples you find online stop at "the agent clicked a button." That is a demo, not a production pattern. Production means the same task runs at 3 a.m. on a machine you never log into, against a site that changed its layout last week, with a session that has to survive a worker restart. This post walks through concrete browser use production examples — login-gated extraction, multi-step form submission, and CI smoke checks — and shows what each one requires from the runtime underneath.

The primary keyword here is browser use production examples, and the goal is to give you patterns you can copy, not a tour of a framework. If you want the runtime background first, start with Remote browsers for AI agents and come back.

What separates a demo from a production example

A browser use example becomes a production example when it has to answer four questions:

  • Where does the browser run? Local Chrome on a laptop does not scale past one concurrent task, and it dies when the laptop sleeps.
  • How does the agent reconnect? If the session is tied to a process, a crash loses the task. Production sessions are addressable over a network endpoint.
  • What happens when the site fights back? CAPTCHAs, rate limits, and geo-blocks are normal, not exceptional.
  • How do you debug a failure at 3 a.m.? You need a live view or a recording, not a stack trace from a headless process you cannot see.

Every example below assumes a hosted Chromium session reachable over CDP. That is the same connection model Playwright and Puppeteer already use locally, so the code changes are small. The Chrome DevTools Protocol documentation is the reference for what that endpoint exposes.

Example 1: Login-gated data extraction

This is the most common browser use production example, and the one most likely to break. An agent logs into a vendor portal, navigates to a report, and pulls structured rows.

The failure modes are predictable:

  • The login form has a second factor or a "remember this device" cookie that expires.
  • The report is behind a session that resets on every new browser context.
  • The site rate-limits repeated logins from the same IP.

The production fix is persistent profiles plus a stable egress IP. A persistent profile keeps cookies and local storage across sessions, so the agent logs in once and reuses the authenticated state. A stable proxy keeps the login from looking like a new device every run.

import { chromium } from "playwright";

// Connect to a hosted Chromium session over CDP.
// The endpoint comes from your session API; treat it as a secret.
const browser = await chromium.connectOverCDP(process.env.BROWSER_WS_ENDPOINT!);

// Reuse the persistent profile's default context so cookies survive.
const context = browser.contexts()[0] ?? (await browser.newContext());
const page = await context.newPage();

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

// If the profile is still authenticated, this skips the login form.
if (await page.locator("form[action='/login']").count()) {
  await page.fill("#username", process.env.PORTAL_USER!);
  await page.fill("#password", process.env.PORTAL_PASS!);
  await page.click("button[type=submit]");
  await page.waitForURL("**/reports");
}

const rows = await page.$$eval("table.report tbody tr", (trs) =>
  trs.map((tr) =>
    Array.from(tr.querySelectorAll("td")).map((td) => td.textContent?.trim() ?? "")
  )
);

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

Two details matter more than the code. First, browser.contexts()[0] assumes the hosted session already has a profile attached; if you create a fresh context every run, you throw away the login. Second, closing the context without closing the browser keeps the session alive for the next task if your runtime supports that — check the documentation for how your session lifecycle is scoped.

Production criteria for this pattern:

  • Persistent profile with a defined TTL, so stale cookies get rotated.
  • Proxy with a stable region matching the account's normal login location.
  • Retry logic that distinguishes "session expired" from "site is down."

Example 2: Multi-step form submission with verification

Agents that submit forms — support tickets, expense reports, procurement requests — need to verify the submission landed, not just that the click fired. This is where browser use tools that only return a screenshot fall short.

The pattern is: fill, submit, wait for a confirmation signal, then read back the record ID. If the confirmation never appears, the task is not done, regardless of what the agent's model thinks.

await page.goto("https://ops.example.com/tickets/new");

await page.fill("#title", ticket.title);
await page.fill("#body", ticket.body);
await page.selectOption("#priority", ticket.priority);
await page.click("button[data-testid=submit]");

// Wait for a durable confirmation, not a toast that disappears.
const confirmation = page.locator("[data-testid=ticket-id]");
await confirmation.waitFor({ state: "visible", timeout: 30_000 });

const ticketId = (await confirmation.textContent())?.trim();
if (!ticketId) {
  throw new Error("Submission did not return a ticket ID");
}

The subtle production issue is idempotency. If the agent retries after a timeout, you can create duplicate tickets. The fix is to check for an existing record before submitting, or to use a client-generated idempotency key that the target system honors. Neither is a browser problem — but both are things a production browser use example has to address, because the browser is where the retry happens.

Production criteria for this pattern:

  • A durable confirmation selector, not a transient toast.
  • Idempotency handling before the submit click.
  • A timeout that fails the task rather than leaving it half-done.

Example 3: CI smoke checks against a real browser

Not every browser use production example involves an LLM. A large share of production browser workloads are deterministic: log in, click through a critical path, assert the page renders. These run in CI on every deploy.

This is where hosted Chromium earns its keep. CI runners are ephemeral, and installing a browser plus its dependencies on every job is slow and flaky. Connecting to a remote session over CDP removes that step entirely.

ConcernLocal browser in CIHosted Chromium over CDP
Install time per jobMinutes (browser + deps)None; connect to an endpoint
Session persistenceLost when the job endsProfiles survive across jobs
Debugging a failureArtifacts if you remembered to capture themLive viewer during the run
Scaling concurrent checksLimited by runner resourcesBounded by your session quota
Proxy / geo requirementsManual per-runner setupConfigurable at the session level
Cost modelRunner minutesPer browser-hour; see /pricing

The trade-off is real: a hosted session adds network latency between your test code and the browser. For a smoke check that waits on page loads anyway, that latency is noise. For a micro-benchmark that measures render timing to the millisecond, it is not — keep those local.

Example 4: Agent-driven research with a live viewer

The fourth pattern is the one that most needs a human in the loop. An agent researches a topic across several sites, and a person watches the session to catch it going off the rails.

This is where a live viewer changes the economics of debugging. Instead of reading a log after the fact, you watch the agent navigate in real time and intervene when it misreads a page. The remote control browser model — where a human and an agent share one session — is the practical version of this.

The production requirements are different from the first three examples:

  • Session sharing. The viewer and the agent must attach to the same session, not two copies.
  • Latency budget. A viewer that lags by seconds is useless for intervention.
  • Access control. Whoever can watch the session can see the credentials in it.

If you are running this pattern, treat the viewer as a privileged surface. Session isolation and per-session access tokens are not optional.

Choosing browser use models and tools for each pattern

The "browser use models" question — which LLM drives the agent — matters less than the runtime, but it is not irrelevant. A few practical notes:

  • Deterministic tasks (Example 3) need no model at all. Adding one makes the check slower and less reliable.
  • Structured extraction (Example 1) works well with a smaller, cheaper model, because the page structure constrains the output.
  • Open-ended navigation (Example 4) benefits from a stronger model, because the agent has to recover from unexpected page states.

On the tools side, the split is between frameworks that drive the browser (Playwright, Puppeteer, Selenium) and runtimes that host it. Remote Browser sits in the second category: it provides the hosted Chromium session, CDP endpoint, persistent profiles, and live viewer, and your existing Playwright or Puppeteer code connects to it unchanged. If you are coming from a local setup, Remote browser online covers the migration path.

What to check before you ship

Before any of these examples goes to production, verify:

  1. The session is addressable. You can reconnect to it from a different process.
  2. The profile has a TTL. Stale auth state is a silent failure source.
  3. Failures are distinguishable. "Session expired," "site down," and "selector changed" need different responses.
  4. You can see what happened. A live viewer or a recording, not just logs.
  5. Cost is bounded. Per-browser-hour pricing means a stuck session is a running bill. Set session timeouts.

That last point is worth repeating. An agent that hangs on a page it cannot parse will hold a browser session open until something kills it. Session timeouts and usage controls are the difference between a predictable bill and a surprise. Current rates and limits are on the pricing page.

The common thread

Every browser use production example above shares one requirement: the browser has to outlive the process that started it. Local Chrome cannot do that. A hosted Chromium session reachable over CDP can, and it lets you keep the Playwright code you already wrote.

Start with the deterministic example — a CI smoke check — because it has the fewest moving parts and will surface any connection issues immediately. Then move to the login-gated extraction, which is where persistent profiles and proxies start to matter. The agent-driven patterns come last, once you trust the runtime underneath them.