Skip to main content

Overview

Playwright’s network interception allows you to intercept, modify, mock, or block network requests. This is essential for testing edge cases, simulating API responses, and controlling network conditions.

Basic Request Interception

Intercept and handle network requests using the route API.
import { test, expect } from '@playwright/test';

test('intercept API request', async ({ page }) => {
  // Intercept all API calls
  await page.route('**/api/**', route => {
    console.log('Request URL:', route.request().url());
    route.continue();
  });
  
  await page.goto('https://example.com');
});

Mock API Responses

Return mock data instead of making real API requests.
import { test, expect } from '@playwright/test';

test('mock API response', async ({ page }) => {
  await page.route('**/api/users', route => {
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify([
        { id: 1, name: 'John Doe' },
        { id: 2, name: 'Jane Smith' },
      ]),
    });
  });
  
  await page.goto('https://example.com');
  
  // Verify mocked data appears
  await expect(page.locator('text=John Doe')).toBeVisible();
});

Modify Requests

Change request properties before they are sent.
import { test } from '@playwright/test';

test('add custom headers', async ({ page }) => {
  await page.route('**/api/**', route => {
    const headers = {
      ...route.request().headers(),
      'X-Custom-Header': 'custom-value',
      'Authorization': 'Bearer token123',
    };
    
    route.continue({ headers });
  });
  
  await page.goto('https://example.com');
});

Modify Responses

Fetch the real response and modify it before returning.
import { test } from '@playwright/test';

test('modify API response', async ({ page }) => {
  await page.route('**/api/users', async route => {
    // Fetch the original response
    const response = await route.fetch();
    const json = await response.json();
    
    // Modify the data
    const modified = json.map(user => ({
      ...user,
      modified: true,
    }));
    
    // Return modified response
    route.fulfill({
      response,
      json: modified,
    });
  });
  
  await page.goto('https://example.com');
});

Request Information

Access detailed information about intercepted requests.
Inspect Requests
import { test } from '@playwright/test';

test('log request details', async ({ page }) => {
  await page.route('**/*', route => {
    const request = route.request();
    
    console.log('URL:', request.url());
    console.log('Method:', request.method());
    console.log('Headers:', request.headers());
    console.log('Post Data:', request.postData());
    console.log('Resource Type:', request.resourceType());
    console.log('Is Navigation:', request.isNavigationRequest());
    
    route.continue();
  });
  
  await page.goto('https://example.com');
});

Context-Level Interception

Intercept requests for all pages in a context.
Context Routes
import { test } from '@playwright/test';

test('intercept at context level', async ({ context, page }) => {
  // Apply to all pages in the context
  await context.route('**/api/**', route => {
    route.fulfill({
      json: { mocked: true },
    });
  });
  
  await page.goto('https://example.com');
  
  // Open another page - routing still applies
  const page2 = await context.newPage();
  await page2.goto('https://example.com');
});

Conditional Interception

Apply different handling based on request properties.
Conditional Routing
import { test } from '@playwright/test';

test('conditional interception', async ({ page }) => {
  await page.route('**/api/**', route => {
    const request = route.request();
    
    // Different handling based on method
    if (request.method() === 'POST') {
      route.fulfill({ json: { created: true } });
    } else if (request.method() === 'DELETE') {
      route.fulfill({ status: 204 });
    } else {
      route.continue();
    }
  });
  
  await page.goto('https://example.com');
});

test('intercept based on headers', async ({ page }) => {
  await page.route('**/api/**', route => {
    const request = route.request();
    const headers = request.headers();
    
    if (headers['authorization']) {
      // Allow authenticated requests
      route.continue();
    } else {
      // Block unauthorized requests
      route.fulfill({ status: 401, body: 'Unauthorized' });
    }
  });
  
  await page.goto('https://example.com');
});

Abort Requests

Block specific requests to test offline scenarios or reduce load times.
import { test } from '@playwright/test';

test('simulate network failure', async ({ page }) => {
  await page.route('**/api/users', route => {
    route.abort('failed');
  });
  
  await page.goto('https://example.com');
  // Test how app handles failed requests
});

HAR Recording and Replay

Record network traffic to HAR files and replay them later.
import { test } from '@playwright/test';

test('record network traffic', async ({ context, page }) => {
  // Start recording
  await context.routeFromHAR('recordings/network.har', {
    update: true,
  });
  
  await page.goto('https://example.com');
  // All network traffic is recorded
});

Unroute

Remove route handlers when no longer needed.
Remove Routes
import { test } from '@playwright/test';

test('remove route handler', async ({ page }) => {
  const handler = route => route.fulfill({ json: { mocked: true } });
  
  // Add route
  await page.route('**/api/data', handler);
  
  await page.goto('https://example.com');
  // Uses mocked data
  
  // Remove route
  await page.unroute('**/api/data', handler);
  
  await page.reload();
  // Uses real API now
});

test('remove all routes', async ({ page }) => {
  await page.route('**/api/**', route => route.continue());
  
  // Remove all routes
  await page.unrouteAll({ behavior: 'wait' });
});

Best Practices

Pattern Specificity

Use specific patterns to avoid unintended interceptions. Match exact endpoints when possible.

Error Handling

Always test both success and failure scenarios. Mock error responses to test error handling.

Performance

Use network mocking to speed up tests by avoiding slow external APIs.

Realistic Mocks

Keep mock data realistic and up-to-date with actual API responses.

Network Events

Monitor and analyze network activity

API Testing

Test APIs directly with APIRequestContext

Build docs developers (and LLMs) love