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. 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

import puppeteer from 'puppeteer-core';

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

// First connection - perform login and set up reconnection
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://example.com/login');
await page1.type('#username', 'user@example.com');
await page1.type('#password', 'password123');
await page1.click('#login-button');
await page1.waitForNavigation();

// Enable reconnection - browser will stay alive for 60 seconds after disconnect
const { browserWSEndpoint } = await cdp.send('Browserless.reconnect', {
timeout: 60000,
});

await browser1.close();

// Reconnect using the returned endpoint
const browser2 = await puppeteer.connect({
browserWSEndpoint: `${browserWSEndpoint}?${queryParams}`,
});

const [page2] = await browser2.pages();
// You're still logged in! Navigate to protected area
await page2.goto('https://example.com/dashboard');

await browser2.close();

Timeout-Based Sessions

You can use the Browserless.reconnect CDP command to automatically keep browsers alive after disconnection:

import puppeteer from 'puppeteer-core';

// Connect and set up reconnection
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/login');
// ... perform login

// Enable reconnection - browser will stay alive for 60 seconds after disconnect
const { error, browserWSEndpoint } = await cdp.send('Browserless.reconnect', {
timeout: 60000,
});

if (error) throw error;
console.log('Reconnection endpoint:', browserWSEndpoint);

await browser.disconnect(); // Browser stays alive for 60 seconds

// Reconnect within the timeout window
const reconnectedBrowser = await puppeteer.connect({
browserWSEndpoint: `${browserWSEndpoint}?token=YOUR_API_TOKEN`,
});

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.

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 sessionId from session creation
const sessionId = 'session-abc123';

const browser = await puppeteer.connect({
browserWSEndpoint: `wss://production-sfo.browserless.io/session/connect/${sessionId}?token=YOUR_API_TOKEN`,
});

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

// 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
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

Reconnection with Retry Logic

Implement retry logic for reliable session connections:

import puppeteer from 'puppeteer-core';

async function connectWithRetry(browserEndpoint, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const browser = await puppeteer.connect({
browserWSEndpoint: browserEndpoint,
});
return browser;
} catch (error) {
console.log(`Connection attempt ${i + 1} failed:`, error.message);
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}

// Usage with reconnection setup
try {
const browser = await connectWithRetry('wss://production-sfo.browserless.io?token=YOUR_API_TOKEN');
const page = await browser.newPage();
const cdp = await page.createCDPSession();

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

// ... your automation
await browser.close();
// Use browserWSEndpoint for potential reconnection
} catch (error) {
console.error('Failed to connect after retries:', error);
}

Next Steps

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