← TemplatesSessions API template

Parallel browser sessions

Fan a URL list across several cloud browsers at once and collect results as each session finishes.

Sessions APIPlaywrightConcurrency

Use this when one browser is too slow for the batch: crawls, screenshot sweeps, per-account checks. Each worker owns one session, so cookies and identity never leak between jobs, and a crashed page only loses its own URL.

Executable starters

parallel-sessions.ts
import { chromium } from 'playwright';const apiKey = process.env.BROWSERCITY_API_KEY;if (!apiKey) {  throw new Error('Set BROWSERCITY_API_KEY before running this script.');}const urls = [  'https://example.com',  'https://example.org',  'https://example.net',];const CONCURRENCY = 3; // Stay within your plan's parallel session allowance.async function processUrl(url: string): Promise<{ url: string; title: string }> {  const { endpoint, token, id } = await fetch('https://api.browser.city/v1/sessions', {    method: 'POST',    headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },    body: JSON.stringify({ browser: 'chromium' }),  }).then((r) => r.json());  try {    const browser = await chromium.connect(endpoint, {      headers: { Authorization: `Bearer ${token}` },    });    const page = browser.contexts().at(0)!.pages().at(0)!;    await page.goto(url);    return { url, title: (await page.title()) ?? '' };  } finally {    await fetch(`https://api.browser.city/v1/sessions/${id}`, {      method: 'DELETE',      headers: { Authorization: `Bearer ${apiKey}` },    });  }}const queue = [...urls];const workers = Array.from({ length: CONCURRENCY }, async () => {  const results: { url: string; title: string }[] = [];  for (let url = queue.shift(); url; url = queue.shift()) {    results.push(await processUrl(url));  }  return results;});const results = (await Promise.all(workers)).flat();console.log(JSON.stringify(results, null, 2));

Production hardening checklist

  • Size the worker pool to your plan’s concurrency, not to the batch size.
  • Always close sessions in a finally block; leaked sessions bill until they time out.
  • Record per-URL failures and retry them in a second pass instead of aborting the batch.
  • Label sessions per batch so usage views show which job consumed what.

Cost and plan notes

Total compute equals the sum of session minutes regardless of parallelism, so raising concurrency buys speed, not savings. If a batch step is pure extraction, consider the Request API instead — it is cheaper than holding open sessions.

[ 08 / 08 ] — Get Started

Give your AI agents the web.

We're in private beta — request access and we'll get you set up. Private sessions by default.