PRACTICAL GUIDE / playwright HAR mocking

Deterministic Network Tests with Playwright HAR Recording and Replay

Record, sanitize, and replay Playwright HAR fixtures for deterministic network tests, strict request matching, safer updates, and clear failures.

By The Testing AcademyUpdated July 11, 20269 min read
All field guides
In this guide10 sections
  1. Decide What the HAR Is Supposed to Prove
  2. Capture the Smallest Useful Traffic Set
  3. Sanitize Before the Fixture Enters Source Control
  4. Understand Strict Request Matching
  5. Replay With a Closed Network Boundary
  6. Keep Fixture Updates Deliberate
  7. Diagnose HAR Replay Failures
  8. Weigh HAR Against Other Network Strategies
  9. Operational Checklist
  10. Action Plan

What you will learn

  • Decide What the HAR Is Supposed to Prove
  • Capture the Smallest Useful Traffic Set
  • Sanitize Before the Fixture Enters Source Control
  • Understand Strict Request Matching

HAR replay is valuable when a UI needs a realistic cluster of API responses but the test must not depend on a live service. It is not a button that makes arbitrary network traffic deterministic. A trustworthy HAR fixture is narrow, sanitized, reviewed, and replayed under strict matching so unexpected requests fail visibly.

Use HAR for coherent conversations such as catalog load, search suggestions, and product details that must agree with one another. Use ordinary route handlers for isolated responses and live integration tests for contracts that need current server behavior. That division keeps recordings understandable and prevents old traffic from impersonating broad API coverage.

Decide What the HAR Is Supposed to Prove

Define the user-visible behavior and the network boundary before recording. A catalog test might prove that three products render, pagination uses the recorded cursor, and a product detail opens from the same fixture. It should not claim that the staging catalog API is healthy, because replay deliberately removes that dependency.

The official Playwright API mocking guide describes the workflow as recording a HAR, keeping it with the tests, and routing matching requests from it. The same guide notes that HAR includes request and response metadata, cookies, content, and timing information. Treat the fixture as captured data, not harmless generated output.

Animated field map

Governed HAR Capture and Replay

A limited slice of real traffic becomes a reviewed fixture, then serves matching requests while UI assertions remain independent of the live API.

  1. 01 / real api traffic

    Real API traffic

    Exercise one known scenario against a controlled source environment.

  2. 02 / har capture

    HAR capture

    Record only the endpoint family needed by the user journey.

  3. 03 / fixture sanitization

    Fixture sanitization

    Remove secrets, personal data, unstable fields, and irrelevant entries.

  4. 04 / route replay

    Route replay

    Serve strict URL, method, and payload matches without updating in CI.

  5. 05 / ui assertion

    Deterministic UI assertion

    Verify rendering and interaction against the reviewed response set.

Capture the Smallest Useful Traffic Set

Apply a URL filter for the API family under test. Capturing every document, image, analytics beacon, and identity request makes the artifact large and introduces secrets with no test value. It also makes a supposedly offline test fail when an unrelated URL changes.

One practical workflow uses routeFromHAR in update mode only when an explicit variable is present. The test performs the normal journey against a controlled environment, and Playwright writes the traffic when the context closes.

TypeScript
import { expect, test } from "@playwright/test";
import path from "node:path";

const catalogHar = path.join(__dirname, "fixtures", "catalog.har");
const updateHar = process.env.UPDATE_HAR === "1";

test("renders the recorded catalog", async ({ page }) => {
  await page.routeFromHAR(catalogHar, {
    url: "**/api/catalog/**",
    update: updateHar,
  });

  await page.goto("/catalog");
  await expect(page.getByRole("heading", { name: "Catalog" })).toBeVisible();
  await expect(page.getByTestId("product-card")).toHaveCount(3);
  await page.getByRole("link", { name: "Field Recorder" }).click();
  await expect(page.getByText("Available for dispatch")).toBeVisible();
});

Run fixture refresh through a named local command and keep normal runs in replay mode:

