For AI agents: a documentation index is available at /llms.txt
Skip to main content

Reconnecting to sessions in BAP

reconnect() keeps the browser alive after your connection closes and hands you the endpoints to come back to it. That's how a session survives a client restart, moves between processes, or gets handed from BAP to Puppeteer mid-run.

Prerequisites

How reconnects work

Normally the browser shuts down when your page's WebSocket closes. Calling reconnect() changes that: after you disconnect, the browser stays up for the timeout you passed (default 30000 milliseconds) waiting for a new connection. The call returns the URLs a future connection needs. Nothing about your current connection changes, so you keep working on the page and disconnect whenever you're ready.

import Browserless from "@browserless.io/bap-ts";

const TOKEN = "YOUR_API_TOKEN_HERE";

const browser = Browserless.connect({
browserWSEndpoint: "wss://production-sfo.browserless.io/chromium/bql",
token: TOKEN,
});

try {
const page = await browser.newPage();
await page.goto("https://example.com/dashboard");

// After close(), the browser now survives for 60 seconds waiting for us.
const session = await page.reconnect({ timeout: 60_000 });
console.log(session.browserQLEndpoint);
} finally {
// Safe either way: after a successful reconnect() the keep-alive window
// outlives this close; before one, closing prevents a leaked session.
await browser.close();
}

Response:

https://production-sfo.browserless.io/chromium/bql/e4f5a6b7-c8d9-4012-a3b4-c5d6e7f8a9b0

The endpoints you get back

The response carries four URLs, each for a different way back in. None of them include your token, so append it when you connect.

FieldReconnectsUse it with
browserQLEndpointThe BrowserQL sessionBAP and raw BQL queries
browserWSEndpointThe browser over CDPPuppeteer or Playwright connect()
devtoolsFrontendUrlChrome DevTools remotelyA regular browser, for inspection
webSocketDebuggerUrlOne page over CDPLibraries that attach to a page instead of a browser

Continue the session from BAP

browserQLEndpoint comes back as an https:// URL for HTTP-based BQL queries. BAP talks BrowserQL over WebSocket, so swap the scheme to wss:// and connect a fresh browser to it:

// The returned endpoint is https://; BAP connects over WebSocket.
const endpoint = session.browserQLEndpoint!.replace(/^https/, "wss");

const resumed = Browserless.connect({
browserWSEndpoint: endpoint,
token: TOKEN,
});

try {
const samePage = await resumed.newPage();

// Still on the dashboard: this is the same browser, same state.
console.log(await samePage.url());
} finally {
await resumed.close();
}

Response:

https://example.com/dashboard

Cookies, storage, and the open page all persist, because it's the same browser process that never shut down.

Hand the session to Puppeteer or Playwright

browserWSEndpoint is a CDP URL, which means a session that BAP set up, solved a CAPTCHA in, or navigated through a login can be finished by CDP tooling:

import puppeteer from "puppeteer-core";

const TOKEN = "YOUR_API_TOKEN_HERE";

// The endpoint BAP's reconnect() returned, plus your token.
const browser = await puppeteer.connect({
browserWSEndpoint: `${session.browserWSEndpoint}?token=${TOKEN}`,
});

const [page] = await browser.pages();
console.log(await page.title());

// Terminate the session when done; a browser left to wait out its
// reconnect timeout still bills and holds a concurrency slot.
await browser.close();

This is the escape hatch for the methods BAP deliberately doesn't have, such as arbitrary evaluate() with argument passing. Do the protected part in BAP, then reconnect into Puppeteer for the rest.

Timeout limits and billing

The maximum reconnect TTL equals your plan's maximum session duration:

PlanMaximum Session Duration
Free2 minutes
Prototyping (20k)15 minutes
Starter (180k)30 minutes
Scale (500k)60 minutes
Enterprise (self-hosted)Custom

Passing a timeout above your plan's maximum fails immediately:

"Reconnect timeout (Xms) exceeds the maximum allowed limit (Yms)."

The maximum is an upper bound, not a way to reset the session clock:

  • The TTL is an idle grace period: how long the browser is held after you disconnect, waiting for you to come back.
  • Your plan's maximum session duration is an absolute deadline measured from when the browser started. A reconnect is always cut short by that deadline, so a 60-minute reconnect requested 50 minutes into a Scale session holds the browser for 10 minutes, not 60.
  • Repeated reconnects cannot push that deadline out. A session cannot be kept alive past its original maximum by reconnecting again.
  • Each reconnect is a new browser connection, so it's billed like any other connection.
  • Terminate the session as soon as you are done. A browser held open for its remaining TTL still occupies a concurrency slot.

FAQ & Troubleshooting

My reconnect endpoint stopped working after a minute

The timeout you passed is an idle grace period measured from disconnect. Once it elapses with no new connection, the browser terminates and the endpoint dies. Call reconnect() again on each new connection to keep the chain going, within your plan's maximum session duration.

I get an authorization error connecting to the returned endpoint

Returned endpoints never include token information. Pass your token the same way as a normal connection: the token option in BAP, or ?token= appended to the URL for Puppeteer and Playwright.

Does the session keep billing while nobody is connected?

Yes. A browser waiting out its reconnect timeout occupies a concurrency slot like any connected session, and each reconnection is billed as a new connection. Close sessions you're done with instead of letting the timeout expire.

Can I raise the timeout above my plan's session limit?

No. A timeout beyond the plan maximum fails immediately with Reconnect timeout (Xms) exceeds the maximum allowed limit (Yms)., and reconnecting never extends the absolute deadline measured from when the browser started.

Next steps

Was this page helpful?