Creating Sessions
When building automation workflows, you often need to maintain browser state across multiple connections such as keeping a user logged in, preserving shopping cart contents, or maintaining form data between script runs. Browserless offers two approaches for creating persistent browser sessions that survive disconnections and allow you to resume automation from where you left off.
Which approach to use
Browser Sessions use the Browserless.reconnect
CDP command to maintain state between connections. This approach works with all automation libraries and automatically manages session lifecycle.
Use Browser Sessions When:
- Working with existing automation scripts
- Need simple session persistence
- Want maximum compatibility
- Session lifetime managed by your application logic
Session API allows you to restore sessions with all their preserved state, such as a logged-in user session, shopping cart contents, or any other browser state you need to maintain. This is particularly useful when you need to continue automation workflows across multiple script runs or when building applications that require users to authenticate once and then perform multiple operations over time. This approach provides explicit programmatic control over session creation and deletion through dedicated endpoints, designed for advanced use cases requiring precise lifecycle management or integration with larger automation platforms.
Use Session API When:
- Need explicit session lifecycle control
- Building advanced session management workflows
- Want programmatic session creation/deletion
- Need session monitoring and metadata
Pseudocode workflow diagram
Browser Sessions
The standard approach uses the Browserless.reconnect
CDP command to generate a browserWSEndpoint to reuse later on, which keeps the browsers alive after disconnection for a specified timeout duration.
It's important to note that the browser will be closed down if the browser.close()
method is used, so you'll need to use the browser.disconnect()
method so that the browser is kept alive for reconnection.
Browser Sessions TTL Limitations by Plan
The Time-To-Live duration is 30 seconds (30,000ms) by default, but can be increased depending on your plan type.
Plan | Maximum TTL |
---|---|
Free | 10 seconds (10,000ms) |
Prototyping/Starter | 1 minute (60,000ms) |
Scale | 5 minutes (300,000ms) |
How it works
When you use reconnection commands, Browserless:
- Keeps the browsers alive for the specified timeout duration after disconnection
- Maintains browser state including cookies, localStorage, sessionStorage, and cache
- Allows reconnection to the same browser instance within the timeout window
- Automatically cleans up sessions after the timeout expires or browser is closed.
Creating a Session
- Puppeteer
- Playwright
import puppeteer from "puppeteer-core";
// Connect to browser
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 up session state
await page.evaluate(() => {
localStorage.setItem("myData", "persistent-value");
});
// Enable reconnection with 60 second timeout
const { error, browserWSEndpoint } = await cdp.send("Browserless.reconnect", {
timeout: 60000,
});
if (error) throw error;
console.log("Reconnection endpoint:", browserWSEndpoint);
await browser.disconnect(); // Browser remains alive for 60 seconds
import { chromium } from "playwright";
// Connect to browser
const browser = await chromium.connectOverCDP(
"wss://production-sfo.browserless.io?token=YOUR_API_TOKEN",
);
const page = await browser.newPage();
const cdpSession = await page.context().newCDPSession(page);
await page.goto("https://example.com");
// Set up session state
await page.evaluate(() => {
localStorage.setItem("myData", "persistent-value");
});
// Enable reconnection with 60 second timeout
const { error, browserWSEndpoint } = await cdpSession.send(
"Browserless.reconnect",
{
timeout: 60000,
},
);
if (error) throw new Error(error);
console.log("Reconnection endpoint:", browserWSEndpoint);
await browser.disconnect(); // Browser remains alive for 60 seconds
Session Configuration
You can combine reconnection timeouts with other browser options for advanced configuration:
const queryParams = new URLSearchParams({
token: "YOUR_API_TOKEN",
stealth: true,
proxy: "residential",
headless: false,
});
const browser = await puppeteer.connect({
browserWSEndpoint: `wss://production-sfo.browserless.io?${queryParams.toString()}`,
});
const page = await browser.newPage();
const cdp = await page.createCDPSession();
// Enable reconnection with all options active
const { error, browserWSEndpoint } = await cdp.send("Browserless.reconnect", {
timeout: 60000,
});
Session API
Session API requires a paid plan and is designed for advanced use cases requiring explicit session lifecycle control.
For more control over session lifecycle, you can use the REST API to explicitly create sessions. This approach is useful when you need programmatic session management or advanced session control.
Creating a Session via REST API
- JavaScript
- Python
- cURL
const sessionConfig = {
ttl: 180000, // 3 minutes
stealth: true,
headless: false,
args: [
"--no-sandbox",
"--disable-dev-shm-usage",
"--disable-background-timer-throttling",
],
};
const response = await fetch(
"https://production-sfo.browserless.io/session?token=YOUR_API_TOKEN",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(sessionConfig),
},
);
if (!response.ok) {
throw new Error(
`Failed to create session: ${response.status} "${await response.text()}"`,
);
}
const session = await response.json();
console.log("Session created, browserWSEndpoint:", session.connect);
import requests
session_config = {
'ttl': 180000, # 3 minutes
'stealth': True,
'headless': False,
'args': [
'--no-sandbox',
'--disable-dev-shm-usage',
'--disable-background-timer-throttling',
]
}
response = requests.post(
'https://production-sfo.browserless.io/session',
params={'token': 'YOUR_API_TOKEN'},
json=session_config
)
session_data = response.json()
print(f'Session created: {session_data["connect"]}')
curl -X POST "https://production-sfo.browserless.io/session?token=YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"ttl": 180000,
"stealth": true,
"headless": false,
"args": [
"--no-sandbox",
"--disable-dev-shm-usage",
"--disable-background-timer-throttling"
]
}'
Session Configuration Options
Parameter | Type | Default | Description |
---|---|---|---|
ttl | number | 300000 | Time-to-live in milliseconds (max 30 minutes) |
stealth | boolean | false | Enable stealth mode to avoid detection |
headless | boolean | true | Run browser in headless mode |
args | string[] | [] | Additional Chrome launch arguments |
proxy | object | null | Proxy configuration |
Connecting to Session API
After creating a session with the Session API, use the returned connect
URL to connect to it:
- Puppeteer
- Playwright
- Python
import puppeteer from "puppeteer-core";
// Assume you have a browserWSEndpoint 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");
console.log(await page.url());
const foo = await page.evaluate(() => {
return window.localStorage.getItem("foo");
});
if (foo) {
console.log("LocalStorage foo exists:", foo);
} else {
console.log("LocalStorage foo does not exist, this is the first run");
}
// Session state is maintained by the Session API
await page.evaluate(() => {
localStorage.setItem("foo", "bar");
});
await browser.close(); // Session remains active
import { chromium } from "playwright-core";
// Assume you have a browserWSEndpoint 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");
console.log(await page.url());
const foo = await page.evaluate(() => {
return window.localStorage.getItem("foo");
});
if (foo) {
console.log("LocalStorage foo exists:", foo);
} else {
console.log("LocalStorage foo does not exist, this is the first run");
}
// Session state is maintained by the Session API
await page.evaluate(() => {
localStorage.setItem("foo", "bar");
});
await browser.close(); // Session remains active
import asyncio
from playwright.async_api import async_playwright
# Assume you have a browserWSEndpoint from the session creation step
browser_wse_endpoint = '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(browser_wse_endpoint)
context = browser.contexts[0]
page = await context.new_page()
await page.goto("https://example.com")
print(await page.url())
foo = await page.evaluate("window.localStorage.getItem('foo')")
if foo:
print('LocalStorage foo exists:', foo)
else:
print('LocalStorage foo does not exist, this is the first run')
# Session state is maintained by the Session API
await page.evaluate("window.localStorage.setItem('foo', 'bar')")
await browser.close() # Session remains active
asyncio.run(main())
Next Steps
- Managing Sessions - Learn how to connect to and manage existing sessions
- Closing Sessions - Understand session cleanup and termination