Dummy Data Generator

Generate up to 100,000 rows of realistic fake data as CSV, JSON, NDJSON or SQL. Seeded and reproducible, 100% in your browser. No signup.

Runs in your browser

CSV · JSON · NDJSON · SQL — up to 100,000 rows, generated in your browser. Set a seed to get the same data every time.

Saved in this browser only — clearing site data or switching devices removes it. Use Export to keep a backup.

Presets

Columns

6 / 30 columns

Generation

Clamping moves the real mean and standard deviation away from μ and σ.

Some columns fell back to placeholder values.

ML options — distributions, correlation, target label, missing values
age 18.0 … 80.0

Chained correlation multiplies: corr(A, C) = ρ(A, B) × ρ(B, C).

Names, addresses and companies are fictional and may combine real place names.

Preview

First 20 rows
idnameemailagesignup_dateis_active
1sample_1arrowharbor1@outlook.com282021-01-16true
2sample_2happygreen3@example.com412021-08-09false
3sample_3quartz4912@outlook.com622021-07-05true
4sample_4novalagoon8@outlook.com452024-04-23false
5sample_5trailwitty2@yahoo.com422021-09-16false
6sample_6onyxeager46@outlook.com322022-09-03false
7sample_7deploy3326@hotmail.com412023-09-17false
8sample_8clever9318@yahoo.com422023-01-16true
9sample_9stonearrow75@outlook.com352024-06-18false
10sample_10spark5517@yahoo.com442023-03-20true
11sample_11stream5113@hotmail.com332023-12-06true
12sample_12spark678@yahoo.com262025-05-10true
13sample_13sparkember97@yahoo.com182023-06-14true
14sample_14vertex7474@outlook.com502021-07-05false
15sample_15halowitty8@gmail.com252025-07-19true
16sample_16echo4318@outlook.com462022-08-10false
17sample_17grovesummit67@yahoo.com252022-01-19true
18sample_18wolfprairie82@yahoo.com212024-07-12false
19sample_19shade2090@outlook.com492025-03-01true
20sample_20summitmellow32@outlook.com272025-08-25true

∅ marks a missing value — the file itself uses the missing-value style below.

Output

The BOM is what stops Excel from garbling UTF-8 — leave it on for spreadsheets.

Estimated size: 5.53 KB · Runs in your browser

Values starting with = + - @ can be executed as formulas when opened in a spreadsheet.

Load it in pandas
import pandas as pd
df = pd.read_csv("dummy-data.csv")
df.head()

What dummy data is for — and what it must never be

Dummy data exists so that a table, an import routine or a dashboard can be exercised before real records exist. You need a shape — 500 rows, six columns, a plausible distribution of values — not truth. Copying a slice of the production database into a staging environment gets you the shape too, and also gets you real names, real phone numbers and a breach report if that environment leaks.

The values here are fabricated from a seeded pseudo-random stream, so no row corresponds to a person. Phone numbers stay inside reserved or structurally valid ranges (US numbers use the 555 exchange; Korean numbers use real area codes but random subscriber blocks), and e-mail local parts are generated tokens. Nothing here is a masked or shuffled copy of anything real.

The limit follows from the same fact: fabricated data has no statistical relationship with your users, so it cannot support an analysis, a model you intend to ship, or a claim about behaviour. Use it for load, layout, parsing, encoding, migration and teaching — and use real (consented, anonymised) data when you need conclusions.

28 column types, grouped by what they model

Twenty-seven ordinary types plus one machine-learning target. Structure: auto-increment (start and step configurable), UUID v4 (upper case and hyphen-free variants) and a fixed constant. Numeric: integer, decimal, price (with currency prefix or suffix), boolean (true/false, 1/0 or Y/N) and weighted category — ["paid","shipped","refunded"] with weights 7:2:1 gives roughly 70/20/10.

Dates come as date or timestamp with a range and a format (date, datetime, ISO 8601 or a Unix epoch in seconds). People and company: full name, first name, last name (with a gender option), e-mail, username, phone, job title and company. Places and web: street address, city, state, country (name, ISO-2 or ISO-3), postal code, URL, IPv4 (public or RFC 1918 private), word and sentence.

