Create an Isolated Browser Context with Puppeteer
Create a fresh Puppeteer browser context, keep cookies and cache separate, and close it safely. Includes current API syntax, options, troubleshooting, and a screenshot API shortcut.
Use Puppeteer’s browser.createBrowserContext() to create a fresh browser context, then open pages with context.newPage(). The new context keeps its cookies and cache separate from other contexts; close it with context.close() when the work is done. In current Puppeteer, createBrowserContext() is the method name. Puppeteer API reference
1. Create and close an isolated context
This runnable ES module example launches a browser, creates a context, navigates a page, and cleans up both resources. The finally block runs even if navigation or page work throws.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
let context;
try {
// This context has separate cookies and cache from other contexts.
context = await browser.createBrowserContext();
const page = await context.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
console.log(await page.title());
// Work with this page and any popups it opens.
} finally {
// Closing a created context closes its pages too.
if (context) {
await context.close();
}
// Close the browser only because this example launched and owns it.
await browser.close();
}
To run it, install Puppeteer in a project and use Node.js with ES module support:
npm install puppeteer
node --input-type=module app.js
Save the code as app.js in a project configured for ES modules, for example by setting "type": "module" in package.json. Puppeteer’s method returns a promise, so await it before creating a page.
2. What the isolation covers
A browser context is a grouping of pages within a browser. A newly created context does not share cookies or cache with other browser contexts. Puppeteer’s API overview also describes storage isolation including cookies and localStorage. In Chrome, non-default contexts are incognito. This is storage separation inside the browser, not a separate browser process or a claim of operating-system-level security isolation. Puppeteer API reference
- Cookies: a site’s cookies in one context are separate from those in another.
- Cache: browser cache is not shared across contexts.
- Local storage: Puppeteer’s context overview includes it in the isolated storage description.
- Pages and popups: pages created with
context.newPage()belong to that context. A popup opened by a page, such as throughwindow.open(), stays in its opener’s context.
Use a separate context per independent session when you need separate site state. Use a single context with multiple pages when those pages should act as the same session.
3. Create multiple independent sessions
For example, this helper creates two separate sessions. Each gets its own context and page. The caller that creates the contexts is responsible for closing them.
const contexts = [];
try {
for (const accountUrl of [
'https://example.com/account-a',
'https://example.com/account-b',
]) {
const context = await browser.createBrowserContext();
contexts.push(context);
const page = await context.newPage();
await page.goto(accountUrl, { waitUntil: 'domcontentloaded' });
}
} finally {
await Promise.all(contexts.map(context => context.close()));
}
In production code, create each context before assigning its pages and make sure every successfully created context is tracked for cleanup. If the browser is supplied by a caller or shared by a larger service, close only the contexts your code owns.
4. Choose the right context and lifecycle
| Need | Use | Lifecycle note |
|---|---|---|
| A fresh session with separate storage | browser.createBrowserContext() |
Close the context when finished; its pages close with it. |
| A page in the browser’s default session | browser.newPage() |
This creates a page in the default context. |
| The browser’s default context object | browser.defaultBrowserContext() |
The default context cannot be closed. |
| End a browser process your code launched | browser.close() |
Closes the browser and all associated pages. |
| Stop controlling a browser without stopping its process | browser.disconnect() |
Leaves the browser process running. |
These methods have different ownership effects. A utility borrowing a running browser should close its own context, then return control; it should not close or disconnect a browser unless its contract says it owns that browser lifecycle. Puppeteer API reference
5. Configure context options when needed
The options object is optional. The current BrowserContextOptions reference lists downloadBehavior, proxyBypassList, and proxyServer. The basic isolated-context use case needs none of them. Check the reference for the Puppeteer and browser versions you run if your workflow depends on a specific option. BrowserContextOptions reference
const context = await browser.createBrowserContext({
proxyServer: 'http://proxy.example:8080',
proxyBypassList: ['localhost', '*.internal.example'],
});
try {
const page = await context.newPage();
// If the proxy requires authentication, configure the page as needed:
// await page.authenticate({ username: 'user', password: 'secret' });
await page.goto('https://example.com');
} finally {
await context.close();
}
The proxy option configures a proxy server for requests; the reference notes that username and password can be set with Page.authenticate(). Treat proxy credentials as secrets: read them from a secret store or environment, avoid logging them, and rotate them according to your operational policy. Download behavior is another available option; consult the API reference for its shape and supported behavior rather than copying an assumed configuration.
6. Common errors and fixes
| Symptom | Cause | Fix |
|---|---|---|
browser.createIncognitoBrowserContext is not a function |
The code uses the former method name, renamed in Puppeteer 22. | Use await browser.createBrowserContext(). The changelog records the rename as a breaking change in version 22.0.0. Puppeteer changelog |
| Two pages unexpectedly share session state | One page was created with browser.newPage(), which uses the default context, or both pages were created in the same context. |
Create a separate context for each independent session and call context.newPage() for its pages. |
| Closing a context throws or is not available | The code may be trying to close the default context. | The default context cannot be closed. Create a disposable context with createBrowserContext() for work that needs cleanup. defaultBrowserContext reference |
| Other pages disappear after a helper finishes | The helper closed a browser it did not own. | Close only the context created by the helper. Let the browser owner decide whether to call browser.close() or browser.disconnect(). |
| A created context remains open after an exception | Cleanup was placed only on the success path. | Put context disposal in a finally block and track the context as soon as creation succeeds. |
| Proxy option or behavior is rejected | The option shape or support may differ by Puppeteer or browser version. | Check the installed version’s API reference and the browser/protocol support for that option. |
7. Performance, reliability, and cost
Contexts let one browser host multiple separated sessions, but each context and page still uses browser resources. Keep only the contexts and pages needed for the job, close them promptly, and bound concurrency according to the memory and CPU available to your deployment. The cited Puppeteer references do not provide a universal per-context resource cost or throughput figure, so measure your workload rather than relying on a fixed estimate.
For reliability, use try/finally cleanup, give navigation and the overall task appropriate timeouts, and make ownership explicit in APIs that borrow a browser. Context separation prevents accidental sharing of browser storage between contexts; it does not by itself isolate operating-system resources or make untrusted browser workloads safe.
Self-hosting means you operate the browser process and its compute environment. A hosted browser service is an optional deployment choice when you do not want to manage that infrastructure; it is not necessary to create an isolated context locally. Browserless platform
8. Or skip the browser setup
If your task is to capture a website rather than automate a multi-page browser session, ScreenshotNeo provides a website screenshot API and MCP server. It returns a PNG, JPEG, WebP, or PDF from one GET request. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.
Sign up free for 1,000 screenshots a month, with no card required.
9. Frequently asked questions
How do I keep cookies separate between Puppeteer pages?
Put the pages in different contexts. Pages in the same context share that session’s context state; pages in separate contexts have separated cookies and cache.
Does a popup use a new context?
No. A popup opened by a page belongs to its opener’s browser context.
Is a browser context a separate Chrome process?
No. It is a context within the browser. The documented isolation covers browser storage such as cookies and cache; do not treat it as process-level isolation.
Can I close the default browser context?
No. The default context cannot be closed. Create a non-default context when you need a disposable session.
What replaced createIncognitoBrowserContext()?
Use browser.createBrowserContext() in current Puppeteer. The former method was renamed in Puppeteer 22.0.0.


