โ† All guides

An MSW alternative when you need a real URL

Honest split first: Mock Service Worker is a genuinely great library. If you're writing JavaScript unit or component tests and you want request interception inside the test process โ€” per-test handler overrides, no network, mocks that target the real API URL without changing your app's base URL โ€” MSW is the right tool and this page is not trying to talk you out of it.

But MSW has a hard boundary that sends people searching for alternatives: the mock only exists inside your JavaScript process. A service worker in your browser tab, or interceptors in your Node test runner โ€” and nowhere else. Which means:

Mockbird is the other half: a hosted mock REST API on a real URL. Define resources (or pick a preset, or import an OpenAPI spec / db.json / CSV / Postman collection), get realistic seeded data and full stateful CRUD โ€” reachable from a browser, curl, Postman, a phone, a backend, CI, or a teammate on another continent. No handler code, no service worker, no signup.

The 60-second version

# one curl, no signup โ€” a whole seeded e-commerce backend
curl -X POST https://HOST/api/projects \
  -H 'content-type: application/json' -d '{"name":"shop","preset":"ecommerce"}'
# โ†’ {"id":"abc123","adminKey":"KEY", ...}   โ† save both

curl https://HOST/m/abc123/products?limit=3
# โ†’ 3 seeded products, CORS on, writes persist

Prefer clicking? This link creates the same project in your browser โ€” no account. Have an OpenAPI spec? Paste it at /app#import and get a live seeded mock of your actual API shape.

MSW concepts โ†’ Mockbird

MSWMockbirdNotes
http.get('/products', โ€ฆ) handlera products resourcelist/get/create/update/delete generated, plus filtering, sorting, pagination, relations
Hand-rolled response dataseeded realistic recordsfaker-style names/emails/prices/dates; or import your exact records from db.json/CSV
HttpResponse.json(data, {status: 500})?mock_status=500 on any URLno handler edit, no rebuild โ€” error/loading states guide
delay(2000)?mock_delay=2000plus ?mock_jitter=100-1500 random latency and ?mock_chaos=0.3 random failures
Stateful handlers you write yourselfstateful by defaultPOST persists; GET it back over REST or GraphQL
Per-test server.use(โ€ฆ) overridessnapshot pinningsave named data states, serve any GET from one via X-Mockbird-Snapshot โ€” parallel workers don't race
onUnhandledRequest loggingrequest inspectorlast 50 requests: method, path, query, headers, body
graphql.query(โ€ฆ) handlersgenerated GraphQL endpointtyped schema from your resources, GraphiQL included
Handlers shared via your reposhared via URLsend a teammate the base URL โ€” nothing to install

Try it in 10 seconds (shared demo, no setup)

# seeded data with field projection
curl 'https://HOST/m/demo/products?limit=2&select=name,price'

# the states you'd write handlers for โ€” as query params
curl -i 'https://HOST/m/demo/products?mock_status=503'
curl 'https://HOST/m/demo/products/1?mock_delay=2000'

# stateful: the write persists
curl -X POST https://HOST/m/demo/products \
  -H 'content-type: application/json' -d '{"name":"proof","price":9.99}'
# โ†’ returns {"id":31,โ€ฆ} โ€” and GET /m/demo/products/31 now works

All against the shared demo project (resets daily).

Or use both โ€” they compose

Plenty of teams keep MSW for unit tests and use a hosted mock everywhere MSW can't go. Two easy patterns:

Honest comparison

MSWMockbird
What it isfree OSS library (JS/TS)free hosted service
Reachable fromyour JS process onlyanything with HTTP: browser, curl, Postman, mobile, backend, CI, agents
Setupwrite handlers + worker init + wiringone curl or one click; no code
Mock datayou write itseeded realistic data, or import your own
Stateful CRUDDIY in handler codedefault
Error/latency simulationper-handler code?mock_status / ?mock_delay / ?mock_chaos / ?mock_jitter on any URL
Works offlineyes โ€” no network at allno โ€” it's a real network call
Latencyzero (in-process)real network latency
Mocks the real URL transparentlyyes โ€” intercepts requests to your actual API hostno โ€” you point your app at a Mockbird base URL
Per-test isolationexcellent (server.use, reset between tests)snapshot pinning + restore recipes
Dynamic programmable responsesfull JS โ€” anything you can codecustom routes with templating; less powerful than arbitrary code
Request capnone10,000/project/day

Written by the Mockbird maker โ€” bias disclosed. Where MSW genuinely wins: in-process interception means zero network flakiness, zero latency, and tests that run offline; it mocks your real API URLs without touching app config; per-test handler overrides are cleaner than anything URL-based can be; and a handler is arbitrary JavaScript, so any conditional behavior you can imagine is expressible. For JS unit and component tests, keep MSW. When the thing you need is a URL โ€” for a prototype, a mobile client, a backend consumer, a teammate, or CI hitting a deployed build โ€” that's us.

Full API reference in the docs. More guides: Mirage JS alternative ยท mock API for React ยท free mock API tools compared ยท deterministic test data ยท testing loading & error states. Create your API โ†’