← Blog

BLOG

Stagehand Browser-Use: Connect Stagehand to Hosted Chromium

Stagehand browser-use integration guide: connect Stagehand agents to hosted Chromium over CDP, with production criteria, trade-offs, and setup code.

October 18, 20269 min readRemote Browser

# Stagehand Browser-Use: Connect Stagehand to Hosted Chromium

Stagehand browser-use is the pattern of running Stagehand's AI-driven browser actions against a remote Chromium instance instead of a local one. Stagehand wraps Playwright and adds natural-language actions, extraction, and observation on top of deterministic browser control. Browser-use is the broader category of AI agents that drive a browser to complete tasks. Combining them means your Stagehand agent connects to a hosted browser over the Chrome DevTools Protocol (CDP), runs in an isolated session, and never depends on a developer laptop staying open.

This guide covers how the integration works, what to check before you ship it, and where hosted Chromium changes the failure modes you will hit in production.

What Stagehand actually is, and why the runtime matters

Stagehand is an open-source TypeScript framework from Browserbase that sits on Playwright. You get three primitives: act for a single natural-language action, extract for structured data pulled from a page, and observe for discovering candidate actions on a page. Underneath, it is still Playwright driving a Chromium instance. That matters because every Stagehand call ultimately becomes CDP traffic to a browser process.

The framework does not ship a browser. It launches or connects to one. By default, that is a local Chromium binary on the machine running your script. In development this is fine. In production it is the first thing that breaks: headless Chrome on a CI runner has no persistent profile, no stable IP, no live view for debugging, and no isolation between concurrent jobs.

A hosted runtime fixes the browser side of the equation. Remote Browser provides Chromium sessions reachable over CDP, with persistent profiles, configurable browser settings, session isolation, and a live viewer. Stagehand does not need to know the difference — it connects to a WebSocket endpoint and proceeds as if the browser were local.

How the Stagehand browser-use integration works

The connection path is short:

  1. Your code requests a browser session from the runtime API.
  2. The runtime returns a CDP WebSocket endpoint for that session.
  3. Stagehand (via Playwright's connectOverCDP) attaches to that endpoint.
  4. Stagehand runs act, extract, and observe calls against the remote page.
  5. You close the session when the task finishes.

Because Stagehand is Playwright-based, the connection uses Playwright's standard CDP attach mechanism. The Playwright `connectOverCDP` documentation is the authoritative reference for the connection semantics, including how contexts and pages are surfaced after attach.

Connecting Stagehand to a hosted session

The exact Stagehand constructor varies by version, but the shape is consistent: you pass a CDP URL instead of letting Stagehand launch a local browser.

import { Stagehand } from "@browserbasehq/stagehand";
import { chromium } from "playwright-core";

// 1. Create a hosted session via the runtime API.
//    Endpoint and auth header names are documented at /documentation.
const sessionRes = await fetch(`${process.env.RB_API_URL}/sessions`, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.RB_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    // Keep the session alive long enough for the agent loop.
    // Actual limits are documented at /pricing.
    profileId: process.env.RB_PROFILE_ID, // optional persistent profile
  }),
});

if (!sessionRes.ok) {
  throw new Error(`Session create failed: ${sessionRes.status}`);
}

const { cdpUrl, sessionId } = await sessionRes.json();

// 2. Attach Playwright to the remote Chromium over CDP.
const browser = await chromium.connectOverCDP(cdpUrl);
const context = browser.contexts()[0] ?? (await browser.newContext());
const page = context.pages()[0] ?? (await context.newPage());

// 3. Hand the live page to Stagehand.
const stagehand = new Stagehand({
  env: "LOCAL",
  // Stagehand accepts an existing page/browser in recent versions;
  // check the version you pin for the exact option name.
  browserbaseSessionID: undefined,
  logger: (line) => console.log(line),
});

await stagehand.init({ page });

// 4. Run the agent loop.
await stagehand.page.goto("https://example.com/dashboard");
await stagehand.act({ action: "open the billing settings page" });

const invoices = await stagehand.extract({
  instruction: "list the three most recent invoices with amount and date",
  schema: {
    type: "object",
    properties: {
      invoices: {
        type: "array",
        items: {
          type: "object",
          properties: {
            amount: { type: "string" },
            date: { type: "string" },
          },
        },
      },
    },
  },
});

console.log(invoices);

// 5. Tear down cleanly.
await stagehand.close();
await browser.close();
await fetch(`${process.env.RB_API_URL}/sessions/${sessionId}`, {
  method: "DELETE",
  headers: { "Authorization": `Bearer ${process.env.RB_API_KEY}` },
});

Two details are worth calling out. First, connectOverCDP returns a browser whose existing contexts and pages are already populated — you do not get a blank slate, so check contexts()[0] before creating a new context. Second, always close the remote session explicitly. A dropped WebSocket does not necessarily terminate the browser process, and orphaned sessions are the most common source of surprise usage.

If you are wiring this up for the first time, the Remote Browser documentation covers endpoint formats, auth headers, and session lifecycle. For a broader architectural view of why agents need a hosted runtime at all, see Remote browsers for AI agents.

Stagehand on hosted Chromium vs. local Chromium

