PLAYWRIGHT UIINTERMEDIATE

Playwright Browser Context & Multiple Tabs: The Complete Guide with Real-World Examples

Learn Playwright Browser Context with real-world examples. Master multiple tabs, multiple users, session isolation, incognito browsers, authentication, context storage, and enterprise testing best practices.

iff Solution Academy July 12, 2026 28 min read Updated July 2026
Playwright Browser Context Multiple Tabs Multi-User storageState SDET

One of Playwright's most powerful features is the Browser Context. It is the mechanism that lets you simulate multiple independent users, isolate sessions, reuse authentication, and orchestrate multi-tab flows — all inside a single browser instance.

This guide walks through Browser Context end to end: what it is, how it differs from a Browser, how to open and switch between multiple tabs, how to save and reuse authentication with storageState, and the enterprise patterns real SDET teams use in production frameworks.

What is Browser Context?

A Browser Context represents an isolated browser session. Every context has its own cookies, local storage, session storage, permissions, and cache. Think of a Browser Context as an 'Incognito Window' — nothing leaks between contexts.

Multiple Browser Contexts can exist inside a single browser instance without sharing any session data, which allows Playwright to simulate multiple independent users without launching multiple browsers.

Why Browser Context Matters

In real-world applications, automation engineers frequently need to simulate scenarios that involve more than one user or more than one session:

  • Two users chatting in real time.
  • Buyer and seller on a marketplace.
  • Admin approving actions performed by a customer.
  • Manager reviewing an employee's submission.
  • Multiple banking users with separate accounts.
  • Separate authenticated sessions running in parallel.

Without Browser Context, these scenarios become extremely difficult — you either launch multiple browsers (slow, memory-heavy) or try to reuse a single session (broken isolation). Browser Context gives you cheap, clean isolation.

Browser vs Browser Context

A Browser launches Chrome, Firefox, or WebKit. A Browser Context is an isolated session running inside that browser. Each context can host multiple tabs (pages).

text
Browser
│
├── Context A (Admin User)
│      ├── Tab 1
│      └── Tab 2
│
├── Context B (Customer)
│      └── Tab 1
│
└── Context C (Guest User)

Each context has completely separate authentication and storage; tabs inside the same context share them.

Creating a Browser Context

ts
import { chromium } from '@playwright/test';

const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();

This creates a fresh, isolated session — no cookies, no local storage, no cached auth.

Creating Multiple Browser Contexts

ts
const adminContext = await browser.newContext();
const customerContext = await browser.newContext();

const adminPage = await adminContext.newPage();
const customerPage = await customerContext.newPage();

Each user now behaves independently. Using multiple contexts inside one browser is:

  • Faster than launching multiple browsers.
  • Less memory-intensive.
  • Easier to manage in code.
  • Better suited to parallel execution.

Enterprise automation frameworks almost always prefer multiple contexts over multiple browser instances.

Opening Multiple Tabs

One Browser Context can contain many tabs. All tabs share the context's cookies and storage.

ts
const context = await browser.newContext();
const homePage = await context.newPage();
const profilePage = await context.newPage();

await homePage.goto('https://example.com');
await profilePage.goto('https://example.com/profile');

Both tabs belong to the same authenticated user.

Getting All Tabs

ts
const pages = context.pages();
console.log(pages.length);

Waiting for a New Tab

Many applications open a new window after clicking a button. Playwright makes this simple:

ts
const pagePromise = context.waitForEvent('page');
await page.getByRole('link', { name: 'Open Report' }).click();
const newPage = await pagePromise;
await newPage.waitForLoadState();

This ensures the test waits until the new tab is fully created before interacting with it.

Switching Between Tabs

ts
const pages = context.pages();
const dashboard = pages[0];
const report = pages[1];

await report.bringToFront();

You can freely switch between pages within the same context — no session reload, no re-authentication.

Sharing Authentication Across Tabs

Tabs inside the same Browser Context automatically share cookies, local storage, and session storage. If one tab logs in, every tab in that context is authenticated — exactly like real browser behavior.

Authentication Example

ts
const context = await browser.newContext();
const page = await context.newPage();

await page.goto('/login');
await page.fill('#email', 'admin@test.com');
await page.fill('#password', 'password');
await page.click('button[type=submit]');

Any new page created inside this context is already logged in.

Saving Storage State

Instead of logging in before every test, Playwright can save the authenticated session to a JSON file.

ts
await context.storageState({ path: 'auth.json' });

The file contains cookies, local storage, and authentication tokens. Reusing it dramatically speeds up automation.

Loading Storage State

ts
const context = await browser.newContext({
  storageState: 'auth.json',
});

The browser starts already authenticated. This is one of the most common enterprise Playwright techniques, and it is usually paired with a global setup file that runs the login once per test run.

Multi-User Testing

Suppose you're testing a chat application. Create one context per user so their sessions stay isolated:

ts
const admin = await browser.newContext({ storageState: 'auth/admin.json' });
const customer = await browser.newContext({ storageState: 'auth/customer.json' });

const adminPage = await admin.newPage();
const customerPage = await customer.newPage();

await adminPage.goto('/chat');
await customerPage.goto('/chat');

await adminPage.getByRole('textbox').fill('Hello from admin');
await adminPage.keyboard.press('Enter');

await expect(customerPage.getByText('Hello from admin')).toBeVisible();

