brawsrdocsv0.6
Examples

Start several paths from one browser

Fork ordered Playwright sessions from one checkpoint and verify every child inherited the captured state.

Suppose a workflow has already reached an expensive state: it authenticated, loaded data, and filled part of a form. Several independent jobs now need to start from exactly there. Fork captures that common starting point once and creates peer browser sessions from it.

The state model

  • The source prepares "checkpointed" and captures it.
  • The source then changes its own value to "source-after-checkpoint".
  • Every child should still contain "checkpointed".
  • Children are independent sessions; changes in one do not appear in another.

1. Capture the shared starting point

The post-checkpoint edit is deliberate. It proves the children inherit the checkpoint, not whatever state happens to be live in the source later.

await page.goto(url);
await page.evaluate(
  ([key, value]: readonly [string, string]) =>
    localStorage.setItem(key, value),
  [markerKey, "checkpointed"] as const,
);
const checkpoint = await brawsr.createCheckpoint(session.id, {
  label: `playwright-fork-${n}`,
});
await page.evaluate(
  ([key, value]: readonly [string, string]) =>
    localStorage.setItem(key, value),
  [markerKey, "source-after-checkpoint"] as const,
);

2. Create ordered children

n comes from BRAWSR_FORK_N. With the default three-session organization limit, use one or two children because the source session remains active too. The lineage check confirms the children are visible from their source.

forked = await brawsr.fork(session.id, checkpoint, { n });
const lineage = await brawsr.getLineage(session.id);
if (lineage.children.length !== n)
  throw new Error("fork children are missing from session lineage");

3. Attach to each child and verify inheritance

Each child carries its own CDP connection. The branch index gives stable order; the marker check proves every browser started from the checkpointed state.

const restored = await Promise.all(
  forked.children.map(async (child) => {
    const connection = brawsr.connectCDP(child);
    const browser = await chromium.connectOverCDP(connection.endpointUrl, {
      headers: connection.headers,
    });
    browsers.push(browser);
    const childPage = browser.contexts()[0]?.pages()[0];
    if (!childPage)
      throw new Error(`child ${child.branchIndex} has no restored page`);
    return childPage.evaluate(
      (key: string) => localStorage.getItem(key),
      markerKey,
    );
  }),
);
if (restored.some((value) => value !== "checkpointed"))
  throw new Error("fork lost browser state");

4. Own the cleanup policy

brawsr does not decide which peers your application should keep. The example closes every browser handle, every child session, and the source in finally.

await Promise.allSettled(browsers.map((browser) => browser.close()));
await closeSessionTree(brawsr, session.id, [forked]);

View the complete Playwright fork example (opens in a new tab)

On this page