Table of contents

What are the different browser contexts and when should I use them?

Browser contexts in Playwright are isolated environments that allow you to run multiple independent browser sessions within a single browser instance. Think of them as separate "profiles" or "sandboxes" that don't share cookies, local storage, or other browser state. Understanding when and how to use different browser contexts is crucial for efficient web scraping, testing, and automation.

Understanding Browser Contexts

A browser context is essentially a logical separation layer that creates an isolated browsing environment. Each context maintains its own:

  • Cookies and session data
  • Local storage and session storage
  • Cache
  • Permissions and geolocation settings
  • Authentication state
  • Network interceptors

This isolation makes browser contexts perfect for scenarios where you need to simulate different users, test various authentication states, or prevent data contamination between different operations.

Types of Browser Contexts

1. Default Browser Context

When you launch a browser without explicitly creating a context, Playwright automatically creates a default context. This is the simplest approach for basic automation tasks.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage(); // Uses default context

  await page.goto('https://example.com');
  await page.screenshot({ path: 'example.png' });

  await browser.close();
})();
import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page()  # Uses default context

        await page.goto('https://example.com')
        await page.screenshot(path='example.png')

        await browser.close()

asyncio.run(main())

2. Explicit Browser Contexts

Creating explicit contexts gives you more control over the browsing environment and allows you to configure specific settings for each context.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();

  // Create a new context with specific settings
  const context = await browser.newContext({
    viewport: { width: 1920, height: 1080 },
    userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    locale: 'en-US',
    timezoneId: 'America/New_York'
  });

  const page = await context.newPage();
  await page.goto('https://example.com');

  await context.close();
  await browser.close();
})();
import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()

        # Create a new context with specific settings
        context = await browser.new_context(
            viewport={'width': 1920, 'height': 1080},
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            locale='en-US',
            timezone_id='America/New_York'
        )

        page = await context.new_page()
        await page.goto('https://example.com')

        await context.close()
        await browser.close()

asyncio.run(main())

3. Incognito/Private Contexts

Every context you create in Playwright is essentially "incognito" by default, as they don't share state with other contexts. However, you can explicitly configure contexts to behave like private browsing sessions.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();

  // Create multiple isolated contexts
  const context1 = await browser.newContext();
  const context2 = await browser.newContext();

  const page1 = await context1.newPage();
  const page2 = await context2.newPage();

  // These pages operate in complete isolation
  await page1.goto('https://example.com');
  await page2.goto('https://example.com');

  // Login in context1 won't affect context2
  await page1.fill('#username', 'user1');
  await page1.fill('#password', 'pass1');
  await page1.click('#login');

  // page2 will still see the login page

  await context1.close();
  await context2.close();
  await browser.close();
})();

When to Use Different Browser Contexts

1. Multi-User Testing

Use separate contexts when you need to simulate different users or test different authentication states simultaneously.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();

  // Admin user context
  const adminContext = await browser.newContext();
  const adminPage = await adminContext.newPage();

  // Regular user context
  const userContext = await browser.newContext();
  const userPage = await userContext.newPage();

  // Login as admin
  await adminPage.goto('https://app.example.com/login');
  await adminPage.fill('#username', 'admin');
  await adminPage.fill('#password', 'admin123');
  await adminPage.click('#login');

  // Login as regular user
  await userPage.goto('https://app.example.com/login');
  await userPage.fill('#username', 'user');
  await userPage.fill('#password', 'user123');
  await userPage.click('#login');

  // Test different permissions
  await adminPage.goto('https://app.example.com/admin');
  await userPage.goto('https://app.example.com/admin'); // Should be denied

  await adminContext.close();
  await userContext.close();
  await browser.close();
})();

2. Geographic and Locale Testing

Create contexts with different geographic settings to test location-based features, similar to how you might handle browser sessions in Puppeteer for different user scenarios.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();

  // US context
  const usContext = await browser.newContext({
    locale: 'en-US',
    timezoneId: 'America/New_York',
    geolocation: { latitude: 40.7128, longitude: -74.0060 },
    permissions: ['geolocation']
  });

  // UK context
  const ukContext = await browser.newContext({
    locale: 'en-GB',
    timezoneId: 'Europe/London',
    geolocation: { latitude: 51.5074, longitude: -0.1278 },
    permissions: ['geolocation']
  });

  const usPage = await usContext.newPage();
  const ukPage = await ukContext.newPage();

  await usPage.goto('https://example.com');
  await ukPage.goto('https://example.com');

  // Pages will see different localizations and locations

  await usContext.close();
  await ukContext.close();
  await browser.close();
})();

