Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@browserview/typescript

TypeScript client for the browserview.io API. browserview.io runs disposable cloud Chromium sessions that humans can watch and control in a live viewer while agents drive the same browser over the Chrome DevTools Protocol.

Zero runtime dependencies. Requires Node 18+ (any runtime with fetch works).

Install

npm install @browserview/typescript

Configuration

Setting Option Env var Default
API key apiKey BROWSERVIEW_API_KEY — (required)
Base URL baseUrl BROWSERVIEW_BASE_URL https://sessions.browserview.io
Retries maxRetries 3 (0 disables)
Timeout timeoutMs 60000

Explicit constructor options take precedence over environment variables.

Two kinds of API keys work:

  • Tenant keys minted by the browserview.io console, format bv_live_ + 40 hex chars.
  • Shard admin keys, which are arbitrary strings (often bare hex). Admin keys unlock capacity(), the owner option on create() (create a session on behalf of a tenant), and cross-tenant access.

The SDK sends the key as Authorization: Bearer <key>; the API equally accepts x-api-key: <key>.

Quickstart

import { BrowserView } from "@browserview/typescript";

const bv = new BrowserView(); // reads BROWSERVIEW_API_KEY
// or: new BrowserView({ apiKey: "...", baseUrl: "https://sessions.browserview.io" })

const session = await bv.sessions.create({
  startUrl: "https://example.com", // server default: "about:blank"
  width: 1280,                     // server default (320–3840)
  height: 800,                     // server default (240–2160)
});

console.log(session.viewer_url); // live viewer, control access
console.log(session.watch_url);  // live viewer, view-only

// ...when you're done:
await bv.sessions.destroy(session.id);

create() blocks until the browser is ready by default (server-side wait: true, typically ~5s). Pass wait: false to return immediately; the SDK only sends fields you set. With an admin key, owner: "<user id>" creates the session on behalf of a tenant (the server ignores owner for tenant keys).

Other operations:

const sessions = await bv.sessions.list();       // no URLs/tokens in list responses
const fresh = await bv.sessions.get(session.id); // fresh URLs/tokens + restarts/degraded
const token = await bv.sessions.mintToken(session.id, {
  scope: "view",    // "view" | "control" | "cdp"
  ttlSeconds: 3600, // 1..604800 (7 days); default 3600
});

get() additionally reports session health: restarts (number of browser restarts, or null when the in-container status server is unreachable) and degraded (true once the browser has restarted). All session objects include mem_limit_bytes, the container memory limit.

The server returns viewer_url, watch_url, and cdp_url as relative paths; the SDK absolutizes them against your base URL before you see them.

Drive the session with Playwright

Connect an agent to the same browser a human is watching in the viewer:

import { chromium } from "playwright";

const session = await bv.sessions.create({ startUrl: "https://example.com" });

const browser = await chromium.connectOverCDP(session.cdp_url, {
  headers: { "x-session-token": session.cdp_token },
});

const page = browser.contexts()[0].pages()[0];
await page.goto("https://news.ycombinator.com");

The token can also be passed as ?token= on the CDP URL. Puppeteer's puppeteer.connect({ browserURL }) works the same way.

Session replay

Create the session with record: true and BrowserView captures everything server-side — a video of the display plus structured streams of actions, console output, network requests, and errors:

const session = await bv.sessions.create({
  startUrl: "https://example.com",
  record: true,
});

// ... drive the session ...
await bv.sessions.destroy(session.id);

// The replay is ready seconds after the session ends.
const replay = await bv.sessions.waitForReplay(session.id); // polls up to 2 min
console.log(replay.video?.url);          // seekable WebM
console.log(replay.pages);               // main-frame navigation timeline
console.log(replay.events?.console?.url); // JSONL: {"ts": ..., "level": ..., ...}

sessions.replay(id) fetches the manifest without polling: it returns { status: "recording" } while the session is alive and throws a 404 BrowserViewError while the recording finalizes. Every event line carries an absolute epoch-ms ts; align it with the video via (ts - replay.video.start_time_ms) / 1000 seconds. Artifact URLs expire at urls_expire_at_ms — call replay() again for fresh ones.

Errors and retries

Failed calls throw BrowserViewError with status, message, and retryAfter (seconds, parsed from the Retry-After header on any status). status is 0 when no HTTP response was received (e.g. timeout).

The client retries automatically before throwing:

  • 429 (rate/capacity limits — creates send Retry-After: 30) and 503 (auth backend temporarily down — Retry-After: 10) are retried for every method; the server does not commit a session create before returning these.
  • Network errors and timeouts are retried for idempotent GET/DELETE only.
  • Waits honor Retry-After (a single wait is capped at 30s), otherwise back off 1s, 2s, 4s. Default 3 retries; configure with maxRetries (0 disables).
  • Each attempt is aborted after timeoutMs (default 60s, sized for create-with-wait).

Other statuses you may see: 401 invalid/missing key (repeated failures escalate to 429 per IP), 403 admin-only endpoint with a tenant key, 404 unknown or un-owned session (tenants never get 403 for foreign sessions), 502 session create/backend failure.

import { BrowserViewError } from "@browserview/typescript";

try {
  await bv.sessions.get("nope");
} catch (err) {
  if (err instanceof BrowserViewError && err.status === 404) {
    // session gone or not yours
  }
}

Capacity (admin keys only)

const cap = await bv.capacity();
// { max_sessions, active_sessions, mem_total_bytes, mem_reserve_bytes,
//   mem_committed_bytes, session_mem_limit_bytes, webrtc_ports_free,
//   subnets_free, admittable }

Tenant keys receive a 403 ("admin API key required").

Health endpoints

GET /healthz and GET /readyz are unauthenticated and return {"status":"ok"} — useful for probes; the SDK does not wrap them.

About

TypeScript client for the browserview.io API. browserview.io runs disposable cloud Chromium sessions.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages