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.