Skip to main content
Version: v2

Persisting State

For more control over session lifecycle, you can use the REST API to explicitly create and manage sessions through HTTP endpoints. This approach provides programmatic session management with advanced control over session configuration and monitoring, and is designed for use cases requiring persistent state across longer periods of time. This method allows you to persist data for multiple days, depending on your plan, even when the browser is closed.

Persisting browser sessions demonstration

Sessions API Only

This document covers the Sessions API (REST API for explicit session management). For Browser Sessions using Browserless.reconnect CDP command, see Standard Sessions.

Persisting State Workflow

  1. Create Session

    Create a new session using the REST API with the desired configuration. You can save the session object returned in your database so you can manage these sessions for multiple days (Depending on your plan).

    import fetch from 'node-fetch';

    async function createSession(apiKey, sessionConfig) {
    try {
    const response = await fetch(`https://production-sfo.browserless.io/session?token=${apiKey}`, {
    method: "POST",
    headers: {
    "Content-Type": "application/json",
    },
    body: JSON.stringify(sessionConfig),
    });

    if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
    }
    const session = await response.json();
    return session;
    } catch (error) {
    console.error("Error creating session:", error.message);
    throw error;
    }
    }

    (async () => {
    try {
    const sessionConfig = {
    ttl: 180000,
    stealth: true,
    headless: false,
    };
    const session = await createSession("YOUR_API_TOKEN_HERE", sessionConfig);
    console.log("Session created: ", session);
    } catch (error) {
    console.error("Failed to create session:", error);
    }
    })();
  2. Connect to Session

    Use the session connect URL from step 1 to connect your automation library to the created session:

    import puppeteer from "puppeteer-core";

    async function connectToSession(connectUrl) {
    try {
    const browser = await puppeteer.connect({
    browserWSEndpoint: connectUrl,
    });
    const pages = await browser.pages();
    const page = pages[0] || await browser.newPage();
    return { browser, page };
    } catch (error) {
    console.error("Error connecting to session:", error.message);
    throw error;
    }
    }
    // Use the WSS from step 1
    const connectUrl = "wss://production-sfo.browserless.io/e/53...f2/session/connect/27...11?token=...";
    const { browser, page } = await connectToSession(connectUrl);
    await page.goto("https://example.com");
    await page.close();
  3. Close Session

    When you're finished with your session, properly close it to free up resources. Use the session.stop URL from the previous steps as the sessionCloseURL:

    import fetch from 'node-fetch';

    const stopSession = async (sessionCloseURL) => {
    try {
    const urlWithForce = `${sessionCloseURL}&force=true`; //force is optional
    console.log('Stopping session with URL:', urlWithForce);

    const response = await fetch(urlWithForce, {
    method: 'DELETE',
    });

    if (response.ok) {
    const result = await response.json();
    return true;
    } else {
    console.error(`Failed to stop session ${sessionCloseURL}:`, response.status);
    const errorText = await response.text();
    console.error('Error response:', errorText);
    return false;
    }
    } catch (error) {
    console.error(`Error stopping session ${sessionCloseURL}:`, error);
    return false;
    }
    };

    // Use stop URL from step 1
    await stopSession('https://production-sfo.browserless.io/e/57..09/session/57..09?token=...');

Complete Example

Here's a complete example that demonstrates the full session lifecycle - creating a session, connecting to it, persisting data, and properly cleaning up once you no longer need to reconnect to it.

import fetch from 'node-fetch';
import puppeteer from "puppeteer-core";

const apiKey = "YOUR_API_TOKEN_HERE"; // Replace with your actual API key
const sessionConfig = {
ttl: 180000,
stealth: true,
headless: false,
};

async function createSession(apiKey, sessionConfig) {
try {
const response = await fetch(`https://production-sfo.browserless.io/session?token=${apiKey}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(sessionConfig),
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const session = await response.json();
return session;
} catch (error) {
console.error("Error creating session:", error.message);
throw error;
}
}

async function connectToSession(connectUrl) {
try {
const browser = await puppeteer.connect({
browserWSEndpoint: connectUrl,
});
const pages = await browser.pages();
const page = pages[0] || await browser.newPage();
return { browser, page };
} catch (error) {
console.error("Error connecting to session:", error.message);
throw error;
}
}

const stopSession = async (sessionCloseURL) => {
try {
const urlWithForce = `${sessionCloseURL}&force=true`;
console.log('Stopping session with URL:', urlWithForce);

const response = await fetch(urlWithForce, {
method: 'DELETE',
});

if (response.ok) {
const result = await response.json();
return true;
} else {
console.error(`Failed to stop session ${sessionCloseURL}:`, response.status);
const errorText = await response.text();
console.error('Error response:', errorText);
return false;
}
} catch (error) {
console.error(`Error stopping session ${sessionCloseURL}:`, error);
return false;
}
};

(async () => {
try {
const session = await createSession(apiKey, sessionConfig);

const { connect: connectUrl, stop: stopUrl } = session;
console.log("Step 1: Created session and saved connect WSS and stop URL:", connectUrl);

const { browser, page } = await connectToSession(connectUrl);

console.log("Step 2: Connected to the session using Puppeteer:", page);
await page.goto("https://docs.browserless.io/");
await page.click('.toggle_vylO.colorModeToggle_x44X');
await page.screenshot({path:"FirstRun.jpg"});
console.log("Toggled dark mode and took a screenshot");
await browser.close();

const { browser: browser2, page: page2 } = await connectToSession(session.connect);

console.log("Connected to the session again.");
await page2.goto("https://docs.browserless.io/");
await page2.screenshot({path:"SecondRun.jpg"});
console.log("Took a screenshot and see the dark mode persisted");
await browser2.close();
await new Promise(resolve => setTimeout(resolve, 1000));
// Step 3: Only run this stopSession function once you are ready to destroy it and don't plan on connecting to this session again.

await stopSession(stopUrl);

console.log("Session stopped, you won't be able to reconnect to this session again.");
} catch (error) {
console.error("Failed to complete session workflow:", error.message);
}
})();

Persisted session data duration

The data that can be persisted includes cache, cookies, localStorage, and session data. The length of time this data can be persisted depends on your plan:

PlanPersisted Session Duration
Free1 day
Prototyping7 days
Starter30 days
Scale90 days
EnterpriseCustom

You can also limit the time you want the data to be persisted by passing a ttl option to the session API, which will expire the session data before the plan limit if desired.

Session Configuration Options

ParameterTypeDefaultDescription
ttlnumber300000Time-to-live in ms (When the session data will expire)
stealthbooleanfalseEnable stealth mode to avoid detection
headlessbooleantrueRun browser in headless mode
argsstring[][]Additional Chrome launch arguments
proxyobjectnullProxy configuration

For the complete list of all available session configuration parameters, see the Session API documentation.

Next Steps

Ready to take your session management to the next level? Explore these key areas: