Free Mock API Generator Guide — Build and Test APIs Without a Backend

Mock APIs let frontend developers build and test UIs without waiting for a real backend. They simulate API responses, handle different scenarios, and speed up development. This guide covers the best free mock API tools, how to use them effectively, and patterns for realistic fake data generation with Faker.js.

Zero backend

required to start frontend development

JSON Server

most popular — full REST API from a JSON file

MSW

best for React testing with service workers

Faker.js

generate realistic fake data for any field

1

Why Mock APIs?

The core benefit

Mock APIs eliminate the frontend/backend dependency during development. Instead of waiting for the backend team to build endpoints, frontend devs define the expected API shape and mock it immediately. This enables parallel development, faster iteration, and reliable testing without live API dependencies.

Parallel development

Frontend and backend teams work simultaneously. Frontend mocks the agreed API contract; backend implements it. No blocking, faster delivery.

Reliable testing

Tests that hit real APIs are flaky — network issues, rate limits, changing data. Mock APIs return predictable responses every time, making CI reliable.

Edge case simulation

Easily simulate error states (500, 401, timeout), empty states, large datasets, and pagination that are hard to reproduce with real APIs.

Offline development

Work without internet or VPN. Mock APIs run locally and don't depend on network connectivity, API uptime, or authentication.

Cost savings

Avoid burning API rate limits or incurring costs for paid APIs (Stripe, SendGrid, Twilio) during development and CI/CD test runs.

Contract-first development

Define the API shape first as the mock, then both teams implement against that contract. Reduces integration surprises at merge time.

2

Tool Comparison

ItemToolBest For
JSON ServerZero-config REST API from db.jsonQuick prototypes, CRUD APIs, no code required — start in 30 seconds
MSW (Mock Service Worker)Intercepts real fetch/axios calls in browserReact/Vue apps, Jest/Vitest testing, Storybook component isolation
MockoonDesktop GUI mock server applicationTeams that prefer GUI over code, sharing mock configs as files
Mirage JSIn-browser API mocking with ORMEmber/React apps with complex relational data needs
Postman Mock ServerCloud-hosted mock from Postman collectionTeams already using Postman, sharing mocks across teams via URL
WireMockJava-based mock server with powerful matchingJava/JVM projects, complex request matching, fault simulation
Faker.jsFake data generation library (not a server)Seeding JSON Server, generating test fixtures, Storybook stories
3

JSON Server — REST API in 30 Seconds

bashSetup JSON Server
# Install
npm install -g json-server

# Create your mock database
cat > db.json << 'EOF'
{
  "users": [
    { "id": 1, "name": "Alice Johnson", "email": "alice@example.com", "role": "admin" },
    { "id": 2, "name": "Bob Smith", "email": "bob@example.com", "role": "user" }
  ],
  "posts": [
    { "id": 1, "title": "Hello World", "userId": 1, "published": true },
    { "id": 2, "title": "Mock APIs Rock", "userId": 2, "published": false }
  ],
  "comments": [
    { "id": 1, "postId": 1, "body": "Great post!", "userId": 2 }
  ]
}
EOF

# Start server — full REST API available instantly!
json-server --watch db.json --port 3001

# Now you have:
# GET    /users          → list all users
# GET    /users/1        → get user by id
# POST   /users          → create user (auto-assigns id)
# PUT    /users/1        → replace user
# PATCH  /users/1        → partial update
# DELETE /users/1        → delete user
# GET    /posts?userId=1 → filter by field
# GET    /users?_sort=name&_order=asc  → sort
# GET    /users?_page=1&_limit=10      → pagination
# GET    /posts?_expand=user           → include related user
# GET    /users/1/posts                → nested resources
javascriptJSON Server with custom routes and middleware
// json-server-config.js — custom routes + middleware
const jsonServer = require('json-server');
const server = jsonServer.create();
const router = jsonServer.router('db.json');
const middlewares = jsonServer.defaults();

// Add custom middleware for auth simulation
server.use((req, res, next) => {
  if (req.headers.authorization !== 'Bearer mock-token') {
    // Allow GET requests without auth
    if (req.method !== 'GET') {
      return res.status(401).json({ error: 'Unauthorized' });
    }
  }
  next();
});

// Custom route rewrites
server.use(
  jsonServer.rewriter({
    '/api/*': '/$1',           // /api/users → /users
    '/v1/users/:id': '/users/:id',
  })
);

// Simulate delay for all requests (realistic latency)
server.use((req, res, next) => {
  setTimeout(next, 300 + Math.random() * 200);  // 300-500ms delay
});

server.use(middlewares);
server.use(router);
server.listen(3001, () => console.log('Mock API running on port 3001'));

// Run with: node json-server-config.js
4

MSW — Mock Service Worker for React

typescriptMSW Setup for React + Jest
// src/mocks/handlers.ts
import { http, HttpResponse, delay } from 'msw';

export const handlers = [
  // Mock GET /api/users
  http.get('/api/users', async () => {
    await delay(200);  // realistic latency
    return HttpResponse.json([
      { id: 1, name: 'Alice', email: 'alice@example.com', role: 'admin' },
      { id: 2, name: 'Bob', email: 'bob@example.com', role: 'user' },
    ]);
  }),

  // Mock POST /api/users with request body access
  http.post('/api/users', async ({ request }) => {
    const body = await request.json() as { name: string; email: string };
    return HttpResponse.json(
      { id: Math.floor(Math.random() * 1000), ...body, role: 'user' },
      { status: 201 }
    );
  }),

  // Simulate 404 for specific IDs
  http.get('/api/users/:id', ({ params }) => {
    if (params.id === '999') {
      return HttpResponse.json({ error: 'User not found' }, { status: 404 });
    }
    return HttpResponse.json({ id: params.id, name: 'Test User', role: 'user' });
  }),

  // Simulate server error
  http.delete('/api/users/:id', ({ params }) => {
    if (params.id === '1') {
      return HttpResponse.json({ error: 'Cannot delete admin' }, { status: 403 });
    }
    return new HttpResponse(null, { status: 204 });
  }),
];

// src/mocks/browser.ts (for development)
import { setupWorker } from 'msw/browser';
import { handlers } from './handlers';
export const worker = setupWorker(...handlers);

// src/main.tsx — only activate in development
if (process.env.NODE_ENV === 'development') {
  const { worker } = await import('./mocks/browser');
  await worker.start({ onUnhandledRequest: 'warn' });
}

// In Jest tests (setupTests.ts)
import { setupServer } from 'msw/node';
import { handlers } from './mocks/handlers';
const server = setupServer(...handlers);
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

// Override handlers per test for specific scenarios:
test('handles 500 error', () => {
  server.use(
    http.get('/api/users', () =>
      HttpResponse.json({ error: 'Server Error' }, { status: 500 })
    )
  );
  // ... test error handling
});
5

Generating Realistic Fake Data with Faker.js

javascriptFaker.js for realistic mock data
import { faker } from '@faker-js/faker';

// Generate realistic user data
function generateUser() {
  return {
    id: faker.string.uuid(),
    name: faker.person.fullName(),
    email: faker.internet.email(),
    phone: faker.phone.number(),
    avatar: faker.image.avatar(),
    username: faker.internet.username(),
    address: {
      street: faker.location.streetAddress(),
      city: faker.location.city(),
      state: faker.location.state(),
      country: faker.location.country(),
      zipCode: faker.location.zipCode(),
    },
    company: faker.company.name(),
    jobTitle: faker.person.jobTitle(),
    createdAt: faker.date.past({ years: 2 }).toISOString(),
    isActive: faker.datatype.boolean({ probability: 0.85 }),
  };
}

// Generate realistic product data
function generateProduct() {
  return {
    id: faker.string.uuid(),
    name: faker.commerce.productName(),
    price: parseFloat(faker.commerce.price({ min: 10, max: 500 })),
    description: faker.commerce.productDescription(),
    category: faker.commerce.department(),
    sku: faker.string.alphanumeric(8).toUpperCase(),
    inStock: faker.datatype.boolean({ probability: 0.9 }),
    rating: parseFloat((Math.random() * 2 + 3).toFixed(1)),  // 3.0–5.0
    reviewCount: faker.number.int({ min: 0, max: 2000 }),
    images: Array.from({ length: 3 }, () => faker.image.url()),
  };
}

// Seed for reproducible data (same seed = same data across runs)
faker.seed(12345);
const reproducibleUser = generateUser(); // Always the same user

// Generate bulk data for db.json seeding
const dbSeed = {
  users: Array.from({ length: 50 }, generateUser),
  products: Array.from({ length: 200 }, generateProduct),
};

// Write to db.json for JSON Server
import fs from 'fs';
fs.writeFileSync('db.json', JSON.stringify(dbSeed, null, 2));
console.log('Seeded db.json with', dbSeed.users.length, 'users and', dbSeed.products.length, 'products');
6

Setting Up a Complete Mock API Workflow

1

Define your API contract

Before writing any mock code, document the endpoint paths, request/response shapes, and error codes in a shared spec (OpenAPI/Swagger or a simple TypeScript interface file). This becomes the source of truth for both the mock and the real implementation.

2

Generate seed data with Faker.js

Create a seed script that generates realistic data: 50+ users, 200+ products, with real-looking names, emails, and prices. Run it to populate db.json. Realistic data surfaces UI bugs that placeholder text hides (long names, special characters, edge cases).

3

Start JSON Server for rapid prototyping

Run json-server --watch db.json --port 3001 during development. Your entire React/Vue/Angular app can immediately CRUD data. No backend required. Add a custom middleware file for auth simulation and artificial delays.

4

Add MSW for component and integration tests

Set up MSW handlers that mirror your JSON Server routes. In tests, override specific handlers to simulate errors, empty states, and edge cases. This gives you test coverage of every UI state without hitting a real network.

5

Simulate all error states

Explicitly test: 401 (logged out), 403 (no permission), 404 (not found), 422 (validation error), 500 (server down), network timeout. Use MSW's server.use() in individual tests to inject these states. Your error UI is only as good as your error testing.

6

Transition to real API

When the real backend is ready, remove the MSW handlers and JSON Server. Since you used real endpoint paths throughout, your app transitions with zero code changes. Run the same test suite against the staging API to catch contract mismatches early.

Use Unblockdevs Mock API Generator

Our tool at unblockdevs.com/mock-api-generator lets you define a JSON schema and instantly generates realistic fake API endpoints with pagination, filtering, and error simulation — no setup required. Paste your TypeScript interface and get a live API URL in seconds.

Frequently Asked Questions

Related API Tools Guides

Continue with closely related troubleshooting guides and developer workflows.