Skip to main content
The browser primitive gives your agents a real, cloud-hosted browser they can drive step by step (navigate, act, extract, observe, screenshot), reusable saved logins, and two high-level autonomous actions — signup and login — that handle account creation and re-authentication end to end. Sessions are per-user, scoped to an allowlist of domains, metered per action, and watchable live from the dashboard. It is a per-tenant-user primitive: every session belongs to a tenant_user and is gated by that user’s Account Kit (browser must be enabled). Enable or disable it per kit, and optionally require human approval for autonomous signup.

CLI First

How it works

CapabilityWhat it doesCost
session createOpen a live cloud browser scoped to allowed_domains0 credits (time floor at close)
navigateGo to a URL (allowlist + SSRF enforced)10 credits
actNatural-language action (click/fill/scroll); returns the page url after the action10 credits
extractPull structured data (visible text) from the page (read-only)10 credits
linksRead anchor hrefs + the current URL via a DOM read (read-only)10 credits
observeList candidate elements/actions (read-only)10 credits
screenshotCapture the page (short-lived signed URL)10 credits
signupAutonomous account creation + credential vaulting40 credits
loginAutonomous re-authentication from the vault30 credits
Sessions have a hard TTL (default 15 min, max 30) and a per-session credit ceiling of 400. Always close sessions when done — an idle session still bills a vendor time floor at close, based on actual elapsed time: 10 credits (≤5 min), 20 (≤15 min), 30 (≤30 min). extract reasons over the page’s accessibility tree — the same semantic view a screen reader sees. That tree carries roles and visible text, but not raw DOM attributes like a link’s href or window.location. So asking extract for “the LinkedIn URL” or “the current page URL” returns visible text (or a fabricated-looking guess), never the real target. Two purpose-built reads cover URLs:

links — link targets

links(session_id, { contains?, limit? }) does a direct DOM read and returns { url, links: [{ text, href }] }. This is the reliable way to capture real hrefs (LinkedIn / GitHub / profile links). Filter with contains (matches href or text) and cap with limit (default 300, max 1000).

act / navigate — the current URL

act and navigate both return the page url after the step runs — the way to learn where a click landed, including SPA route changes that put an opaque token in the path (e.g. /applicants/<token>), which no page-content read can reconstruct.
links is read-only and, on a logged-in (context-backed) saved-login session, is capability-gated (--allow-extract) and output-redacted exactly like extract.

Autonomous signup & login

This is the core workflow: an agent that needs an account on a third-party service can create one and reuse it later, without ever handling the password itself.
1

Signup

signup opens a scoped, write-enabled session, fills the registration form with the user’s identity (email + name) and a strong generated password, submits, and stores { email, password } in the user’s encrypted Vault under the key login:<service>. The password is never returned to the agent or sent to the model.
2

Approval (optional)

Because signup creates a real account under the user’s identity, it is approval-gated by default. When gated, the call returns status: "pending_approval" (HTTP 202) and runs only after a human approves it. Toggle this per Account Kit.
3

Login later

When a session expires and the agent needs the service again, login reads the stored credential from the Vault and signs back in — again without the password crossing the agent/LLM boundary.
Secrets never reach the model. The password is filled via Stagehand variable substitution (%password% is a placeholder; the real value is substituted locally and is never logged or sent to the LLM). Signup uses the tenant user’s profile email as the account email — point it at a provisioned inbox so verification emails can be received. Set it with the profile primitive (client.forUser(id).profile.setEmail(...), or profile.set_email from the agent toolset).If you already have a working email/password for the service, store it with saveCredential (POST .../browser/credentials) instead of typing it via act; a later login then pulls it from the Vault server-side.

Saved logins (Tier B)

For services where a human must log in once (SSO, 2FA, CAPTCHAs), open a human_login session, complete the login in the dashboard live view, then save_login to persist it as a reusable, encrypted vendor-side context. naive stores only an opaque pointer — never the cookies or credentials. Later sessions reopen already-logged-in by name (--context-name), gated by a human-created grant (default-deny; an agent can use a saved login but never create the grant or revoke it).

Live view

From the dashboard, open a user’s Browser tab to see their sessions. For an active session you can watch it stream in real time and click Take control to interact directly — this is how a human completes the one-time login for a saved-login context, or steps in to solve a CAPTCHA.

Safety

  • Domain allowlist (default-deny). Every session must pass allowed_domains; pass ['*'] to browse unrestricted (not recommended — no DNS-rebinding protection). An SSRF denylist (private/loopback/metadata hosts, non-http(s) schemes) always applies.
  • Writes are gated. Destructive/submit actions are rejected unless the session was opened with allow_writes.
  • No secrets in instructions. Never put passwords in an act/extract instruction — the autonomous signup/login flow handles credentials server-side.
  • Read-restricted saved logins. On a logged-in (context-backed) session, extract/observe/screenshot are disabled unless a human opened it with allow_extract, and their output is redacted.