Browse the Knowledge Hub211 resources
Faker review: what it is and how to use it for test data
Faker, published as @faker-js/faker, is an open-source MIT library that generates realistic fake data for tests, demos and development: people, addresses, emails, companies, finance, dates and much more, in over 70 locales. It runs in Node.js, browsers and Deno. Separate projects with the same idea exist for Python, Ruby, Java and PHP, each with its own API.
QAble has evaluated this tool and works alongside it. The factual sections are complete; our view is bounded to what we have actually seen rather than a long-term verdict.
- last reviewed
- 13 October 2026
- version covered
- Faker 10 (@faker-js/faker 10.6)
- licence
- Open source
At a glance
Faker at a glance
- Vendor
- Faker project
- Category
- Test data
- Licence
- Open source (MIT)
- Platforms
- Node.js, Browsers, Deno
- Languages
- JavaScript, TypeScript
- First released
- 2004
- Version reviewed
- Faker 10 (@faker-js/faker 10.6)
Verdict
Our verdict on Faker
Strengths
- Hundreds of generators across people, location, internet, finance, commerce, dates and more, all typed for TypeScript
- Over 70 built-in locales, plus custom locales with fallbacks for data your market needs
- faker.seed() makes output reproducible, and calling it without arguments returns a random seed you can log
- exampleEmail() uses reserved example domains, so generated users cannot email real inboxes
- MIT licensed and community maintained under the faker-js organisation since January 2022
Weaknesses
- Values are not unique by default; duplicates appear sooner than expected because of the birthday paradox
- The same seed can produce different data after a Faker upgrade, breaking hard-coded expectations
- Version 10 is ESM-first, and older Jest setups need configuration or must stay on v9
- Generates values, not related datasets: factories and database seeding are code you write
Our take
Faker is the default answer when tests need data that looks real and is different on every run, which is what stops tests colliding in a shared environment and catches the bugs that only appear with an apostrophe in a surname or a long street name. QAble has evaluated it for test data generation rather than maintained a long-running suite built around it, so treat this as a bounded take. The caution is determinism. Random data that is not seeded produces a failure nobody can reproduce, and even seeded data changes across Faker versions and with relative dates. Seed per test, log the seed, fix the reference date, and pin the version in the lockfile. And remember that realistic is not the same as safe: use reserved example domains for email and keep production data out entirely.
We have evaluated this tool rather than maintained a long-running suite on it, so this is a bounded view rather than a long-term verdict. The rest of this page is factual.
How it works
What is Faker and how does it work?
A seeded generator over locale data
Every Faker instance combines a pseudo-random number generator with locale definitions: lists of first names, street suffixes, company words and patterns for phone numbers and postcodes. A method such as faker.person.lastName() draws from those lists using the generator, so with the same seed, the same Faker version and the same sequence of calls, the output is identical. That is the basis of reproducibility, and also of its fragility: adding one extra call earlier in a test shifts every value after it, and a Faker release that changes a list changes the data a seed produces.
Modules, instances and locales
Methods are grouped into modules: basic types such as number, string, date and datatype, topic modules such as person, location, internet, finance, commerce and company, and helpers for working with your own data. The default faker export is English; each built-in locale has its own pre-built instance, such as fakerDE or fakerEN_GB, and new Faker({ locale: [...] }) builds a custom instance from a list of locale definitions checked in order, so a custom definition can override part of a locale and fall back to English and base for the rest. simpleFaker offers the locale-free modules without loading locale data.
Relative dates depend on today
Methods such as faker.date.past, date.future, date.recent, date.soon, git.commitEntry and string.uuid with version 7 generate values relative to a reference date, which defaults to now. A seed alone therefore does not make them reproducible: tomorrow the same seed yields different dates. Passing refDate to a call, or calling faker.setDefaultRefDate once, fixes the reference so date output becomes deterministic. This is the most common reason a seeded test still fails differently on different days.
One library, several unrelated ports
Faker began as a Perl library in 2004 and the idea was ported widely. @faker-js/faker is the JavaScript port, taken over by a community team in January 2022 after the original faker.js maintainer deleted the project; the unscoped faker package on npm was left at a version 6.6.6 that contains almost nothing. Faker for Python, faker-ruby, Datafaker for Java and FakerPHP are separate projects with their own APIs, versions and seeding rules, so code and advice do not transfer between them unchanged.
Strengths
What it does well
Unique data per run in shared environments
Tests that always register [email protected] collide with each other and with yesterday’s data. Generating each user, order and company per test keeps parallel workers and repeated runs independent, without a cleanup step that must succeed before the next run can start. It also means the suite exercises a spread of inputs rather than one happy-path record.
Realistic edge cases for free
Locale data includes names with apostrophes, hyphens and accents, long addresses and varied phone formats. Running forms and APIs against that variety surfaces truncation, encoding and validation bugs that a fixed record such as John Smith never triggers. Switching the instance to fakerDE, fakerJA or fakerAR checks the same flows with other scripts and formats.
Reproducible randomness
faker.seed(n) resets the sequence, and faker.seed() with no argument picks a random seed and returns it. Logging that value on every test run gives the variety of random data with a way back: when a test fails, rerun it with the logged seed and get the same data. setDefaultRefDate does the same for relative dates.
Safe-by-construction contact data
faker.internet.exampleEmail() generates addresses on example.com, example.net and example.org, domains reserved for documentation that can never receive mail. Using it, or the provider option on faker.internet.email, means a staging system that really sends email cannot reach a real person, which is a genuine risk with generated addresses on common webmail domains.
Helpers for building datasets
faker.helpers.multiple calls a generator a fixed or random number of times, uniqueArray returns a set of distinct values, arrayElement and weightedArrayElement pick from your own lists, and fake and mustache fill string templates. Together they turn single-value methods into the arrays and records a seeding script or API test needs.
Typed API that guides usage
The library is written in TypeScript and its documentation assumes strict mode. Method options, such as a sex for person.firstName or a provider for internet.email, are typed, so editors autocomplete the options and flag removed methods after an upgrade, which matters given how many tutorials still use names removed in recent majors.
Pricing
Faker pricing and licensing
Faker is free and open source under the MIT licence, with no paid edition, hosted service or usage limit. The faker-js team maintains it as volunteers and accepts sponsorship through Open Collective. The real costs are engineering time: writing factories for your domain, keeping seeded expectations stable across upgrades, and handling the v10 module changes in older toolchains. The Python, Ruby, Java and PHP ports are also free and open source, under their own licences.
- Licence: MIT for @faker-js/faker. Faker for Python, faker-ruby and FakerPHP are also MIT; Datafaker for Java is Apache 2.0.
- No tiers: every module, locale and helper is in the one npm package.
- Bundle size: the full package is over 5 MiB minified, so keep it in devDependencies and out of production web bundles.
- Hidden cost: upgrades. Majors remove deprecated methods and seeded output can change, so budget time to update factories and any snapshot or hard-coded expectations.
- Paid alternatives exist for different needs, such as Mockaroo, a hosted generator with a free tier limited to 1,000 rows per file and paid annual plans.
Checked against the vendor’s own pages on 13 October 2026. Pricing changes; confirm on the official site before buying.
Getting started
Faker tutorial: getting started
Setup, step by step
- Use Node.js 20.19, 22.13, 24 or later, as Faker 10 requires.
- Install @faker-js/faker as a development dependency, not the unscoped faker package.
- Write a factory function per domain object, generating related fields from each other.
- Seed Faker and set a default reference date in test setup, and log the seed.
- Call the factory in a test, overriding only the fields the test cares about.
Install
npm install --save-dev @faker-js/faker
# Requires Node.js ^20.19.0, ^22.13.0 or >=24.0.0A first example
// test/factories/user.ts
import { faker } from '@faker-js/faker'
export interface User {
id: string
firstName: string
lastName: string
email: string
phone: string
signedUpAt: Date
plan: 'free' | 'pro' | 'team'
}
export function createUser(overrides: Partial<User> = {}): User {
// Derive the email from the name so the record is internally consistent
const firstName = overrides.firstName ?? faker.person.firstName()
const lastName = overrides.lastName ?? faker.person.lastName()
return {
id: faker.string.uuid(),
firstName,
lastName,
// example.com/.net/.org are reserved: no real inbox can receive this
email: faker.internet.exampleEmail({ firstName, lastName }),
phone: faker.phone.number({ style: 'international' }),
signedUpAt: faker.date.past({ years: 2 }),
plan: faker.helpers.arrayElement(['free', 'pro', 'team'] as const),
...overrides,
}
}
// In test setup: same seed + same reference date = same data every run
faker.seed(20261013)
faker.setDefaultRefDate('2026-10-13T00:00:00.000Z')
const proUser = createUser({ plan: 'pro' })What trips people up first
Installing the wrong package or copying removed methods. npm install faker installs the abandoned unscoped package, whose latest version, 6.6.6, contains almost no code, so imports fail or return nothing. Install @faker-js/faker. Then expect tutorials to use names that no longer exist: faker.name and faker.address were replaced by faker.person and faker.location, and faker.internet.userName became username, all removed for good in v10. If Jest then fails with an ESM error, see the v10 upgrade guide: Jest 30.4.2 or later with native ESM support works, older setups need a ts-jest transform or should stay on v9.
In practice
Using Faker in practice
Factories with overrides
Wrap Faker in one factory per domain object, in a shared folder such as test/factories, and never call Faker directly in test bodies. The factory generates related fields from each other, a first name before the email that uses it, so records are internally consistent. Overrides let each test pin only what it asserts on: a test about the pro plan passes plan: pro and leaves everything else random. That keeps tests short, makes intent obvious, and puts the knowledge of what a valid user looks like in one place, so a new mandatory field means one change rather than a hundred.
Seeding per test and logging the seed
A single shared faker instance, seeded once, makes data depend on test order: run one test alone and its data changes. Give each test its own instance and seed it, using a seed from the environment when reproducing a failure or a fresh random one otherwise, and record the seed where the report shows it. The Playwright fixture below does this; the same pattern works in a Vitest or Jest beforeEach. To reproduce a failure, rerun the test with FAKER_SEED set to the logged value, on the same Faker version.
// test/fixtures.ts: one seeded Faker per test, seed shown in the report
import { test as baseTest } from '@playwright/test'
import { Faker, en, base } from '@faker-js/faker'
export const test = baseTest.extend<{ faker: Faker }>({
faker: async ({}, use, testInfo) => {
const faker = new Faker({ locale: [en, base] })
// seed() with no argument picks a random seed and returns it
const seed = process.env.FAKER_SEED
? faker.seed(Number(process.env.FAKER_SEED))
: faker.seed()
faker.setDefaultRefDate('2026-01-01T00:00:00.000Z')
testInfo.annotations.push({ type: 'faker-seed', description: String(seed) })
await use(faker)
},
})
// In a spec:
// test('signs up', async ({ page, faker }) => {
// const email = faker.internet.exampleEmail()
// })Uniqueness in shared environments
Faker methods do not promise unique values, and some draw from small lists; faker.animal.type has 44 options. Even full names repeat sooner than intuition suggests. For a batch generated at once, faker.helpers.uniqueArray returns distinct values. For data created across tests and runs against a shared database, add a run-specific token: a short random string per run, or the CI run ID, placed in the email local part or a name suffix. That guarantees uniqueness and makes cleanup trivial, because every record from a run shares the token.
import { faker } from '@faker-js/faker'
// 500 distinct addresses for a bulk import test
const emails = faker.helpers.uniqueArray(() => faker.internet.exampleEmail(), 500)
// Unique across runs: tag every record with the run, then clean up by tag
const runId = process.env.GITHUB_RUN_ID ?? faker.string.alphanumeric(6)
const email = `qa+${runId}.${faker.string.alphanumeric(8)}@example.com`Generating data safely
Realistic data can still do harm. Generated emails on common webmail domains may belong to real people, so use exampleEmail or a provider on a domain you control. Phone numbers are random digits in a valid format and can be real numbers, so never let staging send SMS to generated numbers. Generated card numbers and IBANs are for format validation only, and payment sandboxes require their documented test numbers instead. Above all, use Faker instead of copying production records: generated data has no data protection obligations, while a copied customer table carries all of them into every test environment.
Locales and custom data
Choose the locale that matches the market under test: fakerEN_GB produces British postcodes and phone formats, fakerDE German addresses, fakerJA Japanese names. For domain-specific values, define a small custom locale and put it first in the list, so it overrides only what you specify and falls back to built-in locales for everything else. A custom domain_suffix of test, for example, makes generated domain names and URLs non-routable; note that the key uses the snake_case name of the locale data, and that internet.email still draws on free webmail providers, so keep using exampleEmail for addresses. Keep custom definitions in the factories folder so the whole suite shares them.
import type { LocaleDefinition } from '@faker-js/faker'
import { Faker, en_GB, en, base } from '@faker-js/faker'
const qaLocale: LocaleDefinition = {
// Locale keys use snake_case: domain_suffix, not domainSuffix
internet: { domain_suffix: ['test'] }, // .test is reserved
}
// Checked in order: custom first, then British English, then English, then base
export const fakerQA = new Faker({ locale: [qaLocale, en_GB, en, base] })
fakerQA.location.zipCode() // a UK-style postcode
fakerQA.internet.url() // https://....testPitfalls
Common pitfalls
Installing faker instead of @faker-js/faker
Why it happens: The unscoped faker package was abandoned in January 2022 and its latest version, 6.6.6, contains almost no code, but older tutorials still say npm install faker.
The fix: Uninstall faker, install @faker-js/faker as a development dependency, and update imports to import { faker } from @faker-js/faker.
Copying methods removed in v10
Why it happens: faker.name, faker.address and faker.internet.userName were deprecated in v9 and removed in v10, along with image.urlPlaceholder, image.avatarLegacy, finance.maskedNumber and one internet method.
The fix: Use faker.person, faker.location and faker.internet.username, and the documented replacements for the rest. Upgrade to the latest v9 first and clear its deprecation warnings before moving to v10.
Seeded tests that fail differently tomorrow
Why it happens: date.past, date.recent, date.soon and similar methods are relative to the current date, so a seed alone does not fix their output.
The fix: Call faker.setDefaultRefDate with a fixed date in test setup, or pass refDate to each call.
Hard-coded expectations breaking after an upgrade
Why it happens: The faker-js documentation warns that a new version may return different values for the same seed, because underlying lists change. Faker for Python makes no consistency promise even across patch versions.
The fix: Assert on properties of data, such as format or relationships, rather than exact generated values, and pin the version through the lockfile.
Word methods throwing after upgrading to v10
Why it happens: Word module methods now default to a fail strategy, so a length constraint no word satisfies throws a FakerError instead of quietly returning a word of another length.
The fix: Loosen the length constraint, or pass strategy: any-length to restore the v9 behaviour where that is acceptable.
Shipping Faker in a production web bundle
Why it happens: The full package is over 5 MiB minified because of its locale data. Importing it from application code to fill demo screens or mocks puts all of that in front of users.
The fix: Keep Faker in devDependencies and test or mock code only, import a single locale instance, or use simpleFaker where locale data is not needed.
Compared
How Faker compares
| Tool | Used from | Licence | Runs where | Cost | Output |
|---|---|---|---|---|---|
| Faker | JavaScript and TypeScript code | MIT | In process: Node.js, browsers, Deno | Free, no limits | Values and objects in code |
| Faker for Python | Python code, CLI, pytest fixture | MIT | In process, Python 3.10 or later | Free, no limits | Values in code or CLI output |
| Datafaker | Java and other JVM languages | Apache 2.0 | In process, Java 17 or later | Free, no limits | Values, plus CSV, JSON, SQL transformers |
| Mockaroo | Web UI and REST API | Commercial, free tier | Hosted on mockaroo.com | Free: 1,000 rows per file | Downloadable files, such as CSV, JSON, SQL |
FAQ
Frequently asked questions
What is Faker?
Faker, published as @faker-js/faker, is an open-source MIT library that generates realistic fake data for tests, demos and development: people, addresses, emails, companies, finance, dates and much more, in over 70 locales. It runs in Node.js, browsers and Deno. Separate projects with the same idea exist for Python, Ruby, Java and PHP, each with its own API.
Is Faker free?
Yes. @faker-js/faker is open source under the MIT licence, with no paid edition, account or usage limit, and it is maintained by a volunteer team funded through Open Collective. The Python, Ruby and PHP Faker projects are also MIT licensed, and Datafaker for Java is Apache 2.0. The costs are your time writing factories and handling upgrades.
What happened to faker.js?
In January 2022 the original maintainer deleted the faker.js project and published a near-empty 6.6.6 version of the faker package on npm. A group of long-time users created the faker-js organisation, republished the history as @faker-js/faker and have maintained it as a community project since. Use @faker-js/faker; the unscoped faker package should not be installed.
How do I get the same fake data on every test run?
Call faker.seed with a fixed number before generating data, and faker.setDefaultRefDate with a fixed date so relative dates are stable too. Keep the order of Faker calls the same and pin the Faker version, because new versions can change the values a seed produces. For random but reproducible runs, call faker.seed() with no argument and log the seed it returns.
Does Faker generate unique values?
Not by default. Each call is independent, so duplicates appear, quickly for methods with short lists. In @faker-js/faker, helpers.uniqueArray generates a set of distinct values in one go; otherwise add your own sequence or run-specific token. Faker for Python has a unique proxy, as in fake.unique.first_name(), that refuses repeats on that instance until cleared.
Faker vs Mockaroo: which should I use?
Use Faker when data is generated by test code at run time: per test, seeded and versioned with the suite. Use Mockaroo when someone needs a file, such as CSV, JSON, SQL or Excel, built from a schema in a browser without writing code. Mockaroo’s free tier allows 1,000 rows per file and 200 API requests a day, with paid annual plans above that.
Which Faker should I use for Python or Java?
For Python, the Faker package on PyPI, which needs Python 3.10 or later and includes a pytest plugin with a faker fixture seeded by a faker_seed fixture. For Java, Datafaker is a maintained fork of java-faker; version 2.x requires Java 17. The original java-faker’s latest published version is 1.0.2. Ruby has faker-ruby and PHP has FakerPHP.
What changed in Faker 10?
Faker 10.0.0 was released on 24 August 2025, and 10.6.0 on 14 August 2026 is the current release. It requires Node.js 20.19, 22.13, 24 or later, is ESM-first while still loadable through require on those versions, removes methods deprecated in v9 such as faker.name and faker.address, and makes word methods throw when no word matches the constraints. The project’s main branch already documents Node.js 22 as the minimum for the next major.
Alternatives
Faker alternatives worth weighing
Mockaroo
Browser-based realistic test data generation, exporting to CSV, JSON, SQL and other formats.
Resources
Where to go next
Picking the wrong tool costs more than picking late.
QAble advises on toolchain decisions and then implements them, with engineers who have run these tools on real delivery. Start with a free QA audit.