The differences show up in operations, not in the Stagehand API. Here is the practical comparison.

CriterionLocal Chromium (default Stagehand)Hosted Chromium (Remote Browser)
Session persistenceLost when the process exitsPersistent profiles survive across sessions
ConcurrencyBounded by the machine's RAM and CPUBounded by your plan's concurrency; see /pricing
IP and networkYour office or CI runner's IPConfigurable proxy settings per session
DebuggingScreenshots and logs after the factLive viewer attached to the running session
IsolationShared filesystem and profile unless you sandboxOne browser per session, isolated by default
Cold startFast on a warm machine, slow on cold CIRemote session creation; latency depends on region
Failure recoveryManual restart of the scriptNew session, same profile, resume the task
Cost modelCompute you already pay forMetered per browser-hour; see /pricing

The trade-off is real. Local Chromium has zero network latency between your code and the browser, which matters for tight action loops. Hosted Chromium adds a network hop per CDP message. In practice, Stagehand's LLM calls dominate latency by a wide margin, so the CDP hop is rarely the bottleneck — but if you are running thousands of deterministic act calls with a fast local model, measure before you assume.

Production criteria before you commit

Before you move a Stagehand workload to a hosted runtime, check these five things.

1. Session lifecycle and timeouts. Decide how long a session should live and what happens when the agent stalls. A Stagehand loop that retries a failing act call will burn browser-hours. Set a wall-clock budget per task and close the session when it is exceeded. Usage controls on the runtime side are a backstop, not a substitute for task-level timeouts.

2. Profile strategy. Stagehand tasks that require login — dashboards, internal tools, SaaS accounts — need persistent profiles. A profile stores cookies and local storage so the agent does not re-authenticate on every run. Decide whether profiles are shared across tasks (convenient, riskier) or scoped per tenant (safer, more setup). The runtime's profile API is covered in /documentation.

3. Network identity. Some sites behave differently based on IP reputation. If your Stagehand workload targets sites with bot mitigation, configure proxy settings per session rather than relying on a single egress IP. Be careful here: "stealth" is a spectrum, and no runtime guarantees you will pass every challenge. Treat proxy configuration as a lever, not a solution.

4. Observability. When a Stagehand extract returns the wrong shape, you need to see what the page actually looked like at that moment. A live viewer lets you watch the session in real time and inspect the DOM after a failure. Pair it with structured logging from Stagehand's logger callback so you can correlate LLM decisions with page state.

5. Concurrency and cost. Stagehand agents are slow relative to scripted Playwright because each step involves a model call. That means fewer concurrent sessions than you might expect for the same throughput. Model your expected browser-hours before you pick a plan; the pricing page has the current rates, and the arithmetic is straightforward: sessions × average duration × runs per day.

Where Stagehand fits against browser-use and other frameworks

Stagehand is not the only way to build a browser agent, and the choice affects how you connect to a runtime.

  • Stagehand gives you Playwright plus LLM primitives. You keep deterministic control and add AI where it helps. Best when you want a hybrid: scripted steps for known flows, act for the messy parts.
  • browser-use (the Python framework) is a full agent loop with its own planning layer. It also connects over CDP, so the same hosted runtime works. If you are comparing the two, the connection mechanics are nearly identical; the difference is who owns the planning.
  • Raw Playwright or Puppeteer is the right choice when the flow is fully deterministic and you only need a remote browser for isolation, profiles, or scale.

For teams evaluating the runtime layer separately from the framework, Remote browser online and Remote web browser cover the hosted-browser side without assuming a specific agent framework. And if you are driving sessions interactively during development, Remote control browser explains the live-control model.

One more consideration: Stagehand's observe primitive is useful for adapting to UI changes, but it costs a model call per invocation. In production, cache the action candidates it returns for a given page state and only re-observe when an act fails. This is the single biggest cost lever for Stagehand workloads.

Common failure modes and how to handle them

The session dies mid-task. Usually a timeout or a network drop. Catch the error, create a new session with the same profile, and resume from the last known good URL rather than restarting the whole task. Stagehand does not checkpoint for you.

`act` succeeds but the page did not change. Stagehand reports success based on the model's judgment, not on DOM verification. Add an assertion after each critical act — check for a specific selector or URL — and treat a mismatch as a failure. This is the difference between a demo and a production agent.

Extraction returns hallucinated fields. Constrain the schema tightly and validate the output against it. If a field is optional in reality, mark it optional in the schema rather than letting the model invent a value.

Concurrent sessions interfere. This should not happen with proper session isolation, but it will if you reuse a single profile across parallel tasks that mutate the same account. Scope profiles per concurrent task or serialize access.

Costs climb unexpectedly. Almost always orphaned sessions or retry loops. Log session creation and deletion with timestamps, and alert on sessions that outlive their expected duration.

Bottom line

Stagehand browser-use works because Stagehand is Playwright underneath, and Playwright attaches to remote Chromium over CDP with one call. The integration itself is a few lines. The work is in the operational layer: session lifecycle, profiles, network configuration, observability, and cost control. Get those right and Stagehand becomes a reliable production agent framework rather than a local demo. Start with the documentation for the connection details, and check /pricing before you size your concurrency.