Shell
UPDATE_HAR=1 npx playwright test tests/catalog.har.spec.ts --project=chromium
npx playwright test tests/catalog.har.spec.ts --project=chromium

The refresh account and source data should be reproducible. If the recorder sees random inventory, timestamps, or tenant data, the fixture will churn and reviewers cannot distinguish expected contract updates from unrelated noise.

Sanitize Before the Fixture Enters Source Control

Start with prevention: use a non-sensitive account, limit the URL glob, and turn off unrelated integrations. Then inspect the HAR as structured JSON. Search request and response headers for authorization, cookies, API keys, and tracing identifiers. Inspect bodies for email addresses, names, tokens, internal hostnames, and data covered by retention policy.

Prefer an allowlist of fields that the UI requires over a growing list of redaction patterns. If the response has twenty customer fields but the component uses three, capture a synthetic test record or replace the payload with a minimal reviewed body. Redaction that changes a POST body must preserve matching with the request the browser will send.

Keep the sanitizer in a separate tooling workflow and fail if forbidden header names remain. Do not print their values during validation. A clean git diff should show intentional endpoint or payload changes, not generated timestamps and opaque identifiers across hundreds of lines.

Understand Strict Request Matching

HAR replay matches URL and method strictly; POST payloads are also part of matching. Query parameter order, generated request IDs, timestamps, GraphQL variables, and random idempotency keys can therefore turn a valid-looking recording into "no matching entry." Multiple matching entries are resolved using matching headers, which is another reason to remove unstable or secret headers from the design.

Normalize dynamic inputs before they reach the network when that behavior is not under test. For example, inject a fixed search term and known page cursor instead of trying to wildcard a recorded POST body. If requests are inherently dynamic, a page.route() handler can parse the request and return a controlled response more clearly than editing many nearly identical HAR entries.

Redirect chains need all relevant responses available. Binary or large payloads may be stored alongside an archive rather than embedded in one readable file. Keep the HAR and its companion content together, and verify the fixture from a clean checkout so local untracked payloads cannot make the test pass.

Replay With a Closed Network Boundary

Register routeFromHAR before navigation or before the action that initiates requests. Use the narrow URL option during replay as well as capture. Requests in that scope without a matching entry should fail rather than fall through to the live API, because fallback hides fixture gaps and makes results depend on network availability.

Unrelated first-party traffic may remain live by design, but state that boundary in the test. If the goal is true offline UI behavior, block all non-recorded application requests and assert the offline indicator or cached experience. If the goal is only deterministic catalog data, do not call the entire test offline when fonts and authentication still use the network.

Service Workers can intercept traffic before Playwright routing sees it. The Playwright network guide recommends blocking Service Workers when route events appear to be missing. Apply that setting only with an understanding of the product behavior: a Progressive Web App test may need the Service Worker and therefore a different mocking level.

Keep Fixture Updates Deliberate

Never let the routine CI replay job set update: true. A transient backend response could silently rewrite the expected fixture, and a compromised response could enter artifacts without review. Provide a separate refresh command, protected credentials, a known source environment, and required code review of the HAR diff.

Record the reason for refresh in the change description: API contract update, planned sample-data change, or newly covered request. After updating, run once with network access disabled for the captured scope. That second run proves responses came from the fixture rather than a leftover live connection.

Assign ownership and an expiry review date. HAR files do not announce that they represent an obsolete contract. A test may stay green while the live application has changed if both the UI bundle and fixture are old or if the path no longer covers current integration behavior.

Diagnose HAR Replay Failures

When a request aborts, compare its full URL, method, and POST body with the recording. Do not immediately regenerate the HAR; that erases the evidence of why matching changed. Dynamic query values and payload timestamps are frequent causes. A newly added endpoint may indicate a real UI contract change that deserves an assertion.

If the UI displays empty content with successful replay, inspect the response body attachment and content encoding. The entry may reference a missing companion file, or sanitization may have broken JSON shape. If replay unexpectedly reaches the network, verify the URL glob matches the entire intended URL and that routing was installed before the request. For invisible requests, inspect Service Worker behavior.

