Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Microsoft Playwright Page RouteFromHAR

From Leeroopedia
Knowledge Sources
Domains Network_Testing, Mocking, HAR_Fixtures
Last Updated 2026-02-11 00:00 GMT

Overview

Concrete tool for recording and replaying HTTP responses from HAR files to create deterministic test fixtures, provided by the Playwright library.

Description

The page.routeFromHAR() method (packages/playwright-core/src/client/page.ts:L511-522) enables both recording and replaying of HTTP traffic using HAR (HTTP Archive) files. In replay mode, it intercepts network requests and fulfills them from a previously recorded HAR file. In recording mode, it captures live network traffic into a new HAR file for future replay.

The implementation involves three key components:

HarRouter (packages/playwright-core/src/client/harRouter.ts:L25-106) is the client-side router that integrates with Playwright's route system. Its _handle() method at L45-89 processes each intercepted request by:

  1. Extracting request properties (URL, method, headers, POST body, navigation status).
  2. Calling localUtils.harLookup() to search the HAR file for a matching entry.
  3. Handling the response action: 'redirect' triggers a navigation redirect, 'fulfill' serves the recorded response via route.fulfill(), and 'error' falls through to the notFound action.
  4. When no match is found, either aborting (route.abort()) or falling back (route.fallback()) based on the notFound configuration.

HarBackend (packages/playwright-core/src/server/harBackend.ts:L28-157) is the server-side component that performs the actual HAR entry matching. Its _harFindResponse() method at L91-152 matches requests by URL, method, headers, and POST body against HAR entries.

HarRecorder (referenced at harRecorder.ts:L34-103) handles the recording phase, using HarTracer to capture live traffic and flush() at L73-96 to write the HAR output as either a plain JSON file or a ZIP archive with attached response bodies.

When options.update is true, the method delegates to browserContext._recordIntoHAR() instead of replaying, which sets up the HarRecorder to capture traffic.

Usage

Use page.routeFromHAR() when:

  • You want to replay a previously recorded set of API responses for deterministic testing.
  • You need to record API traffic from a real server to create test fixtures.
  • You have many API endpoints and manually mocking each one with page.route() would be impractical.
  • You want to create snapshot-based network tests that can be re-recorded when the API changes.
  • You need to test offline scenarios by serving all network responses from a local HAR file.

Code Reference

Source Location

  • Repository: playwright
  • routeFromHAR: packages/playwright-core/src/client/page.ts:L511-522
  • HarRouter: packages/playwright-core/src/client/harRouter.ts:L25-106
  • HarBackend: packages/playwright-core/src/server/harBackend.ts:L28-157

Signature

page.routeFromHAR(
  har: string,
  options?: {
    url?: string | RegExp;
    notFound?: 'abort' | 'fallback';
    update?: boolean;
    updateContent?: 'attach' | 'embed';
    updateMode?: 'minimal' | 'full';
  }
): Promise<void>;

Import

// Playwright Test (recommended)
import { test, expect } from '@playwright/test';

// Library mode
import { chromium } from 'playwright';

I/O Contract

Inputs

Name Type Required Description
har string Yes Path to the HAR file. In replay mode, this file must exist and contain valid HAR data. In record mode (update: true), traffic will be written to this path.
options.url RegExp No URL pattern filter. Only requests matching this pattern will be served from the HAR file or recorded. Defaults to matching all requests (**/*).
options.notFound 'fallback' No Action when a matching HAR entry is not found. 'abort' (default) cancels the request. 'fallback' passes to the next route handler or the real network.
options.update boolean No When true, records live network traffic into the HAR file instead of replaying. Used to create or refresh fixtures.
options.updateContent 'embed' No Controls how response bodies are stored in the HAR file during recording. 'attach' stores bodies as separate files in a ZIP archive (reduces HAR file size for binary content). 'embed' inlines bodies as base64 in the HAR JSON.
options.updateMode 'full' No Controls the level of detail in the recorded HAR. 'minimal' records only essential request/response data. 'full' records comprehensive details including timing.

Outputs

Name Type Description
return Promise<void> Resolves when the HAR route is registered (replay mode) or recording is set up (record mode).
Replay behavior Implicit Matching requests are fulfilled with recorded responses via route.fulfill(). Non-matching requests are handled per notFound setting.
Recording output HAR file When update: true, a HAR file (or ZIP archive) is written to the specified path when the browser context closes, containing all captured network traffic.

Usage Examples

Basic Example: Replay from HAR File

import { test, expect } from '@playwright/test';

test('replay API responses from HAR', async ({ page }) => {
  // Serve network requests from the recorded HAR file
  await page.routeFromHAR('tests/fixtures/api-responses.har');

  await page.goto('https://example.com/dashboard');

  // The page will receive recorded responses instead of live API calls
  await expect(page.locator('.user-count')).toHaveText('42');
});

Record HAR Fixture

import { test, expect } from '@playwright/test';

test('record API responses to HAR file', async ({ page }) => {
  // Record live traffic into a HAR file
  await page.routeFromHAR('tests/fixtures/api-responses.har', {
    update: true,
    url: '**/api/**',  // Only record API calls
    updateContent: 'attach',  // Store bodies in a ZIP
    updateMode: 'minimal',
  });

  await page.goto('https://example.com/dashboard');
  await page.click('#load-more');
  await page.waitForLoadState('networkidle');

  // HAR file is written when the context closes
});

Filter by URL Pattern

import { test, expect } from '@playwright/test';

test('replay only specific API routes', async ({ page }) => {
  // Only intercept /api/ requests; let other requests through
  await page.routeFromHAR('tests/fixtures/api.har', {
    url: '**/api/**',
    notFound: 'fallback',  // Let unmatched requests go to the network
  });

  await page.goto('https://example.com');
  // Static assets load from the real server
  // API calls are served from the HAR file
});

Fallback for Unmatched Requests

import { test, expect } from '@playwright/test';

test('HAR with fallback to network', async ({ page }) => {
  // Use HAR for known responses, fall back to real network for new endpoints
  await page.routeFromHAR('tests/fixtures/baseline.har', {
    notFound: 'fallback',
  });

  await page.goto('https://example.com');
  // Known endpoints: served from HAR
  // New endpoints: fetched from real server
});

Combined with URL-Specific Regex Filter

import { test, expect } from '@playwright/test';

test('replay HAR for user endpoints only', async ({ page }) => {
  await page.routeFromHAR('tests/fixtures/users-api.har', {
    url: /\/api\/users/,
    notFound: 'abort',
  });

  // Mock other endpoints manually
  await page.route('**/api/config', route => {
    route.fulfill({ json: { theme: 'dark', locale: 'en' } });
  });

  await page.goto('https://example.com/users');
});

Related Pages

Implements Principle

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment