📖 The Story: The 50-Endpoint Nightmare

An analytics company was building a complex dashboard. The frontend pulled data from 15 different microservices. To test the UI, the QA team spent three days writing page.route() mocks for every single endpoint—user profiles, billing stats, chart data, and notifications.

It worked perfectly until the backend team updated the API schema. Suddenly, the QA team's mocks were out of date. The tests passed, but the frontend broke in production because the real API payload structure had changed, and the mocks didn't reflect it.

The QA lead spent another two days updating the mock JSON files manually. It was a nightmare.

Then they discovered HAR (HTTP Archive) files. They logged into the staging site, clicked around the dashboard for two minutes, and exported a .har file. They replaced 500 lines of mock code with a single line: page.routeFromHAR('dashboard.har'). When the backend changed again, they just re-recorded the HAR file in 2 minutes. The nightmare was over.

Manual mocks are for testing specific edge cases. HAR files are for testing real-world accuracy.

🎯 Why Use HAR Files?

Instant Mocking

Mock an entire microservice architecture in seconds without writing a line of code.

🎯

100% Accuracy

Replay exact headers, cookies, and JSON payloads from a real server response.

🔌

Offline Testing

Run your entire frontend test suite without an internet connection or a running backend.

🔄

Easy Updates

When the API changes, just re-record the HAR file. No digging through JSON mock files.

🌍 Real World Example

Imagine a mapping application. To test the UI, you need map tiles, traffic data, and search results. Manually mocking a GeoJSON response for traffic is incredibly tedious. With HAR, you just open the app, search for "New York", and save the HAR. Now your test can run that exact search offline, over and over, instantly.

🧒 Explain Like I'm 10

Imagine you want to practice singing a duet with your favorite singer. But the singer is busy and can't be there every day.

So, you record them singing their part on a tape recorder. The next day, you press "Play" on the tape, and you sing your part along with it. You don't need the real singer to be there; the tape is enough.

A HAR file is that tape recorder. It records the server singing its part, so your frontend test can practice without the real server being there.

🎓 Professional Explanation

A HAR (HTTP Archive) file is a JSON-formatted archive file that logs a web browser's interaction with a server. It contains every request, response, header, cookie, and timing metric. Playwright provides page.routeFromHAR(), which intercepts network requests and serves the corresponding responses from the HAR file.

If the HAR file contains a response for /api/users, Playwright serves it instantly. If it doesn't, Playwright can either fall back to the real network (non-strict mode) or fail the test (strict mode).

📊 Manual Mocking vs HAR

The Shift from Code to Data

Manual Mocking (Code)
Write route() for /api/users
Write route() for /api/billing
Write route() for /api/settings
⬇️
Maintain 500+ lines of JSON
HAR Replaying (Data)
Record network traffic via CLI
Save as dashboard.har
⬇️
page.routeFromHAR('dashboard.har')
All 15 endpoints mocked instantly!

🎥 Recording a HAR File

You can record a HAR file directly from your terminal using the Playwright CLI. This opens a real browser window.

bash
# Opens a browser and records all network traffic
# Save it to a file named 'app.har'
npx playwright open --save-har=app.har https://your-staging-app.com

Once you click around the app and close the browser, Playwright will serialize all the network traffic into app.har. You can also record HAR files directly inside VS Code using the Playwright extension.

▶️ Replaying Traffic with routeFromHAR()

Now, replace your manual mocks with the HAR file.

typescript
test('dashboard loads user data', async ({ page }) => {
  // Replay the HAR file. 
  // Only intercept requests starting with /api/
  await page.routeFromHAR('har/app.har', {
    url: '**/api/**',
    // update: false (default) means it will NOT hit the real network
  });

  // Navigate to the page
  await page.goto('https://your-staging-app.com/dashboard');

  // The UI renders using the mocked data from the HAR file
  await expect(page.getByText('Welcome, Alex')).toBeVisible();
});

🔒 Strict Mode (Fail Fast)

If a frontend developer adds a new API call that isn't in your HAR file, non-strict mode will silently let it pass through to the real network (which might fail or behave unpredictably). Strict mode ensures your test fails if the HAR doesn't have the exact response.