Flakiness can also come from multiple similar entries. If the same request appears several times with differing headers or responses, reduce the scenario or make each request distinct. A deterministic fixture should not depend on accidental header similarity to select the right business state.

Weigh HAR Against Other Network Strategies

HAR provides realistic groups of responses with little hand-authored mocking code. The cost is opaque matching, sensitive captured data, and maintenance when contracts evolve. Hand-written routes are explicit and excellent for errors, latency, and dynamic predicates, but large response graphs become tedious. Live APIs offer the strongest current integration signal while introducing data, availability, and timing variability.

A balanced suite uses each intentionally: routes for focused edge cases, HAR for stable multi-request UI scenarios, contract tests for schema compatibility, and a small live end-to-end path for deployment confidence. No single layer replaces the others.

Operational Checklist

  • Define the exact UI behavior and endpoint family the HAR supports.
  • Capture with a dedicated account and narrow URL filter.
  • Review headers, cookies, query strings, and bodies for sensitive data.
  • Stabilize request URLs and POST payloads used for matching.
  • Register replay before navigation or the triggering action.
  • Abort unmatched in-scope requests instead of silently using the live API.
  • Keep update mode out of routine CI execution.
  • Review fixture diffs and rerun replay without the source API.
  • Verify archives and companion payloads from a clean checkout.
  • Reassess HAR ownership when the API contract or UI flow changes.

Action Plan

Choose one read-only journey that currently fails when a dependency is unstable. Capture only its API family, replace source data with a controlled test record, and inspect every stored header and body. Replay with updates disabled and force unmatched requests to surface. Add one assertion for the expected record and one for a secondary request in the flow. Finally, document the refresh command and reviewer responsibilities so the HAR remains a governed fixture rather than an unexplained snapshot.

// LIVE COURSE / THE TESTING ACADEMY

Playwright Automation Mastery

Go beyond Selenium. Master Playwright with JS/TS in 90 days.

From the instructor behind this guide.

Playwright jobs are growing 8x faster than Selenium. 90 days / 75+ live hrs / Tue-Thu-Sat 7 AM IST.

Code PROMODE / 10% offJoin the batch

The Testing Academy editorial desk

Practical QA guidance built around test evidence, production tradeoffs, and interview-ready explanations.

Published July 11, 2026 / Reviewed July 11, 2026

PRIMARY REFERENCES

Verify the details at the source

QABattle guides are practical explanations. Product behavior, standards, and APIs can change, so use these primary references for the canonical details.

  1. 01
    Playwright documentation

    Microsoft

    Canonical API, locator, fixture, browser, and test-runner behavior.

  2. 02
    Playwright best practices

    Microsoft

    Official guidance for resilient tests, isolation, and user-facing locators.

  3. 03
    HTTP Semantics

    IETF

    The normative semantics for HTTP methods, status codes, and fields.

FAQ / QUICK ANSWERS

Questions testers ask

What does Playwright HAR mocking record?

A HAR can contain request and response URLs, methods, headers, cookies, timings, and payload content for captured traffic. Limit the capture scope and review the artifact because it may include credentials or personal data.

How does routeFromHAR match a browser request?

Playwright matches URL and HTTP method strictly, and it also matches POST payloads for POST requests. When several entries match, header similarity helps select the response, so unstable inputs can make replay fail or choose an unintended entry.

Should HAR files be updated automatically in CI?

Usually no. Replay should be read-only in CI so upstream drift causes a visible review failure. Regenerate fixtures through a deliberate, authenticated workflow and inspect the diff before merging it.

Can Playwright replay a HAR without access to the real API?

Yes, when every routed request has a matching recorded entry and its response content is available. Keep unrelated traffic outside the HAR route so fonts, analytics, or other services do not create accidental offline dependencies.

When is a hand-written Playwright route better than HAR replay?

Use a hand-written route for one or two responses, highly dynamic request matching, or precise fault injection. HAR replay is more useful when a realistic page flow depends on a coherent group of recorded exchanges.