olabrowser

Get connected

Your first browser session.

Create your workspace, connect your own code, and inspect what happened.

1. Set up your workspace

Create an account and verify your email. In workspace settings, create an organization, review its service use policy and activate its one-time 100-unit trial. Customer access opens only for approved workspaces during the controlled beta. Create a project, then choose “Create first-session key.” The key expires in one day and lets you create, read and close sessions and read their recordings. Save it when it appears; it cannot be retrieved later.

2. Connect your client

Use Node.js 22 or later. Set OLABROWSER_API_KEY in your environment. Keep it on your computer or server, outside source control and public browser code. Choose either example, save it as session.mjs, and run node session.mjs. These clients use your remote browser; you do not need to install Chromium locally.

These examples keep recording off. A workspace owner can enable recording consent in settings; then set record: true for an authorized capture. Each create request requires an Idempotency-Key. Reuse the same key and identical body if the response is lost; a pending or completed attempt never creates another browser.

Puppeteer

npm install puppeteer-core
import puppeteer from "puppeteer-core";

const key = process.env.OLABROWSER_API_KEY;
if (!key) throw new Error("Set OLABROWSER_API_KEY before running this example.");
const endpoint = "https://api.olabrowser.com/v1/sessions";
const headers = { Authorization: `Bearer ${key}` };
const response = await fetch(endpoint, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({ record: false }),
  signal: AbortSignal.timeout(45000),
});
if (!response.ok) throw new Error(`Session creation failed (${response.status}).`);
const session = await response.json();
console.log("Session:", session.id);
let browser;
try {
  browser = await puppeteer.connect({ browserWSEndpoint: session.connect_url });
  const page = await browser.newPage();
  await page.goto("https://example.com", { waitUntil: "domcontentloaded" });
  await page.waitForSelector("h1");
  console.log("Page:", await page.title());
} finally {
  try {
    if (browser) await browser.close();
  } finally {
    const closed = await fetch(`${endpoint}/${encodeURIComponent(session.id)}`, {
      method: "DELETE", headers, signal: AbortSignal.timeout(10000),
    });
    if (!closed.ok && closed.status !== 404) {
      throw new Error(`Session cleanup failed (${closed.status}).`);
    }
  }
}

Playwright

npm install playwright
import { chromium } from "playwright";

const key = process.env.OLABROWSER_API_KEY;
if (!key) throw new Error("Set OLABROWSER_API_KEY before running this example.");
const endpoint = "https://api.olabrowser.com/v1/sessions";
const headers = { Authorization: `Bearer ${key}` };
const response = await fetch(endpoint, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({ record: false }),
  signal: AbortSignal.timeout(45000),
});
if (!response.ok) throw new Error(`Session creation failed (${response.status}).`);
const session = await response.json();
console.log("Session:", session.id);
let browser;
try {
  browser = await chromium.connectOverCDP(session.connect_url);
  const page = await browser.newPage();
  await page.goto("https://example.com", { waitUntil: "domcontentloaded" });
  await page.waitForSelector("h1");
  console.log("Page:", await page.title());
} finally {
  try {
    if (browser) await browser.close();
  } finally {
    const closed = await fetch(`${endpoint}/${encodeURIComponent(session.id)}`, {
      method: "DELETE", headers, signal: AbortSignal.timeout(10000),
    });
    if (!closed.ok && closed.status !== 404) {
      throw new Error(`Session cleanup failed (${closed.status}).`);
    }
  }
}

The response’s connect_url is a single-use credential. Do not log, share or reuse it. The examples close the browser and request session cleanup even when navigation fails.

3. Inspect the result

When the example prints “Example Domain,” open Sessions, select your project, and refresh. Inspect the printed session ID for its timeline and, if recording was enabled, its stored replay. Recording processing may take a moment after closure; refresh again if it is still processing. Usage shows confirmed browser time, excluding allocation and cleanup. A normal closure describes the browser lifecycle; your code determines whether its task succeeded.

Limits and privacy

The current beta allows one concurrent trial session per workspace, shared across projects, a five-minute maximum session duration, and a 60-second idle timeout. A unit is 30 seconds, rounded up per session. Session creation reserves 10 units for the maximum five-minute lifetime. Remaining units are released on confirmed closure; our browser and egress errors cost zero. Worker loss holds the reservation for reconciliation. Paid plans are not available yet. Stored recordings expire after 24 hours. Recording is off by default; record: false launches with capture disabled. Enabled recordings mask inputs and omit network headers, bodies and URL paths, but page text and DOM attributes may still contain sensitive data. Only opt in on pages you are authorized to capture.

Troubleshooting

401 means the key is invalid, expired or revoked. A 403 can indicate a missing permission, closed workspace access, a required policy acceptance, or missing recording consent. A 402 means fewer than 10 units remain for a new reservation. A 409 on retry means the same create is pending or has already been attempted; inspect its session instead of allocating again. A 429 means session admission did not finish within its bounded wait; close any session you are no longer using and respect Retry-After before retrying. A 503 indicates a service or browser failure. Do not continuously retry or print a credential-bearing response while diagnosing it.