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

Reconnect to Session

The reconnect mutation lets you reuse a running browser session across multiple BrowserQL queries instead of launching a new browser for every request. The session preserves cookies, cache, and all page state between requests, which cuts proxy bandwidth, eliminates redundant page loads, and reduces the chance of triggering bot detection.

Prerequisites

How reconnects work

The reconnect mutation returns a browserQLEndpoint URL. You send your next query to that URL to reuse the same browser. Each reconnect resets the session's idle timer, so the browser stays alive as long as you keep reconnecting before the timeout expires, up to your plan's maximum session duration.

reconnect(timeout: 30000) {
browserQLEndpoint
}

The timeout value is in milliseconds. The response includes the endpoint URL for your next query.

Response

{
"data": {
"reconnect": {
"browserQLEndpoint": "https://production-sfo.browserless.io/e/53.../chromium/bql/05..."
}
}
}

Start a Session

Send your first query to open a browser session. Include the reconnect mutation to get a reusable endpoint URL.

import fetch from 'node-fetch';

const API_KEY = "YOUR_API_TOKEN";
const BQL_ENDPOINT = `https://production-sfo.browserless.io/chromium/bql?token=${API_KEY}`;

const sessionQuery = `
mutation StartSession {
goto(url: "https://example.com", waitUntil: networkIdle) {
status
}
reconnect(timeout: 30000) {
browserQLEndpoint
}
}`;

async function startSession() {
const response = await fetch(BQL_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: sessionQuery }),
});

const data = await response.json();
const reconnectUrl = data.data.reconnect.browserQLEndpoint;
console.log("Reconnect URL:", reconnectUrl);
return reconnectUrl;
}

startSession();

Use the Reconnect URL

Send your next query to the reconnect URL instead of the original endpoint.

API Token Required

The browserQLEndpoint returned by the reconnect mutation does not include your API token. Append ?token=YOUR_API_TOKEN to the reconnect URL before sending subsequent requests.

const RECONNECT_BQL_ENDPOINT = "YOUR_RECONNECT_BQL_ENDPOINT" + "?token=YOUR_API_TOKEN";

const scrapeQuery = `
mutation FetchData {
text(selector: ".product-title") {
text
}
}`;

async function fetchData() {
const response = await fetch(RECONNECT_BQL_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: scrapeQuery }),
});

const data = await response.json();
console.log("Fetched Data:", data.data.text.text);
}

fetchData();

Full Example

This example starts a session, scrapes multiple pages, and periodically reconnects to reset the idle timer. Reconnecting keeps the browser alive between queries, but never past your plan's maximum session duration.

import fetch from 'node-fetch';

const API_KEY = "YOUR_API_TOKEN";
const BQL_ENDPOINT = `https://production-sfo.browserless.io/chromium/bql?token=${API_KEY}`;

const sessionQuery = `
mutation StartSession {
goto(url: "https://example.com", waitUntil: networkIdle) {
status
}
reconnect(timeout: 30000) {
browserQLEndpoint
}
}`;

async function startSession() {
const response = await fetch(BQL_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: sessionQuery }),
});

const data = await response.json();
return data.data.reconnect.browserQLEndpoint;
}

async function fetchData(reconnectUrl) {
const scrapeQuery = `
mutation FetchData {
text(selector: ".product-title") {
text
}
}`;

const response = await fetch(reconnectUrl + "?token=" + API_KEY, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: scrapeQuery }),
});

const data = await response.json();
console.log("Fetched Data:", data.data.text.text);
}

// Reconnect before the timeout to extend the session
async function refreshSession(reconnectUrl) {
const refreshQuery = `
mutation RefreshSession {
reconnect(timeout: 30000) {
browserQLEndpoint
}
}`;

const response = await fetch(reconnectUrl + "?token=" + API_KEY, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: refreshQuery }),
});

const data = await response.json();
return data.data.reconnect.browserQLEndpoint;
}

(async () => {
let reconnectUrl = await startSession();
let pagesScraped = 0;
const REFRESH_INTERVAL = 20;

for (let i = 0; i < 100; i++) {
// Reconnect periodically to reset the idle timer
if (pagesScraped >= REFRESH_INTERVAL) {
reconnectUrl = await refreshSession(reconnectUrl);
pagesScraped = 0;
}

await fetchData(reconnectUrl);
console.log(`Scraped page ${i + 1}`);
pagesScraped++;
}
})();

Reconnect Timeout Limits

The timeout parameter in the reconnect mutation controls how long the browser stays alive waiting for a reconnect. Omitting it keeps the default of 30 seconds.

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.

Terminate sessions after reconnecting

After your work is done, send a DELETE request to terminate the session immediately. Sessions that are not explicitly closed continue to occupy a concurrency slot until the timeout expires, which can cause 429 Too Many Requests errors when you run many sessions in a loop.

Build the terminate URL from the browserQLEndpoint by replacing the browser-type segment (/chromium/bql/, /chrome/bql/, or /stealth/bql/) with /browser/<browserId>. Keep the /e/<encodedToken>/ prefix intact. The path swap happens inside that prefix, not at the root:

# browserQLEndpoint (returned by reconnect)
https://<host>/e/<encodedToken>/chromium/bql/<browserId>

# terminateURL (replace only the inner path segment)
https://<host>/e/<encodedToken>/browser/<browserId>
const TOKEN = process.env.BROWSERLESS_TOKEN;
const HOST = 'https://production-sfo.browserless.io';

const res = await fetch(`${HOST}/chromium/bql?token=${TOKEN}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `mutation {
goto(url: "https://example.com", waitUntil: networkIdle) { status }
reconnect(timeout: 60000) { browserQLEndpoint }
}`,
}),
});

const { data } = await res.json();
const { browserQLEndpoint } = data.reconnect;

// ... do your work using browserQLEndpoint ...

const browserId = browserQLEndpoint.split('/').pop();
const terminateURL = browserQLEndpoint.replace(/\/(chromium|chrome|stealth)\/bql\/[^/]+$/, `/browser/${browserId}`);

await fetch(`${terminateURL}?token=${TOKEN}`, { method: 'DELETE' });

Reconnect to Puppeteer or Playwright

reconnect also returns a browserWSEndpoint you can pass to puppeteer.connect() or playwright.chromium.connectOverCDP() to attach a CDP-based library to the same session, with all state carried over.

See Reconnect using Puppeteer & Playwright for the full guide.

FAQ & Troubleshooting

My reconnect endpoint returns a connection error

The session has expired. Each reconnect resets the idle timer, but if the timeout elapses before your next request, the browser is terminated. Increase the timeout value or reconnect more frequently. A session that has reached your plan's maximum session duration is terminated regardless of the reconnect timeout.

Can I reconnect to a session from a different machine?

Yes. The browserQLEndpoint URL is fully qualified and includes the session identifier. Any client that can reach the Browserless API can send queries to it.

Next steps

Was this page helpful?