Answer
BrowserContext in Playwright
The Three-Level Hierarchy
CODE
Browser
└── BrowserContext (isolated session)
└── Page (a tab/window)
Browser — the browser process (Chromium, Firefox, WebKit) BrowserContext — an isolated session, like a private/incognito window Page — a single tab within a context
What BrowserContext Isolates
Each context has its own:
- ✓Cookies
- ✓localStorage / sessionStorage
- ✓Cache
- ✓Authentication state
- ✓Permissions
- ✓Network settings
Changes in one context do NOT affect another — even running in the same browser process.
Default Context in Tests
When you use { page } in a Playwright test fixture, it automatically gets a fresh BrowserContext per test:
TypeScript
test('isolated test', async ({ page }) => {
// page lives in its own BrowserContext
// No cookie/auth leakage from other tests
await page.goto('/dashboard');
});
Creating Contexts Manually
TypeScript
import { chromium } from '@playwright/test';
const browser = await chromium.launch();
// Two isolated contexts = two separate sessions
const userContext = await browser.newContext();
const adminContext = await browser.newContext();
const userPage = await userContext.newPage();
const adminPage = await adminContext.newPage();
// User logs in as regular user
await userPage.goto('/login');
await userPage.fill('#email', 'user@test.com');
// Admin logs in simultaneously
await adminPage.goto('/admin/login');
await adminPage.fill('#email', 'admin@test.com');
await browser.close();
Context with Custom Options
TypeScript
const context = await browser.newContext({
// Use saved auth state
storageState: 'auth.json',
// Emulate mobile
viewport: { width: 375, height: 667 },
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0...',
isMobile: true,
// Geolocation
geolocation: { latitude: 40.7128, longitude: -74.0060 },
permissions: ['geolocation'],
// HTTP auth
httpCredentials: { username: 'user', password: 'pass' },
// Ignore HTTPS errors
ignoreHTTPSErrors: true,
// Record video
recordVideo: { dir: 'videos/' },
});
Use Case — Test Concurrent Users
TypeScript
test('admin and user interact simultaneously', async ({ browser }) => {
// Create two isolated sessions
const adminCtx = await browser.newContext({ storageState: 'admin-auth.json' });
const userCtx = await browser.newContext({ storageState: 'user-auth.json' });
const adminPage = await adminCtx.newPage();
const userPage = await userCtx.newPage();
await adminPage.goto('/admin/inventory');
await userPage.goto('/shop');
// Admin updates stock
await adminPage.getByTestId('item-1-stock').fill('0');
await adminPage.getByRole('button', { name: 'Save' }).click();
// User should see out-of-stock
await userPage.reload();
await expect(userPage.getByTestId('item-1-stock-badge')).toHaveText('Out of Stock');
await adminCtx.close();
await userCtx.close();
});
