Docs
Everything on this page is verified against the v3.0.0 source. If something here disagrees with har-to-mocks --help, the CLI wins and the docs have a bug: open an issue.
Install
Requires Node.js 22 or newer for v3.0.0. The v2.x line supported Node.js 18 and newer.
# run without installing npx har-to-mocks [path to .har] [path mock/api folder] --dry-run # or install globally npm install -g har-to-mocks
The CLI checks npm for a newer version on each run and prints an update notice (via update-notifier). There is no web UI, no cloud service, no account, and no telemetry beyond that check.
CLI reference
har-to-mocks <file.har> [output-folder] [flags]
Arguments
file(required): path to the.harfile.to(optional): path to your mocks/api folder. If omitted, nothing is written; the CLI only lists matching requests. If provided, files are written unless--dry-runis set.
Flags
| Flag | Short | Description | Default |
|---|---|---|---|
--url | -u | Filter by substring match in the full URL (case-sensitive, includes the query string, e.g. --url=?q=search). Not a regex. | none |
--method | -m | Filter by HTTP method, repeatable: --method=GET --method=POST. Supported: GET, POST, PUT, DELETE, PATCH. | GET |
--type | -t | Filter by resource type: xhr, fetch, document. Pass --type=fetch or you will miss fetch requests. | xhr |
--format | -f | Folder layout: mocks (<path>/<METHOD>.json) or chrome-overrides (<host>/<path>[?query]). | mocks |
--select | -s | Pick rows by the # column: --select=1,3,5-7, repeatable. In interactive mode they become the pre-selection. | none |
--interactive | -i | Checkbox picker with live JSON response preview and confirmation. | off |
--dry-run | Show tables and folder tree, write nothing. | off | |
--version | -v | Print version. | |
--help | -h | Help. |
Features with output
A. Inspect and filter a HAR file
A HAR can contain hundreds of entries (scripts, images, fonts, analytics). Filters narrow it to the API calls you want.
$ har-to-mocks ./file.har --url=api/service --method=GET
Filtered requests:
# │ Name │ Method │ Path │ Query
──┼───────────────┼────────┼─────────────────────────────┼──────
1 │ userRoles │ GET │ /api/service/userRoles │
2 │ currentUserId │ GET │ /api/service/currentUserId │
3 │ active │ GET │ /api/service/clients/active │- The
#column numbers rows so they can be referenced with--select. - The Query column shows query parameters so similar requests to the same path can be told apart.
- Entries with unparsable URLs are skipped with a warning instead of crashing.
- Missing, non-JSON, or non-HAR input files produce friendly errors:
File not found,File is not valid JSON,File is not a valid HAR file (missing "log.entries").
B. Dry run with a status column and folder-tree preview
When an output folder is given, a Status column appears: create (new file), update (will overwrite an existing file), skip (duplicate endpoint; a later entry writes the same file). A folder tree shows exactly what will land on disk, with [UPDATE] markers for files that already exist.
$ har-to-mocks ./file.har ./mocks --url=api/service --method=GET --dry-run
Filtered requests:
# │ Name │ Method │ Path │ Query │ Status
──┼───────────────┼────────┼─────────────────────────────┼───────┼───────
1 │ userRoles │ GET │ /api/service/userRoles │ │ create
2 │ currentUserId │ GET │ /api/service/currentUserId │ │ create
3 │ active │ GET │ /api/service/clients/active │ │ create
Folder tree which will be applied:
└─ mocks
└─ api
└─ service
├─ userRoles
│ └─ GET.json
├─ currentUserId
│ └─ GET.json
└─ clients
└─ active
└─ GET.json
No files were written. If you want to write files remove the (--dry-run) flag.The tool never writes unless you give it a folder, and --dry-run lets you see every file it would create or overwrite before it does.
C. Interactive mode (-i) with live response preview
$ har-to-mocks ./file.har ./mocks --interactive- A checkbox list of all matching endpoints (
METHOD /path?query). - As you move the cursor, the JSON response body of the focused endpoint is rendered below the list (up to 12 lines), so you can tell apart two calls to the same endpoint that returned different data.
- Endpoints that would be written by default are pre-selected;
--selectoverrides the pre-selection. - After choosing, the CLI prints the equivalent
--select=1,3value so you can script the same choice later. - Folder tree preview, then an explicit confirm step before anything is written.
- Keyboard:
↑/↓navigate,Spacetoggle,atoggle all,iinvert,Enterconfirm. - Works with both output formats.
D. Non-interactive selection (--select) for scripts and CI
$ har-to-mocks ./file.har --url=api/service $ har-to-mocks ./file.har ./mocks --url=api/service --select=1,3 $ har-to-mocks ./file.har ./overrides --url=api/service --select=1,3 --format=chrome-overrides
Output keeps the original row numbers:
Selected requests: # │ Name │ Method │ Path │ Query │ Status ──┼───────────┼────────┼─────────────────────────────┼───────┼─────── 1 │ userRoles │ GET │ /api/service/userRoles │ │ create 3 │ active │ GET │ /api/service/clients/active │ │ create
Comma lists and ranges (5-7) are accepted; invalid numbers fail with a clear error.
E. Duplicate detection with a hint
When several requests share path and method (different query strings), they would collide on one file. The CLI marks the extras as skip and prints:
Note: Some endpoints have status "skip" because they share the same path and method. The last occurrence will be written. To select specific endpoints, use --select or interactive mode: har-to-mocks <file.har> <output-folder> --select=1,3 har-to-mocks <file.har> <output-folder> --interactive
F. Friendly errors and engineering quality
- 100 % test coverage: unit, integration and snapshot tests (Vitest).
- CI on every pull request: lint, tests, build.
- Automated releases with semantic-release, conventional commits, and npm provenance (OIDC-signed publishes from GitHub Actions).
- Bundled with esbuild so the global install footprint is small. TypeScript, ES modules,
@oclif/corev5,@inquirer/prompts, ESLint + Prettier. - Actively maintained: 10+ releases in 2026 alone (v2.0.0 through v3.0.0), including interactive mode, response preview, Chrome overrides,
--select, friendly errors, and security dependency bumps. 21 versions published between October 2021 and October 2026.
Output formats
mocks (default) for MSW, Playwright and connect-api-mocker
Layout: <output>/<url path>/<METHOD>.json. The JSON file is the raw response body only (no headers, no status codes). This layout is what mocks-to-msw and mocks-to-playwright consume and what connect-api-mocker (Express / webpack-dev-server middleware) serves.
import { createMockHandler } from "mocks-to-msw";
import mocks from "./mocks/mocks";
const { mock } = createMockHandler<keyof typeof mocks>({ mocks, debug: true });
export const handlers = [
mock.get("/client"),
mock.post("/client/application", (data) => ({ ...data, modified: true })),
];mocks-to-msw adds type-safe URL/method pairing, async loading, response modifiers, debug logging, origin configuration, and a CLI that generates a typed import file from the mocks folder.
In Playwright tests, mocks-to-playwright serves the same files through page.route() with the same typed API:
import { createMockRoutes } from "mocks-to-playwright";
import mocks from "./mocks/mocks";
const { mock } = createMockRoutes<keyof typeof mocks>({ mocks });
test("shows the client", async ({ page }) => {
await mock.get("/client")(page);
await mock.post("/client/application", (data) => ({ ...data, status: "approved" }))(page);
await page.goto("/");
});Register a mock on a page or a whole browser context. The route registered last wins, so a mock with a modifier overrides a default one in a single test. The query string is ignored, and cross-origin requests work without extra CORS setup.
chrome-overrides for Chrome DevTools Local Overrides
$ har-to-mocks ./file.har ./overrides --format=chrome-overrides --dry-run
Folder tree which will be applied:
└─ overrides
└─ sample.com
├─ api
│ └─ service
│ ├─ userRoles
│ └─ clients
│ └─ active
└─ complete
├─ search?q=javascript
└─ search?q=pythonThen in Chrome: Sources → Overrides → Select folder for overrides, pick that folder, allow access, reload. Chrome now serves those responses instead of the network, with no code changes to the app at all.
- Files are named the way Chrome names them:
<host>/<path>, query string kept in the file name,index.htmlfor paths ending in/, special characters escaped, very long URLs go to alongurlsfolder. - Chrome matches by URL only, not method, so a GET and POST to the same URL share one file (status skip). Different query strings get separate files.
- Chrome returns overridden responses with status 200 and the real request's headers.
- A path cannot be both a file and a folder (
/api/usersand/api/users/1conflict; the CLI reportsA file and a folder would have the same path). - Binary responses (base64 in the HAR) are decoded, so images and fonts are written as original bytes.
- Point DevTools at exactly the folder you wrote to.
Step 0: how to get a HAR file
- Chrome / Edge: DevTools → Network tab → make sure "Preserve log" is on → use the app → click the download icon "Export HAR..." (or right-click → "Save all as HAR with content"). Content must be included for responses to exist in the file.
- Firefox: DevTools → Network → gear icon → "Save All As HAR".
- Safari: Web Inspector → Network → "Export".
HAR files can contain cookies and tokens. The mocks only keep response bodies, but review the output before committing it.
Adapters and the agent skill
mocks-to-msw ↗ is an adapter that loads these mocks into Mock Service Worker with type-safe handlers and its own CLI. The Medium article ↗ walks through the Storybook flow.
mocks-to-playwright ↗ serves the same mocks in Playwright ↗ tests through page.route(). It ships the same generate-mocks CLI and file layout as mocks-to-msw, so one generated mocks.ts feeds both your MSW handlers and your Playwright tests. Requires @playwright/test 1.29 or newer.
npm install mocks-to-playwright --save-dev
The har-extraction skill in peterknezek/skills ↗ lets Claude Code and other AI agents run the whole HAR → mocks → MSW workflow on request.
npx skills add peterknezek/skills
A video walkthrough is at youtu.be/Pc2J8aHRKNY ↗ (recorded on v1.1.1, older UI).
FAQ
Will it overwrite my files?
Not silently. Without an output folder nothing is written. With one, the Status column tells you what will be created, updated or skipped, --dry-run shows the full tree first, and interactive mode asks for confirmation.
My HAR has 600 entries.
Narrow it with --url, --method and --type, then pick rows with the interactive picker or --select=1,3,5-7.
I use GraphQL.
Requests are keyed by URL path and method, so multiple GraphQL operations on one endpoint collide today (open issue #12). Interactive mode and --select let you pick which one to keep. Operation splitting is not implemented.
Same endpoint, different query params?
The Query column shows them apart. The chrome-overrides format writes separate files per query string; in the mocks format use --select or interactive mode to choose. Automatic handling is tracked in open issue #18.
Why don't I see my fetch requests?
The default resource type is xhr and the default method is GET. Pass --type=fetch (and --method=POST etc.) to include them. --url is a case-sensitive substring match, not a regex.
Is it maintained?
21 versions since October 2021, 10+ releases in 2026, 100 % test coverage, CI on every pull request, semantic-release with npm provenance. See the release list.
Can I use the mocks in Playwright without MSW?
Yes. mocks-to-playwright registers them with page.route(), no service worker involved. Unlike page.routeFromHAR(), every response is a readable JSON file, each test picks the endpoints it mocks, and a modifier changes one response for one test. See Adapters.
Does it leak secrets?
HAR files can contain cookies and tokens. The mocks keep response bodies only, no headers. Still, review the output before committing it.