Advanced API Mocking & HAR — The Time Machine
Writing manual mocks for 50 microservices is a nightmare. Learn how to record real network traffic into a HAR file and replay it instantly, creating a 100% accurate, offline-testable frontend environment.
📖 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)
HAR Replaying (Data)
🎥 Recording a HAR File
You can record a HAR file directly from your terminal using the Playwright CLI. This opens a real browser window.
# 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.
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.
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
- Scope your HAR. Use the
urlfilter to only mock/api/traffic. Let CSS, images, and JS load from the real server or local dev environment. - 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.
- 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. - 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
Show Answer
Show Answer
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.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.Show Answer
routeFromHAR. This allows the frontend tests to run 100% offline, completely isolated from the backend's instability.🏋️ Practical Exercise
Record and Replay
- Run
npx playwright open --save-har=test.har https://demo.playwright.dev/todomvc - Add a few todo items in the browser, then close it.
- Write a Playwright test that calls
page.routeFromHAR('test.har'). - 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
- Find a public e-commerce demo site (e.g., saucedemo.com).
- Record a HAR file of the login process and the inventory page.
- Strip out any image traffic (filter by
**/api/**). - Write a test suite that runs entirely offline using only the HAR file.
- 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.
page.route()page.mockHar()page.routeFromHAR()page.replayHar()routeFromHAR reads the file and intercepts network requests automatically.npx playwright record --har=file.harnpx playwright open --save-har=file.harnpx playwright har --save=file.harnpx playwright codegen --har=file.har--save-har flag tells the open command to save traffic to a file.page.route() mocking?update: true is set in routeFromHAR?url: '**/api/**' filter so only API calls are mocked.mockImages: false./api/) are intercepted.routeFromHAR work for testing edge cases like 500 Internal Server Errors?page.route() to easily mock 500 errors.page.route() for specific error states.❓ 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.