typescript
await page.routeFromHAR('har/app.har', {
  url: '**/api/**',
  // If a request is made that isn't in the HAR, abort it!
  update: false, 
});

Wait, update: false is the default behavior and acts as strict mode (it serves from HAR, and if not found, it panics/fails). If you set update: true, Playwright will actually hit the real network, fetch the response, and append it to your HAR file. This is useful for updating your HAR file on the fly.

⚠️ Common Mistakes

Mistake 1: Committing Massive HAR Files to Git

HAR files can be 5MB to 50MB depending on the traffic. Committing these to Git will bloat the repository forever. Add *.har to your .gitignore and store them in cloud storage (S3) or fetch them dynamically in CI.

Mistake 2: Recording Sensitive Data

HAR files capture everything, including Authorization headers and session cookies. If you record a HAR on a staging environment, your tokens are saved in plain text. Playwright provides a --har-include-credentials flag, but by default, it tries to strip sensitive headers. Always double-check your HAR files before sharing them.

Mistake 3: Mocking Dynamic Endpoints

If your app generates a unique timestamp URL (e.g., /api/time/1707500000), the HAR file will only have that specific timestamp. Subsequent runs with different times will fail. Use page.route() for dynamic endpoints, and HAR for static/predictable ones.

✅ Best Practices

  1. Scope your HAR. Use the url filter to only mock /api/ traffic. Let CSS, images, and JS load from the real server or local dev environment.
  2. Re-record periodically. A HAR file is a snapshot in time. Set a reminder to re-record it every sprint to capture backend schema changes.
  3. Use HAR for "Happy Path" tests. It's perfect for testing that the dashboard renders correctly with typical data. Use manual route.fulfill() for testing 500 errors or empty states.
  4. Zip your HAR files. HAR files are JSON and compress incredibly well. A 10MB HAR file zips down to 1MB.

🏗️ Senior Engineer Deep Dive

HAR vs. MSW (Mock Service Worker)

MSW (Mock Service Worker) is a popular alternative where mocks are defined in code and intercepted by a Service Worker in the browser. While MSW is great for local dev, HAR files are superior for E2E testing because they require zero code maintenance and capture 100% accurate payloads. Playwright handles the interception at the network level, so it works across all browsers (even WebKit, where Service Workers can be finicky).

How Playwright Replays

When routeFromHAR is called, Playwright reads the JSON file into memory. It builds a hashmap of request URLs (and sometimes POST bodies) mapped to responses. When the browser makes a request, Playwright intercepts it via CDP, checks the hashmap, and if found, synthesizes a fake HTTP response stream from the JSON data. This is why it's nearly instantaneous.

💼 Interview Questions

Beginner
What is a HAR file?
Show Answer
A HAR (HTTP Archive) file is a JSON-formatted log of network requests and responses between a browser and a server. It contains headers, cookies, and response bodies.
Intermediate
How do you use a HAR file to mock APIs in Playwright?
Show Answer
I use the page.routeFromHAR('file.har') method. I pass the path to the HAR file and an optional URL filter. Playwright automatically intercepts matching requests and serves the recorded responses from the file.
Advanced
What is the difference between update: true and update: false in routeFromHAR?
Show Answer
update: false (default) strictly serves from the HAR file; if a request isn't found, it fails or passes through depending on the setup. update: true allows Playwright to hit the real network for missing requests, fetch the response, and append it to the HAR file, effectively updating the archive on the fly.
Scenario
Your frontend team needs to test a dashboard that pulls from 20 microservices, but the backend is highly unstable. How do you solve this?
Show Answer
I would use the Playwright CLI to record a HAR file against the backend during a brief window when it is working. Then, I would configure the Playwright tests to use routeFromHAR. This allows the frontend tests to run 100% offline, completely isolated from the backend's instability.

🏋️ Practical Exercise

🎯 Hands-On Practice Easy

Record and Replay

  1. Run npx playwright open --save-har=test.har https://demo.playwright.dev/todomvc
  2. Add a few todo items in the browser, then close it.
  3. Write a Playwright test that calls page.routeFromHAR('test.har').
  4. Navigate to the TodoMVC app and assert that the todos you added in step 2 appear instantly without making a real network request.

🚀 Mini Project

🏗️ The Offline E-Commerce Suite

  1. Find a public e-commerce demo site (e.g., saucedemo.com).
  2. Record a HAR file of the login process and the inventory page.
  3. Strip out any image traffic (filter by **/api/**).
  4. Write a test suite that runs entirely offline using only the HAR file.
  5. Verify that you can disconnect your computer from the internet and the tests still pass.

📝 Quiz

Test your understanding. Click an option to check your answer.

1. What does HAR stand for?
A) High-level API Record
B) HTTP Archive
C) Hardware Address Routing
D) Hypermedia Application Resource
Answer: B — HAR stands for HTTP Archive, a JSON format for recording network traffic.
2. Which Playwright method is used to mock APIs using a HAR file?
A) page.route()
B) page.mockHar()
C) page.routeFromHAR()
D) page.replayHar()
Answer: C — routeFromHAR reads the file and intercepts network requests automatically.
3. How do you record a HAR file via CLI?
A) npx playwright record --har=file.har
B) npx playwright open --save-har=file.har
C) npx playwright har --save=file.har
D) npx playwright codegen --har=file.har
Answer: B — The --save-har flag tells the open command to save traffic to a file.
4. What is a major benefit of HAR mocking over manual page.route() mocking?
A) It runs faster.
B) It allows testing 500 errors easily.
C) It captures 100% accurate payloads without writing code.
D) It works in CI.
Answer: C — You don't have to write JSON payloads by hand; it records real server responses.
5. What happens if update: true is set in routeFromHAR?
A) It updates the Playwright version.
B) It fetches missing responses from the real network and appends them to the HAR.
C) It overwrites the HAR with empty data.
D) It forces the test to run in headed mode.
Answer: B — It allows Playwright to hit the real network to update the HAR file dynamically.
6. Why should you be careful about committing HAR files to Git?
A) Git doesn't support JSON files.
B) They can be massive (10MB+) and bloat the repository.
C) They contain compiled binaries.
D) They expire after 30 days.
Answer: B — HAR files can be very large and should ideally be stored in cloud storage or LFS.
7. What security risk exists with HAR files?
A) They can execute malicious scripts.
B) They can contain sensitive data like Authorization tokens and cookies.
C) They expose your IP address to hackers.
D) They bypass firewall rules.
Answer: B — HAR files record headers and cookies in plain text, which can leak secrets.
8. How can you prevent a HAR file from mocking image requests?
A) Delete the images from the HAR file manually.
B) Use the url: '**/api/**' filter so only API calls are mocked.
C) Set mockImages: false.
D) You cannot; HAR mocks everything or nothing.
Answer: B — Filtering by URL ensures only matching requests (like /api/) are intercepted.
9. Does routeFromHAR work for testing edge cases like 500 Internal Server Errors?
A) Yes, it's the best tool for it.
B) No, you should use manual page.route() to easily mock 500 errors.
C) Yes, but you have to manually edit the HAR JSON.
D) No, HAR files only record 200 OK responses.
Answer: B — While you *can* edit the HAR JSON, it's much easier to use page.route() for specific error states.
10. Are HAR files dynamic?
A) Yes, they update automatically.
B) No, they are a static snapshot of network traffic at the time of recording.
C) Yes, they execute JavaScript to generate responses.
D) Only if stored in the cloud.
Answer: B — HAR files are static. If the API changes, you must re-record the HAR.

❓ FAQ

Q: Can I edit a HAR file?

A: Yes, it's just JSON. You can open it in VS Code, find the response body you want to change, and edit it. However, for complex changes, manual route.fulfill() is usually easier to maintain.

Q: Does HAR mocking work with WebSockets?

A: No, standard HAR files only support HTTP/HTTPS requests. WebSockets are not recorded in standard HAR archives.

📦 Summary

🎯 Key Takeaways

  • HAR files are JSON archives of real network traffic.
  • Use page.routeFromHAR() to replay traffic and mock entire APIs instantly.
  • Record via CLI using --save-har=file.har.
  • Filter by URL (e.g., **/api/**) to avoid mocking static assets.
  • Don't commit massive HAR files to Git due to repository bloat and security risks.
  • Use HAR for "Happy Path" testing, and manual mocks for error states.