The same pattern powers approval workflows, banking flows, ecommerce buyer/seller scenarios, and CRM handoffs.

Enterprise Framework Example

In production frameworks, per-role Browser Contexts are wrapped in Playwright fixtures so tests never touch context creation directly.

text
fixtures/
  auth.fixture.ts
  admin.fixture.ts
  customer.fixture.ts
  guest.fixture.ts
fixtures/admin.fixture.ts
import { test as base, Page } from '@playwright/test';

export const test = base.extend<{ adminPage: Page }>({
  adminPage: async ({ browser }, use) => {
    const context = await browser.newContext({ storageState: 'auth/admin.json' });
    const page = await context.newPage();
    await use(page);
    await context.close();
  },
});
export { expect } from '@playwright/test';
ts
import { test, expect } from '../fixtures/admin.fixture';

test('admin can view all orders', async ({ adminPage }) => {
  await adminPage.goto('/orders');
  await expect(adminPage.getByRole('heading', { name: 'All Orders' })).toBeVisible();
});

Each fixture owns its own Browser Context, so tests become extremely simple and completely isolated.

Best Practices

  • One context per user — never share a context between different identities.
  • Use storageState() to avoid repeated login flows in every test.
  • Reuse the browser instance across tests; recreate contexts, not browsers.
  • Close contexts you open manually (Playwright only auto-closes what it created).
  • Keep contexts isolated — do not copy cookies between them by hand.
  • Wrap context creation in fixtures so tests describe behavior, not setup.

Common Mistakes

  • Launching a new browser per user instead of a new context — huge memory and time cost.
  • Logging in before every test instead of reusing storageState — slow and flaky.
  • Sharing one Browser Context between different users — sessions collide.
  • Forgetting to close manually created contexts — memory leaks in long runs.
  • Interacting with a new tab before waitForLoadState() completes — races and flakiness.

Interview Questions

What is Browser Context?

An isolated browser session containing its own cookies, storage, permissions, and authentication.

Difference between Browser and Browser Context?

Browser launches Chrome, Firefox, or WebKit. Browser Context creates isolated sessions inside that browser — many contexts per browser, many tabs per context.

Why is Browser Context important?

It enables multi-user testing, session isolation, authentication reuse, and faster parallel execution — all without launching multiple browsers.

How does Playwright handle multiple tabs?

Each Browser Context can contain multiple pages. Use context.newPage() to open a new tab, and context.waitForEvent('page') to catch tabs the app opens itself.

What is storageState()?

storageState() saves authentication information (cookies, local storage) to a file so future tests can start already logged in.

Summary

Browser Context is one of Playwright's most powerful enterprise features. It allows engineers to create isolated browser sessions, test multiple users simultaneously, reuse authentication, manage multiple tabs, and build scalable automation frameworks.

Understanding Browser Context is essential for professional Playwright automation and is frequently discussed during SDET interviews.

Get Playwright tutorials in your inbox

Weekly tips, real-world examples, and framework patterns – no spam, unsubscribe anytime.

Playwright Framework Series

View all →
  1. 1Getting Started with Playwright: Installation, Setup, and Your First Test
  2. 2Playwright Locators: The Complete Guide with Real-World Examples
  3. 3Playwright Actions: Complete Guide to Click, Fill, Hover, Keyboard, Mouse & File Upload
  4. 4Playwright Assertions: The Complete Guide with Real-World Examples
  5. 5Playwright Auto Waiting: The Complete Guide with Real-World Examples
  6. 6Playwright Fixtures: The Complete Guide with Real-World Examples
  7. 7Playwright Browser Context & Multiple Tabs: The Complete Guide with Real-World Examples
  8. 8Playwright Authentication & Session Management: Complete Guide with Enterprise Examples
  9. 9Playwright Network Interception & API Mocking: Complete Guide with Real-World Examples
  10. 10Playwright Page Object Model (POM): The Complete Guide with Enterprise Examples
  11. 11Page Object Model with Playwright: A Practical Guide
  12. 12How to Build a Robust Professional Playwright Framework from Scratch (Step-by-Step)
  13. 13Building an Enterprise Playwright Framework from Scratch

API Testing Series

View all →
  1. 1Playwright API Testing: The Complete Guide with Real-World Examples
  2. 2Part 1 : Playwright API Testing Tutorial: Build Enterprise-Level API Automation Framework
  3. 3Part 2: Playwright API Testing Tutorial: Setting Up Project & Sending Your First API Request
  4. 4Part 3: Mastering CRUD Operations in Playwright API Testing
  5. 5Part 4: Authentication in Playwright API Testing (Bearer Token, JWT, API Key & Reusable Fixtures)
  6. 6Part 5: Building an Enterprise-Level Playwright API Automation Framework
  7. 7Part 6: API Models, Schema Validation & Test Data Management in Playwright
  8. 8Part 7: Custom Fixtures, Hooks, Logging & Parallel Execution in Playwright API Testing
  9. 9Part 8: Building a Production-Ready Playwright API Framework (Environment Management, CI/CD, Reporting & Best Practices)
  10. 10Part 9: Advanced Playwright API Testing Techniques for Enterprise Automation
  11. 11Part 10: Building a Complete Enterprise Playwright API Automation Framework (Final Part)
  12. 12API Testing with Playwright: Request Context, Auth, and Assertions

Recommended Next Articles