Switching the language to Korean changes the values, not just the labels: names, companies, cities and 시·도 come from the Korean faker locale, addresses are assembled as 시·도 + 시·군·구 + 로/길 + 번지, postal codes are the 5-digit format introduced in 2015 (01000–63644, so Seoul’s 01xxx is included), job titles are 역할 + 직급, and phones are 010-xxxx-xxxx, 02-xxxx-xxxx or a real regional area code.

  • A schema can hold up to 30 columns and 100,000 rows. Above 10,000 rows the page warns that generation may take a moment; the work still happens on your machine, not on a server.

Seeds: why every column has its own random stream

A single global PRNG is the usual design and it has an annoying property: renaming a column, adding one in the middle or deleting one shifts every subsequent draw, so the whole table changes. Here the stream key is seed + purpose + column id, hashed with FNV-1a into a mulberry32 generator, which means each column draws from a stream of its own.

The practical effect: add an e-mail column to a five-column schema and the other five columns keep exactly the values they had. Rename age to age_years and its numbers do not move either, because the id — not the name — keys the stream. Only changing the seed, the row count or that column’s own options changes its values.

The seed and the whole schema travel in the address bar, so a shared link reproduces a byte-identical file on someone else’s machine — useful for a bug report ("this row breaks the importer"), for a fixture a test suite can regenerate, and for a tutorial where every reader must see the same table.

Leave the seed blank and every click gives a fresh table. That is the right default when you want to see variety; type any string — a word, a ticket number, an emoji — the moment you want the result to be repeatable.

Distributions, correlation and clamping

Numeric columns can be drawn uniformly between a minimum and a maximum, from a normal distribution with a mean and a standard deviation, or from a log-normal distribution — the right default for prices, session lengths and anything else that is positive and right-skewed. Uniform data is the reason so many demos look wrong: real revenue is not spread evenly between 0 and 100.

Correlation is injected on the standard normals, not on the finished values: a column that correlates with another at ρ is generated as z = ρ·z_base + √(1 − ρ²)·e. Measured over 10,000 rows, a requested ρ = 0.7 comes back as a Pearson r between 0.65 and 0.75, and ρ = 1 reproduces the base column exactly instead of producing NaN.

Clamping to a min/max is available for the normal case and is worth understanding before you switch it on: a value pushed back to the boundary piles up there, so an age column of μ = 38, σ = 12 clamped to 18–80 is no longer normal at the edges. The page raises a notice when clamping actually moved a value, rather than silently distorting the distribution.

  • σ = 0 produces a constant column, and a negative σ is read as its absolute value rather than an error. Log-normal overflow is capped at 1e15 so a runaway parameter cannot put Infinity into your CSV. Minimum above maximum is swapped, not rejected.

A binary target you can actually train on

The ML target type builds a label from a logistic model: pick the contributing columns, give each a coefficient β, and the label is drawn with probability σ(β₀ + Σβᵢzᵢ), where each contributor is standardised first so the coefficients are comparable no matter what units the columns use. A positive β pushes the label towards 1, a negative one away from it.

The intercept β₀ is not guessed — it is solved. A 4,096-row calibration sample is drawn from the same seed and β₀ is found by 60 bisection steps so the positive rate you typed is the rate you get, whatever the coefficients are and however many rows you generate. Ask for 30% and 10,000 rows come back between 28% and 32%; ask for 1% with five strong betas and the bracket expands until it lands.

Label noise flips a fraction of the labels both ways, which is what makes a synthetic dataset non-separable and therefore worth training on. Because flipping works in both directions it also puts a floor under the achievable rate: the pre-noise rate is (π − nz)/(1 − 2·nz), so 1% positives with 2% noise is unreachable and the page says so instead of quietly giving you 2%.

Compared with scikit-learn’s make_classification this covers the same ground — informative features, a controllable class balance, label noise — but the columns keep readable names, the relationship is one you wrote down, and the output is a CSV you can open in a spreadsheet and hand to someone who does not run Python.

Picking an output format

CSV and TSV are for spreadsheets and bulk loaders. Fields are quoted only when they need it, and a missing value is written as an unquoted empty field, "NA" or "NULL" — never as "" — because an empty quoted string reads back into pandas as a string, not as NaN. The UTF-8 BOM is added to CSV and TSV only; on JSON, NDJSON or SQL it would break the parser.

