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.
- Puppeteer
- Playwright
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);
import { chromium } from 'playwright';
const queryParams = new URLSearchParams({
token: 'YOUR_API_TOKEN',
timeout: 60000,
}).toString();
console.log('Starting up the first browser and logging in...');
const browser1 = await chromium.connectOverCDP(
`wss://production-sfo.browserless.io?${queryParams}`
);
const page1 = await browser1.newPage();
const cdpSession = await page1.context().newCDPSession(page1);
await page1.goto('https://practicetestautomation.com/practice-test-login/', {
waitUntil: 'networkidle',
timeout: 60000
});
await page1.fill('#username', 'student');
await page1.fill('#password', 'Password123');
await page1.click('#submit');
const { browserWSEndpoint } = await cdpSession.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 chromium.connectOverCDP(
`${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:
Plan | Maximum Reconnect Timeout |
---|---|
Free | 10 seconds (10,000ms) |
Prototyping/Starter | 1 minute (60,000ms) |
Scale | 5 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:
- Puppeteer
- Playwright
- Python
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
import { chromium } from 'playwright';
// 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 chromium.connectOverCDP(connect);
const context = browser.contexts()[0];
const page = await context.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
await browser.close(); // Session persists
import asyncio
from playwright.async_api import async_playwright
# Assume you have a "connect" from the session creation step
connect = 'wss://production-sfo.browserless.io/e/53...21/session/connect/b9..7b?token=25df...'
async def main():
async with async_playwright() as p:
browser = await p.chromium.connect_over_cdp(connect)
context = browser.contexts[0]
page = await context.new_page()
await page.goto("https://example.com")
pages.forEach((p, i) => console.log(` [${i}] ${p.url()}`)); //print all existing pages
await browser.close() # Session remains active
asyncio.run(main())
Session State Persistence
Both session types preserve browser state, but handle it differently:
- Browser Sessions
- Session API
// 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
// Session API maintains state through explicit session management
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');
// State is preserved within the session's timeout period
await page.evaluate(() => {
localStorage.setItem('api_session_data', 'preserved_value');
});
await browser.close();
// Reconnect to the same session
const browser2 = await puppeteer.connect({
browserWSEndpoint: connect,
});
const page2 = await browser2.newPage();
const data = await page2.evaluate(() =>
localStorage.getItem('api_session_data')
); // Returns 'preserved_value'
await browser2.close();
Next Steps
- Closing Sessions - Learn how to properly terminate sessions and clean up resources