3. A/B Testing and Feature Flags

Use different contexts to test various configurations or feature flags without interference.

import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()

        # Context A: Feature enabled
        context_a = await browser.new_context(
            extra_http_headers={'X-Feature-Flag': 'enabled'}
        )

        # Context B: Feature disabled
        context_b = await browser.new_context(
            extra_http_headers={'X-Feature-Flag': 'disabled'}
        )

        page_a = await context_a.new_page()
        page_b = await context_b.new_page()

        await page_a.goto('https://example.com')
        await page_b.goto('https://example.com')

        # Test different feature states
        feature_a = await page_a.is_visible('#new-feature')
        feature_b = await page_b.is_visible('#new-feature')

        print(f"Feature visible in context A: {feature_a}")
        print(f"Feature visible in context B: {feature_b}")

        await context_a.close()
        await context_b.close()
        await browser.close()

asyncio.run(main())

4. Parallel Data Extraction

When scraping multiple pages or sites simultaneously, contexts prevent cookie and session conflicts, much like how you might run multiple pages in parallel with Puppeteer.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();

  const urls = [
    'https://site1.com',
    'https://site2.com',
    'https://site3.com'
  ];

  // Create separate contexts for each site
  const contexts = await Promise.all(
    urls.map(() => browser.newContext())
  );

  const pages = await Promise.all(
    contexts.map(context => context.newPage())
  );

  // Scrape all sites in parallel
  const results = await Promise.all(
    pages.map(async (page, index) => {
      await page.goto(urls[index]);
      return {
        url: urls[index],
        title: await page.title(),
        content: await page.textContent('body')
      };
    })
  );

  console.log(results);

  // Clean up
  await Promise.all(contexts.map(context => context.close()));
  await browser.close();
})();

Performance Considerations

Context Reuse

While contexts provide isolation, creating too many contexts can impact performance. Reuse contexts when possible:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();

  // Reuse the same context for multiple pages
  const page1 = await context.newPage();
  const page2 = await context.newPage();
  const page3 = await context.newPage();

  // Navigate to different pages
  await Promise.all([
    page1.goto('https://example1.com'),
    page2.goto('https://example2.com'),
    page3.goto('https://example3.com')
  ]);

  // Process pages...

  await context.close();
  await browser.close();
})();

Memory Management

Always close contexts when you're done with them to free up resources:

import asyncio
from playwright.async_api import async_playwright

async def scrape_with_context(browser, url):
    context = await browser.new_context()
    try:
        page = await context.new_page()
        await page.goto(url)
        data = await page.text_content('body')
        return data
    finally:
        await context.close()  # Always close context

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()

        urls = ['https://site1.com', 'https://site2.com', 'https://site3.com']

        # Process URLs with proper context management
        results = await asyncio.gather(
            *[scrape_with_context(browser, url) for url in urls]
        )

        await browser.close()

asyncio.run(main())

Best Practices

  1. Use explicit contexts for better control and configuration
  2. Create separate contexts for different users, locales, or test scenarios
  3. Reuse contexts when possible to improve performance
  4. Always close contexts to prevent memory leaks
  5. Configure contexts with appropriate settings for your use case
  6. Use context isolation to prevent data contamination between tests

Browser contexts are one of Playwright's most powerful features for creating robust, isolated automation scenarios. Whether you're testing multi-user applications, scraping data from multiple sources, or running parallel test suites, understanding how to effectively use browser contexts will significantly improve your automation workflows.

Try WebScraping.AI for Your Web Scraping Needs

Looking for a powerful web scraping solution? WebScraping.AI provides an LLM-powered API that combines Chromium JavaScript rendering with rotating proxies for reliable data extraction.

Key Features:

  • AI-powered extraction: Ask questions about web pages or extract structured data fields
  • JavaScript rendering: Full Chromium browser support for dynamic content
  • Rotating proxies: Datacenter and residential proxies from multiple countries
  • Easy integration: Simple REST API with SDKs for Python, Ruby, PHP, and more
  • Reliable & scalable: Built for developers who need consistent results

Getting Started:

Get page content with AI analysis:

curl "https://api.webscraping.ai/ai/question?url=https://example.com&question=What is the main topic?&api_key=YOUR_API_KEY"

Extract structured data:

curl "https://api.webscraping.ai/ai/fields?url=https://example.com&fields[title]=Page title&fields[price]=Product price&api_key=YOUR_API_KEY"

Try in request builder

Related Questions

Get Started Now

WebScraping.AI provides rotating proxies, Chromium rendering and built-in HTML parser for web scraping
Icon