Skip to main content

Overview

Browser contexts provide isolated browser environments. This guide covers advanced context features like permissions, geolocation, timezone emulation, offline mode, and more.

Permissions

Grant or deny browser permissions for specific origins to test permission-dependent features.
import { test, expect } from '@playwright/test';

test('grant geolocation permission', async ({ context, page }) => {
  // Grant geolocation permission
  await context.grantPermissions(['geolocation']);
  
  await page.goto('https://example.com');
  // Now the site can access geolocation
});

test('grant permissions for specific origin', async ({ context, page }) => {
  // Grant permissions only for a specific origin
  await context.grantPermissions(['camera', 'microphone'], {
    origin: 'https://example.com',
  });
  
  await page.goto('https://example.com');
  // Camera and microphone are allowed for this origin
});

Available Permissions

Allow access to device location.
Allow access to MIDI devices.
Allow showing notifications.
Allow access to camera.
Allow access to microphone.
Allow reading from clipboard.
Allow writing to clipboard.
Allow registering payment handlers.

Geolocation

Emulate device geolocation to test location-based features.
import { test, expect } from '@playwright/test';

test('set geolocation', async ({ context, page }) => {
  // Set geolocation to San Francisco
  await context.setGeolocation({
    latitude: 37.7749,
    longitude: -122.4194,
  });
  
  await context.grantPermissions(['geolocation']);
  await page.goto('https://maps.google.com');
  
  // Verify location is set correctly
});

Offline Mode

Simulate offline network conditions to test application behavior without connectivity.
Offline Mode
import { test, expect } from '@playwright/test';

test('test offline behavior', async ({ context, page }) => {
  await page.goto('https://example.com');
  
  // Go offline
  await context.setOffline(true);
  
  // Try to navigate (should fail or show offline page)
  await page.goto('https://another-site.com').catch(() => {
    // Navigation will fail when offline
  });
  
  // Verify offline behavior
  await expect(page.locator('.offline-message')).toBeVisible();
  
  // Go back online
  await context.setOffline(false);
  
  await page.goto('https://another-site.com');
  // Should work now
});

Timezone Emulation

Emulate different timezones to test time-sensitive features.
Timezone Configuration
import { test, expect } from '@playwright/test';

test.use({
  timezoneId: 'America/New_York',
});

test('test with EST timezone', async ({ page }) => {
  await page.goto('https://example.com');
  
  const timezone = await page.evaluate(() => {
    return Intl.DateTimeFormat().resolvedOptions().timeZone;
  });
  
  expect(timezone).toBe('America/New_York');
});

Locale and Language

Emulate different locales and languages for internationalization testing.
import { test } from '@playwright/test';

test.use({
  locale: 'de-DE',
  timezoneId: 'Europe/Berlin',
});

test('test German locale', async ({ page }) => {
  await page.goto('https://example.com');
  
  // Page will render in German
  const lang = await page.evaluate(() => navigator.language);
  expect(lang).toBe('de-DE');
});

HTTP Authentication

Provide HTTP authentication credentials for protected resources.
HTTP Credentials
import { test } from '@playwright/test';

test.use({
  httpCredentials: {
    username: 'admin',
    password: 'secret',
  },
});

test('access protected resource', async ({ page }) => {
  await page.goto('https://example.com/protected');
  // Credentials are automatically sent
});

test('change credentials during test', async ({ context, page }) => {
  await page.goto('https://example.com/protected');
  
  // Change credentials
  await context.setHTTPCredentials({
    username: 'user2',
    password: 'password2',
  });
  
  await page.goto('https://example.com/other-protected');
  
  // Clear credentials
  await context.setHTTPCredentials(null);
});

Extra HTTP Headers

Add custom HTTP headers to all requests in the context.
Custom Headers
import { test } from '@playwright/test';

test('add custom headers', async ({ context, page }) => {
  await context.setExtraHTTPHeaders({
    'X-API-Key': 'your-api-key',
    'X-Custom-Header': 'custom-value',
  });
  
  await page.goto('https://api.example.com');
  // All requests will include the custom headers
});

Storage State

Save and restore browser context state including cookies and local storage.
import { test } from '@playwright/test';

test('save authentication state', async ({ page, context }) => {
  await page.goto('https://example.com/login');
  await page.fill('#username', 'user');
  await page.fill('#password', 'pass');
  await page.click('#submit');
  
  // Wait for authentication
  await page.waitForURL('**/dashboard');
  
  // Save storage state
  await context.storageState({ path: 'auth.json' });
});

Service Workers

Access and interact with service workers in the context.
Service Workers
import { test, expect } from '@playwright/test';

test('interact with service worker', async ({ context, page }) => {
  await page.goto('https://example.com');
  
  // Wait for service worker
  const serviceWorker = await context.waitForEvent('serviceworker');
  
  console.log('Service worker URL:', serviceWorker.url());
  
  // Get all service workers
  const workers = context.serviceWorkers();
  expect(workers.length).toBeGreaterThan(0);
});

Best Practices

Isolation

Use separate contexts for tests requiring different browser states. Each context is completely isolated.

Performance

Reuse contexts when possible, but create new ones when state needs to be reset completely.

Permissions

Always grant necessary permissions before navigating to pages that require them.

Cleanup

Contexts are automatically closed, but explicitly close them when done for clarity.

Browser Context Basics

Learn the fundamentals of browser contexts

Authentication

Advanced authentication patterns

Build docs developers (and LLMs) love