Documentation

Everything you need to ship.

Quickstarts, API reference, operational guides, and the migration playbooks other teams have already written. All in one place.

Sections

Start wherever you are.

Getting started

Quickstart

From API key to first session in five minutes.

Guides

Sessions

Lifecycle, regions, IP pools, and cleanup.

Guides

Vault

Store, scope, and rotate credentials safely.

Guides

Replay

Recording, deterministic rerun, export.

Reference

REST API

Every endpoint, every field, every error.

Reference

Python SDK

Types, async patterns, and examples.

Reference

TypeScript SDK

Fully typed, Promise-based API surface.

Operations

Observability

OpenTelemetry, Datadog, and Sentry setup.

Quickstart

Every BrowserAnvil account starts with 60 free session-minutes a month. Grab an API key from your dashboard, install the SDK, and you are ready to spin up your first session.

Install an SDK

pip install browseranvil          # Python
npm install @browseranvil/sdk     # Node / TypeScript

Authentication

Every request is authenticated with a bearer token. Keep your ba_live_* keys server-side. Use ba_test_* keys in CI.

curl https://api.browseranvil.com/v1/sessions \
  -H "Authorization: Bearer ba_live_..." \
  -H "Content-Type: application/json" \
  -d '{"region":"us-west","record":true}'

Create a session

A session is a dedicated Chromium instance in a Firecracker microVM. The response gives you a CDP WebSocket URL that lives as long as the session does.

from browseranvil import Runtime

runtime = Runtime(api_key="ba_live_...")

session = await runtime.create_session(
    region="us-west",
    ip_pool="residential",
    credentials=["acme-okta"],
    record=True,
    idle_timeout_seconds=120,
)

print(session.cdp_url)

Connect your agent

The SDK exposes a Playwright-compatible browser object. Or drop down to raw CDP.

from playwright.async_api import async_playwright

async with async_playwright() as p:
    browser = await p.chromium.connect_over_cdp(session.cdp_url)
    page = await browser.new_page()
    await page.goto("https://example.com")

Session lifecycle

Sessions are live from created through ready, active, ending, and closed. Subscribe to lifecycle events over webhooks or the SDK's event stream.

Credential vault

Store credentials once, reference by handle forever. Vaulted values are injected at the keystroke layer and never appear in prompts, logs, or replays.

runtime.vault.put(
    handle="acme-okta",
    values={
        "username": "agent@example.com",
        "password": "...",
        "totp_seed": "JBSWY3DP...",
    },
)

Replay

Every session recorded produces a replay_id. Open it in the dashboard, export it over the API, or pipe it into deterministic rerun mode.

Human handoff

Register a webhook endpoint and a pause condition. When the agent trips the condition, we fire the webhook with a live-session URL.

Observability

Metrics flow out over OpenTelemetry. Traces stitch into your existing APM. Logs can be mirrored to S3, Datadog, or Splunk.

Rate limits

Team plan: 500 concurrent sessions, 60 new sessions per minute. Enterprise: negotiated.

Error codes

  • session_start_timeout — Chromium did not come up in time
  • ip_pool_exhausted — requested pool has no clean addresses
  • bot_detected — page served a Cloudflare/Akamai challenge
  • credential_not_found — vault handle does not exist or is out of scope
Popular guides

Short reads for common questions.

Migrating from self-hosted Chromium

The minimal diff to route your existing Playwright code through BrowserAnvil.

Handling Cloudflare challenges

Residential pool + human handoff. When to use which.

Concurrency and back-pressure

Safe parallelism patterns for scheduling thousands of sessions.

Cost optimization

Where your session-minutes go, and what to do about it.

Redacting PII in replays

Regex rules and selector-based masking.

Human-in-the-loop patterns

Design patterns for graceful agent → operator handoff.

SDK reference

Typed, async, minimal.

Python

from browseranvil import Runtime

rt = Runtime(api_key="ba_live_...")

async with rt.session() as s:
    ...

TypeScript

import { Runtime } from "@browseranvil/sdk";

const rt = new Runtime({ apiKey: "ba_live_..." });

await rt.session(async (s) => {
  /* ... */
});
Recipes

Copy-pasteable patterns.

Login with TOTP

Vaulted password + TOTP seed in 15 lines.

Parallel scraping

10 residential sessions, typed results, rate-limited.

Session reuse

Keep-alive patterns for long-running agents.

Replay debugging

Deterministic rerun from a saved session.

Webhook handoff

Pause an agent and resume from a human action.

OpenTelemetry wiring

Stitch our spans into your existing traces.

Changelog

What shipped this quarter.

April

Mobile IP pool (US, UK, JP)

True carrier-grade NAT IPs, billed per GB.

March

Deterministic replay v2

Pinned clock, random seed, and network responses for exact reruns.

February

BYO-KMS general availability

Wrap replays and vault with your own AWS or GCP KMS key.

January

LangGraph adapter

Stateful graphs with session lifecycle as a first-class node.

Community.

Discord

A few hundred agent builders, our engineers, and weekly show-and-tell.

GitHub discussions

Longer-form questions and architecture debates.

Office hours

Open Zoom every Thursday. Hard problems get the front of the line.

Docs FAQ

Where is the OpenAPI spec?

Published at /openapi.yaml. We use it to generate the SDKs and the reference docs, so it is always current.

Can I suggest an edit to the docs?

Yes — every page has an "Edit on GitHub" link in production. We merge typo fixes within a day.

Is there a postman collection?

Yes. Import it from the reference page, or regenerate from the OpenAPI spec.

Start reading. Start shipping.

The quickstart is short. The docs are complete.

Get an API key Ask a human