JSON gives one array of objects (indent 0, 2 or 4) for a mock API response or a fixture file. NDJSON gives one object per line with no wrapping array — the format LLM fine-tuning jobs, BigQuery loads and streaming readers expect, and the one pandas reads with pd.read_json(path, lines=True).

SQL emits CREATE TABLE plus INSERT statements for PostgreSQL, MySQL or SQLite, and the column type follows the cell as it will actually be written rather than the field type alone: a Y/N boolean is TEXT, a price with a "$" prefix is TEXT, a true/false target is BOOLEAN on PostgreSQL and INTEGER on SQLite. Duplicate column names are de-duplicated (age, age_2) for SQL, where a repeat would make the script fail outright.

Five starting schemas, and when to use them

Users — id, name, e-mail, phone, joined_at, is_active (80% true). The schema most sign-up screens, admin tables and CRUD demos need, and the fastest way to see whether your list view survives long Korean names.

Orders — UUID order id, customer, quantity 1–5, a log-normally distributed amount, an order timestamp and a weighted status (paid 70% / shipped 20% / refunded 10%). Realistic enough that a revenue chart built on it has the long right tail a real one has.

Churn — age, tenure_months, monthly_fee correlated with tenure at ρ = 0.4, a plan category, and a churn label driven by β = +0.8 age, +1.2 fee, −1.0 tenure at a 20% positive rate with 5% label noise. Fraud is the same idea at a 1% positive rate with six features — the class-imbalance case that breaks naive accuracy scores.

Missing values — five columns with 5%, 10%, 15%, 20% and 30% blanks, for testing an imputation pipeline, a dashboard’s empty states, or a CSV importer that has never met an empty field. Any column in any schema can carry a missing-value percentage; the ML presets are just the ones set up for it.

How to use

  1. Add columns and pick a data type for each.
  2. Set the row count and the language (English or Korean).
  3. Optional: open ML options for distributions, correlation, missing values and a target label.
  4. Choose a format and download or copy.
  5. Optional: set a seed and share the address bar — the other person gets the same data.

FAQ

Is the generated data sent to a server?

No. The schema, the seed and every generated row stay in your browser — there is no upload step and no API call. That matters more than it sounds: column names are often a sketch of an internal database design, and services that generate data on their servers see both the schema and the result.

How many rows can I generate?

Up to 100,000 rows, with no account. Tools that generate on a server usually stop at 1,000–10,000 rows because every row costs them CPU time; here the work happens on your machine, so the limit is only about keeping the page responsive.

Why is my Korean CSV garbled in Excel?

Excel does not auto-detect UTF-8 in a plain .csv file; it falls back to the system code page, which turns Korean into mojibake. A UTF-8 BOM at the start of the file tells Excel what the encoding is. The BOM option is on by default here, and it is added to CSV and TSV only — never to JSON, NDJSON or SQL, where it would break parsers.

Are the names, e-mails and phone numbers real?

No. Names and companies come from faker’s word lists, e-mail local parts are generated tokens, and phone numbers are built to look valid without being assignable — US numbers use the 555 exchange reserved for fiction, and Korean numbers combine real area codes with random subscriber blocks. Addresses are assembled from real 시·도 and city names but random road numbers, so they read correctly and point nowhere. Coincidental collisions with a real address are possible in the way any random string can collide, which is another reason not to publish generated rows as if they described someone.

Can I generate two tables joined by a foreign key?

Not in one pass — the generator produces a single flat table. The usual workaround is two runs: generate the parent with an auto-increment id (start 1, step 1) and note how many rows it has, then generate the child with an integer column drawn uniformly between 1 and that row count as the foreign key. Keep the same seed on both runs and the pair stays reproducible. For a one-to-one link, give the child an auto-increment column with the same start and step.

What is NDJSON (JSONL)?

One JSON object per line, with no wrapping array. It streams line by line, so it is the usual format for LLM fine-tuning datasets, BigQuery and Bag-style data loaders, and pandas reads it with pd.read_json(path, lines=True).

Related tools

More AI & Data tools: AI & Data

Send feedback

Found a bug or have an idea? Tell us — it helps make the tools better.

Only needed if you would like a reply.

Page: /ai/dummy-data-generator/