Puppeteer Browser Contexts: Isolate Sessions Without Spinning Up New Browsers
Use one Puppeteer browser and create a browser context per user or test for fast, lightweight isolation. Contexts keep cookies and storage separate while sharing the Chromium process.
05 Jul 2026, 21:01 UTC

Running a scraper or test suite for many users at once hits the same wall: you need separate cookies, localStorage and permissions per user, but launching a full Chromium browser per user is slow and expensive. The practical takeaway is to keep one browser process and create a browser context per user or per test. A context is a lightweight isolated profile inside Puppeteer that shares the Chromium process while keeping storage and permissions separate.
One browser, many isolated profiles
A browser context is not a new browser. It is a logical partition created with browser.createIncognitoBrowserContext(). All contexts share the same browser launch flags and process, but each context owns its own cookie jar, storage, cache and permission grants.
That means you can spin up dozens of isolated sessions without paying the startup cost of a new browser. Closing a context automatically closes its pages and clears associated storage, which gives deterministic cleanup for long-running jobs.
Contexts model users, pages model tabs
Pages created from the same context share that context's storage state. If you open two pages from one context they behave like tabs for the same user: login in one page is visible in the other.
Pages from different contexts never see each other's state. This maps cleanly to multi-tenant scraping or parallel tests where each tenant or test case must not leak cookies or localStorage to another.
Contexts also allow per-context configuration of geolocation, locale, user agent and permissions. You can simulate different clients in the same browser process without mixing state.
Worked example: per-tenant context with distinct cookies
Run the following in a Node.js project with puppeteer installed. It requires network access to create a browser and no elevated privileges. Replace placeholders with your own values.
// node script, requires puppeteer
const puppeteer = require('puppeteer');
async function run() {
const browser = await puppeteer.launch({ headless: true });
const contextA = await browser.createIncognitoBrowserContext();
const contextB = await browser.createIncognitoBrowserContext();
const pageA = await contextA.newPage();
const pageB = await contextB.newPage();
// Set distinct cookies per context
await contextA.cookies([{
name: 'tenant',
value: 'A',
url: 'https://example.test'
}]);
await contextB.cookies([{
name: 'tenant',
value: 'B',
url: 'https://example.test'
}]);
const cookiesA = await contextA.cookies('https://example.test');
const cookiesB = await contextB.cookies('https://example.test');
// Verify isolation: cookiesA should contain tenant=A and not B
// Verify cleanup
await contextA.close();
// After close, pageA is disposed and further navigation should fail
await browser.close();
}
run().catch(console.error);The meaningful check is reading cookies via the context API and confirming no leakage between contexts. A practical verification is to create two contexts, set a distinct cookie in each, then read cookies from each context to confirm the values stay separate.
Risk: forgetting to close contexts in long-running jobs accumulates memory. Always close contexts when a tenant or test finishes.
Trade-offs and limits
Isolation is logical, not process-level. Many heavy contexts with many pages can still exhaust CPU and memory on the host. If you need hard resource caps, separate browser processes remain the only guarantee.
Request interception and network conditions are configured per page, not per context. Policies must be applied repeatedly when a context contains multiple pages.
Incognito contexts are isolated from each other but still run under the same browser launch flags and environment. Global settings such as user data directory, proxy, and launch arguments affect all contexts.
To check resource impact, create several contexts versus launching several browsers and compare process count and startup time. To verify cleanup, close a context and attempt to use its pages; navigation should fail as expected.
Use contexts when you need fast, cheap isolation per user or test. Use separate browser launches when you need process isolation, crash containment, or strict resource limits.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.