Skip to main content
Version: v2

Managing Sessions

Once you've created a session, you can reconnect to it multiple times to continue your automation workflows while preserving browser state. Only one connection is allowed to this session at-a-time.

This guide covers both browser session reconnection using the Browserless.reconnect CDP command and Session API management.

Reconnecting to Browser Sessions

Browser sessions use the Browserless.reconnect CDP command to maintain state between connections and keep browsers alive after disconnection.

Basic Reconnection

When managing browser sessions, be aware that new connections may create additional pages. You can start your browser on an existing page to avoid creating an about:blank page, but since many examples online use the newPage() method, we're making sure we're reconnecting to the page that isn't about:blank by filtering the pages array.

import puppeteer from 'puppeteer-core';

const queryParams = new URLSearchParams({
token: 'YOUR_API_TOKEN',
timeout: 60000,
}).toString();

console.log('Starting up the first browser and logging in...');
const browser1 = await puppeteer.connect({
browserWSEndpoint: `wss://production-sfo.browserless.io?${queryParams}`,
});

const page1 = await browser1.newPage();
const cdp = await page1.createCDPSession();
await page1.goto('https://practicetestautomation.com/practice-test-login/', {
waitUntil: 'networkidle2',
timeout: 60000
});
await page1.type('#username', 'student');
await page1.type('#password', 'Password123');
await page1.click('#submit');

const { browserWSEndpoint } = await cdp.send('Browserless.reconnect', {
timeout: 60000,
});
console.log('Login successful! Enabling reconnection, the browser will remain active for 60 seconds after disconnect. browserWSEndpoint:', browserWSEndpoint);

await browser1.disconnect(); // Browser must be disconnected, not closed.

const browser2 = await puppeteer.connect({
browserWSEndpoint: `${browserWSEndpoint}?${queryParams}`,
});
// Get all pages and find the one that's not the about:blank page
const pages = await browser2.pages();
const page2 = pages.find(p => !p.url().startsWith('about:blank'));
const title = await page2.title();
await browser2.close();
console.log('Second browser closed - Demo complete! Page 2 title:', title);

Timeout and Plan Limitations

Reconnection functionality has timeout limits based on your subscription plan:

PlanMaximum Reconnect Timeout
Free10 seconds (10,000ms)
Prototyping/Starter1 minute (60,000ms)
Scale5 minutes (300,000ms)

Default timeout: 30 seconds (30,000ms) if not specified

Reconnecting to Sessions

Sessions maintain their state between connections using the Browserless.reconnect CDP command. Here are common reconnection patterns:

Multi-Step Workflows Perfect for breaking complex automation into manageable steps:

import puppeteer from 'puppeteer-core';

let reconnectEndpoint = null;

// Step 1: Authentication
const authenticateUser = async () => {
const browser = await puppeteer.connect({
browserWSEndpoint: 'wss://production-sfo.browserless.io?token=YOUR_API_TOKEN&timeout=60000',
});

const page = await browser.newPage();
const cdp = await page.createCDPSession();

await page.goto('https://app.example.com/login');
await page.type('#username', 'user@example.com');
await page.type('#password', 'password123');
await page.click('#login-button');
await page.waitForNavigation();

// Set up reconnection for next step
const { browserWSEndpoint } = await cdp.send('Browserless.reconnect', {
timeout: 60000, // 1 minute timeout
});
reconnectEndpoint = browserWSEndpoint;

await browser.close();
console.log('Authentication complete');
};

// Step 2: Data Collection
const collectData = async () => {
const browser = await puppeteer.connect({
browserWSEndpoint: `${reconnectEndpoint}?token=YOUR_API_TOKEN&timeout=60000`,
});

const [page] = await browser.pages();
// Still authenticated from previous step
await page.goto('https://app.example.com/dashboard');

const data = await page.evaluate(() => {
return document.querySelector('#user-data').textContent;
});

await browser.close();
console.log('Data collected:', data);
return data;
};

// Execute workflow
await authenticateUser();
const userData = await collectData();

Session Recovery with Reconnection Handle interruptions using Browserless.reconnect to maintain session state:

const resumeWorkflow = async (existingEndpoint = null) => {
let browserEndpoint = existingEndpoint || 'wss://production-sfo.browserless.io?token=YOUR_API_TOKEN';

const browser = await puppeteer.connect({
browserWSEndpoint: browserEndpoint,
});

const page = await browser.newPage();
const cdp = await page.createCDPSession();

// Check current state
await page.goto('https://app.example.com');
const isLoggedIn = await page.$('#user-menu') !== null;

if (!isLoggedIn) {
console.log('Session expired, re-authenticating...');
await page.goto('https://app.example.com/login');
// ... perform login
} else {
console.log('Session still active, continuing...');
await page.goto('https://app.example.com/dashboard');
}

// Set up reconnection before closing
const { browserWSEndpoint } = await cdp.send('Browserless.reconnect', {
timeout: 60000,
});

await browser.close();
return browserWSEndpoint; // Return for potential reconnection
};

Long-Running Processes with Reconnection Use Browserless.reconnect for session persistence during long operations:

const processLargeDataset = async (startPage = 1) => {
// Connect and set up reconnection for maintaining session between chunks
const browser = await puppeteer.connect({
browserWSEndpoint: 'wss://production-sfo.browserless.io?token=YOUR_API_TOKEN',
});

const page = await browser.newPage();
const cdp = await page.createCDPSession();

// Set up reconnection with 5 minute timeout
const { browserWSEndpoint } = await cdp.send('Browserless.reconnect', {
timeout: 300000, // 5 minutes
});

// Resume from where we left off
await page.goto(`https://app.example.com/data?page=${startPage}`);

let currentPage = startPage;
const maxPages = 100;

while (currentPage <= maxPages) {
console.log(`Processing page ${currentPage}`);

// Process current page data
const pageData = await page.evaluate(() => {
return Array.from(document.querySelectorAll('.data-item')).map(item => item.textContent);
});

// Save progress
await page.evaluate((page) => {
localStorage.setItem('lastProcessedPage', page.toString());
}, currentPage);

// Navigate to next page
currentPage++;
if (currentPage <= maxPages) {
await page.goto(`https://app.example.com/data?page=${currentPage}`);
}
}

await browser.close(); // Reconnection keeps session alive for potential reconnection
};

Managing Session API

Session API provides explicit control over session lifecycle with WebSocket connections for automation libraries. This is useful if you want to preserve browser state across a longer period of time.

Connecting to Session API

After creating a session with the Session API, use the WebSocket endpoint to connect your automation library:

import puppeteer from 'puppeteer-core';

// Assume you have a "connect" from the session creation step
const connect = 'wss://production-sfo.browserless.io/e/53...21/session/connect/b9..7b?token=25df...';

const browser = await puppeteer.connect({
browserWSEndpoint: connect,
});

const page = await browser.newPage();
await page.goto('https://example.com');

// Get all pages and print them
const pages = await browser.pages();
pages.forEach((p, i) => console.log(` [${i}] ${p.url()}`)); //print all existing pages

// Session state is maintained by the Session API
await page.evaluate(() => {
localStorage.setItem('myData', 'api-session-value');
});

await browser.close(); // Session remains active

Session State Persistence

Both session types preserve browser state, but handle it differently:

// Browser sessions persist state using Browserless.reconnect and the browser process stays alive
const browser = await puppeteer.connect({
browserWSEndpoint: 'wss://production-sfo.browserless.io?token=YOUR_API_TOKEN',
});

const page = await browser.newPage();
const cdp = await page.createCDPSession();
await page.goto('https://example.com');

// Set various types of state
await page.evaluate(() => {
// Local storage persists
localStorage.setItem('user_pref', 'dark_mode');

// Session storage persists
sessionStorage.setItem('temp_data', 'workflow_state');

// IndexedDB persists
const request = indexedDB.open('myDB', 1);
// ... IndexedDB operations
});

// Cookies are automatically saved
await page.setCookie({
name: 'session_token',
value: 'abc123',
domain: 'example.com'
});

// Set up reconnection before closing
const { browserWSEndpoint } = await cdp.send('Browserless.reconnect', {
timeout: 60000,
});

await browser.close();

// All state is preserved for reconnection within timeout window
// Use browserWSEndpoint for reconnection

Next Steps

  • Closing Sessions - Learn how to properly terminate sessions and clean up resources