BLOG
Use Cloud Browser: A Production Guide for AI Agents
Learn how to use cloud browser sessions for AI agents: CDP wiring, browser-hours, Stagehand and browser-use, and production checks before you ship.
# Use Cloud Browser: A Production Guide for AI Agents
To use cloud browser infrastructure, you create a hosted Chromium session over an API, connect to it with a CDP endpoint, and drive it with Playwright, Puppeteer, Selenium, Stagehand, or a browser-use agent. The browser runs on someone else's servers, so your agent process stays small and stateless. This guide covers the wiring, the cost model (billable browser-hours), and the production criteria that separate a demo from a runtime you can leave running overnight.
The search intent behind "use cloud browser" is usually practical: you have an agent that works locally and you want it to keep working when it runs on a server, in a queue worker, or across many parallel tasks. The sections below answer that directly, then cover the trade-offs you will hit at scale.
What a cloud browser actually is
A cloud browser is a real Chromium instance running on remote infrastructure, exposed through a control protocol. You do not install Chrome on your machine or container. You request a session, receive a connection URL (typically a CDP WebSocket endpoint), and attach your automation library to it.
Three properties matter for agents:
- Real browser, not a renderer. It executes JavaScript, holds cookies, and behaves like the browser a human would use. Headless-only HTML fetchers fail on most interactive tasks.
- Remote control surface. CDP is the same protocol Chrome exposes locally, so Playwright's
connectOverCDP, Puppeteer'sbrowserWSEndpoint, and Selenium's remote driver all work without rewriting your automation logic. - Session lifecycle. Sessions are created, used, and stopped. You pay for the time between start and stop, which is why browser-hours are the unit of cost.
Remote Browser provides hosted Chromium sessions with CDP access, a live viewer, persistent profiles, configurable proxy and browser settings, and session isolation. The details of the runtime layer are covered in Remote browsers for AI agents.
Why teams move off local Chrome
Local Chrome is fine for development. It breaks down in production for predictable reasons:
| Concern | Local Chrome | Cloud browser |
|---|---|---|
| Scaling | One browser per machine; memory-bound | Request sessions per task, isolate by design |
| State | Tied to a disk profile; lost on redeploy | Persistent profiles you can reuse across runs |
| Debugging | Attach a debugger to a headless process | Live viewer plus CDP access from anywhere |
| Network | Your IP; blocks and rate limits hit you | Configurable proxy settings per session |
| Ops | Patch Chrome, manage drivers, clean zombies | Provider handles the browser image |
| Cost visibility | Server cost, opaque | Metered in browser-hours |
The trade-off is real: you give up direct filesystem access to the browser and depend on a network hop to the control endpoint. For agent workloads that hop is usually small relative to page load times, but it matters for high-frequency, low-latency interactions. Measure it before committing.
Connecting to a cloud browser over CDP
The standard path is CDP. Playwright's `connectOverCDP` attaches to an existing browser instead of launching one. The same pattern works for Puppeteer via browserWSEndpoint and for Selenium through a remote WebDriver URL.
A minimal TypeScript example:
import { chromium, Browser, Page } from "playwright";
type Session = { cdpUrl: string; sessionId: string };
async function openSession(): Promise<Session> {
// Replace with your provider's session-creation call.
// Remote Browser returns a CDP WebSocket URL per session.
const res = await fetch(`${process.env.BROWSER_API}/sessions`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BROWSER_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
// Optional: reuse a saved profile for logged-in flows.
profileId: process.env.PROFILE_ID,
// Optional: route traffic through a configured proxy.
proxy: process.env.PROXY_ID,
}),
});
if (!res.ok) throw new Error(`session create failed: ${res.status}`);
const data = await res.json();
return { cdpUrl: data.cdpUrl, sessionId: data.id };
}
async function runTask(url: string) {
const { cdpUrl, sessionId } = await openSession();
let browser: Browser | undefined;
try {
browser = await chromium.connectOverCDP(cdpUrl);
const context = browser.contexts()[0] ?? (await browser.newContext());
const page: Page = context.pages()[0] ?? (await context.newPage());
await page.goto(url, { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: /sign in/i }).click();
await page.getByLabel("Email").fill("agent@example.com");
await page.getByRole("button", { name: /continue/i }).click();
// Wait on a real signal, not a fixed sleep.
await page.waitForResponse((r) => r.url().includes("/api/session") && r.ok());
return await page.title();
} finally {
// Always close the remote session; open sessions burn browser-hours.
await browser?.close();
await fetch(`${process.env.BROWSER_API}/sessions/${sessionId}`, {
method: "DELETE",
headers: { Authorization: `Bearer ${process.env.BROWSER_API_KEY}` },
});
}
}Two details in that snippet matter more than they look. First, browser.close() on a CDP connection detaches the client; the remote session may keep running unless you also stop it through the API. Second, the finally block is where cost leaks happen. An agent that throws before cleanup leaves a session open, and open sessions are billable.
If you are wiring this for the first time, the connection mechanics are covered in more depth in Remote browser online and the documentation.
Browser-hours: the cost model you need to understand
Cloud browsers are metered by billable browser-hours: the wall-clock time a session exists, usually rounded or billed per second with a minimum. This is different from compute billing in one important way — the meter runs whether or not your agent is doing anything.
That changes how you design agents:
- Stop sessions aggressively. Close on task completion, not on process exit. A session idle for ten minutes waiting on a queue is ten minutes of browser-hours.
- Do not pool browsers by default. A warm pool trades cost for latency. Only keep one if your task volume justifies it.
- Separate long-lived state from long-lived sessions. If you need logged-in state across runs, use a persistent profile and start a fresh session per task rather than holding one browser open for hours.
- Measure per-task duration. Instrument start-to-stop time per task. The distribution, not the average, tells you where the cost is.
Pricing varies by provider and plan. Remote Browser's current rates and any included usage are on the pricing page; check there rather than relying on third-party comparisons, which go stale quickly. For a deeper look at how metering works, see Per browser-hour pricing.
Cloud browser vs self-hosted browserless
The main alternative to a managed cloud browser is self-hosting an open-source runtime such as Browserless or Steel on your own infrastructure. Both are legitimate choices.
| Criterion | Managed cloud browser | Self-hosted (Browserless, Steel) |
|---|---|---|
| Time to first session | Minutes; API key and a request | Hours to days; containers, scaling, TLS |
| Browser image upkeep | Provider | You |
| Scaling model | Request sessions; provider handles capacity | You size nodes and autoscaling |
| Cost shape | Per browser-hour | Fixed infra plus engineering time |
| Debugging | Live viewer, session recordings | Your own tooling |
| Network egress | Provider's IPs, configurable proxies | Your IPs; you manage proxies |
| Data residency | Provider regions | Fully under your control |
Self-hosting wins when you have strict data residency requirements, existing Kubernetes capacity, or very high sustained utilization where per-hour metering is more expensive than owned nodes. Managed wins when you want to ship, when load is spiky, and when you would rather not own a browser fleet. The browser-as-a-service vs self-hosted Playwright comparison goes deeper on the break-even math.
A middle path is common: self-host for internal, high-volume, low-sensitivity tasks and use a managed runtime for anything that needs stealth settings, configurable proxy routing, or isolation guarantees you do not want to build.
Framework compatibility: Stagehand, browser-use, and raw CDP
Most agent frameworks assume they control a browser. Cloud browsers work with them as long as the framework can accept an existing CDP endpoint.
- Stagehand and similar AI-native automation layers wrap Playwright. Point the underlying Playwright connection at the CDP URL and the framework's
act,extract, andobserveprimitives run against the hosted browser unchanged. - browser-use and other agent loops that drive Playwright or CDP directly can be configured with a remote browser URL. The agent's planning loop is unaffected; only the connection target changes.
- Raw CDP clients (Puppeteer,
chrome-remote-interface, custom WebSocket code) work if the provider exposes a standard CDP endpoint. Verify that the endpoint supports the domains your client needs — some providers restrict certain CDP domains for security.
The practical check: run your existing local test suite against the cloud endpoint before changing any agent code. If the suite passes, the runtime is compatible. If it fails, the failure is usually in one of three places — a CDP domain that is blocked, a proxy that breaks WebSocket upgrades, or a profile that lacks the cookies your test assumed.
Production criteria before you commit
Use this checklist when evaluating any cloud browser, including Remote Browser:
- CDP fidelity. Does
connectOverCDPwork with your Playwright version, and are the CDP domains you need enabled? - Session lifecycle API. Can you stop a session explicitly, and does the API report session state so you can reconcile orphans?
- Persistent profiles. Can you save and reuse cookies and local storage across sessions without keeping a browser open?
- Proxy and network controls. Are proxy settings configurable per session, and can you verify the egress IP from inside the browser?
- Live debugging. Is there a viewer or a way to attach a second CDP client while a session runs? Debugging blind is expensive.
- Isolation. Are sessions isolated from each other at the process or container level?
- Usage controls. Are there spend limits or concurrency caps you can set to prevent a runaway agent from burning budget?
- Observability. Do you get session logs, durations, and error surfaces you can feed into your own monitoring?
If a provider cannot answer 1, 2, and 7 clearly, it is not ready for unattended agents. The rest are quality-of-life differences that matter more as volume grows.
Common failure modes and fixes
Sessions left open after crashes. Wrap session creation in a try/finally and add a reaper job that stops sessions older than a threshold. Track session IDs in your own database so you can reconcile against the provider's list.
Timeouts that are too short for real pages. Cloud browsers add a network hop. A 5-second navigation timeout that worked locally may fail remotely on heavy pages. Raise timeouts and wait on specific signals (waitForResponse, waitForSelector) rather than fixed sleeps.
Proxy misconfiguration. If the proxy requires authentication, confirm the provider injects credentials correctly and that WebSocket upgrades to the CDP endpoint are not routed through the proxy. Test with a simple page.goto("https://ifconfig.me") and read the body.
Profile drift. Persistent profiles accumulate state. A profile that worked last month may now hold expired tokens or stale service workers. Version your profiles and rotate them on a schedule.
Concurrency surprises. Providers cap concurrent sessions per plan. If your queue worker spawns 50 tasks and the cap is lower, requests will fail or queue. Read the limits on pricing and build backpressure into the worker.
When a cloud browser is the wrong choice
Be honest about the cases where it does not fit:
- Sub-100ms interaction loops. The network hop dominates. If your agent needs to react to DOM changes in milliseconds, run locally or co-locate.
- Full control over the browser binary. If you need a patched Chromium build with specific flags, self-hosting is simpler than negotiating custom images.
- Strict data residency with no provider region. If the page content cannot leave a jurisdiction the provider does not serve, self-host.
- Extremely high sustained utilization. At very high duty cycles, owned infrastructure can be cheaper. Model it with your actual session durations.
For everything else — spiky agent workloads, tasks that need stealth settings or configurable proxy routing, teams that would rather ship than operate a browser fleet — a managed cloud browser is the shorter path. The remote web browser and remote control browser guides cover adjacent patterns if your use case is closer to remote debugging than agent automation.
Getting started
The fastest path is to create a session, connect with connectOverCDP, run one task, and stop the session. Then instrument duration and cost per task before you scale. Start with the documentation for the session API and CDP endpoint format, check pricing for current browser-hour rates and concurrency limits, and read Remote browsers for AI agents for the runtime model behind the API.
The core discipline is the same regardless of provider: treat browser sessions as metered, short-lived resources, clean them up in finally blocks, and measure before you optimize.