Toolvore

Mock Data Generator

Generate fake names, emails, and rows as JSON or CSV.

This tool runs entirely in your browser. Your data is never uploaded, never stored, and never leaves your device.

Generate up to 1,000 dummy records of invented people — id, first and last name, email, age, city, job title and phone number — as a JSON array or a CSV table, for seeding a database or filling a UI you are still building.

How to use it

  1. 1Set the row count, anywhere from 1 to 1,000.
  2. 2Choose JSON for an array of objects, or CSV for a header row plus data lines.
  3. 3Press Generate, then copy the block — or press it again for an entirely new set.

Example

Input
3 rows, CSV
Output
id,firstName,lastName,email,age,city,job,phone — followed by three comma-separated rows, ids 1 to 3

The header line is fixed; every value beneath it is redrawn on each press, so no two presses produce the same table.

What happens to your data

Nothing real goes in and nothing is fetched: the rows are assembled by Math.random picking from five constant arrays compiled into the page — 35 first names, 33 surnames, 16 cities, 13 job titles and five placeholder mail domains such as example.com and mail.test. Ages are 18 plus a random 0–59, phone numbers are digits glued to a +1 prefix, and each press replaces the previous batch in state rather than adding to it.

Last updated August 2026

A list view looks fine with three rows in it. Then someone opens it with two hundred: the pagination is wrong, a long surname wraps onto a second line, and the column you sized by eye pushes the buttons off the right edge. That is what usually sends people looking for fake records — not data as such, but enough rows in roughly the right shape to make a screen behave as it will in front of a real user.

Decide before you generate whether you want a fresh set or a fixed one. Every press redraws every value, which is right for filling a screen and wrong for anything that asserts on what it sees — a test expecting the third row to read Patel passes this afternoon and fails tomorrow. If the rows are going into a seed script, a fixture file or a Storybook story, generate once, paste the block into a file and commit it.

Then settle whether eight columns of person are enough. The set of fields is fixed: there is no field picker, no dates, no company names, no street addresses and no currency amounts. A schema that wants a signup date or an order total gets that column added by hand in a text editor afterwards.

The common mistake is assuming the values are unique. Only the id is. Names, cities and jobs are drawn independently for every row, so repeats inside fifty rows are ordinary rather than a fault, and a unique constraint on anything but id will object.

How it works

Toolvore builds every row inside the page from five constant lists compiled into the JavaScript, picking each value with Math.random and assembling the email from the two names already chosen, a number under 99 and one of five placeholder domains. The id is the loop index plus one, so it always runs 1 to n and restarts at 1 on the next press. JSON comes out of JSON.stringify at two-space indentation, and the CSV takes its header from the keys of the first row, so both formats carry the same columns in the same order; a field is escaped when it contains a comma, quotation mark or newline, though none of the values it can produce ever do. Two weaknesses are worth naming. The randomness is not seeded, so no batch can be reproduced, and pressing Generate discards the previous one rather than adding to it — copy first. And the fields are independent draws, so nothing correlates: a nineteen-year-old Architect in Dubai is as likely as any other row, and the phone number wears a +1 prefix whatever the city says.

Common use cases

  • Filling a list view to see how it behaves at two hundred rows rather than three
  • Seeding a local database table while writing the first migration
  • Checking a layout survives a long surname next to a long job title
  • Testing an import routine that expects a header row
  • Handing a front-end a JSON array to work against before the API exists
  • Building a demo screen that must not show a real customer

Frequently asked questions

Is it legal to use real customer data in a test or staging environment?

Under the UK GDPR and its EU counterpart, testing is a different purpose from the one people handed over their details for, so copying a production table into a development database needs its own lawful basis and usually fails on purpose limitation alone. Staging environments also tend to have weaker access control, longer-lived backups and more people holding credentials than production does, which is why they appear so often in breach reports. Synthetic rows avoid the question: no subject, no retention clock, nothing to report if a laptop goes missing. Where production-shaped data is genuinely needed, a masked or tokenised extract is the usual answer.

Are the names and email addresses real, and could I accidentally email one?

The names are common given names and surnames drawn from lists inside the page, so a match to a real person is coincidence rather than a record of anyone. The addresses need more care. Two of the five domains — example.com, and anything ending .test — are reserved by the IETF so they can never be registered, and post to them goes nowhere. The other three sit in ordinary registrable namespaces and someone may own them. If these rows can reach a mail server, which a staging environment with live SMTP credentials can, point the lot at a catcher rather than trusting the domain.

How many rows do I actually need to test with?

More than you expect for layout, fewer than you expect for speed. Twenty to fifty rows expose what actually breaks: a pagination boundary, a surname long enough to wrap, a nearly empty second page, a sort that looks right on ten rows and wrong on forty. A thousand shows whether a list renders without stalling and whether a query is missing an index. Past that the interesting failures are database-shaped rather than screen-shaped, and a browser writing text is the wrong instrument — a loop in your seed script will reach a million rows and this will not.

Should I take the JSON or the CSV?

JSON if the rows are going into code, CSV if they are going into a database or a spreadsheet. The JSON is an array of objects carrying the field names on every record, which suits a fixture file, a fetch mock or a stubbed API route. The CSV is a header line and one line per row, which is what psql's COPY, MySQL's LOAD DATA, SQLite's .import and every spreadsheet expect. Both carry identical columns in identical order, so the choice is only about the destination. Neither is SQL: no INSERT statements are produced, so an import step is the shorter route into a table.

How do I load a CSV of fake records into a database table?

Save the copied block as a .csv file first — there is no download button, so it goes via your editor. Then match the columns: the header reads id, firstName, lastName, email, age, city, job, phone, and camel case names in Postgres need quoting in the DDL or they fold to lower case, which is where most people trip. Load with COPY … FROM 'rows.csv' CSV HEADER in psql, LOAD DATA INFILE with IGNORE 1 LINES in MySQL, or .import --csv --skip 1 in SQLite. Make id a plain integer rather than an identity column, or the supplied ids and the sequence will disagree.

Does any of this leave my browser?

No. The word lists are constants compiled into the page's JavaScript, the rows are assembled by Math.random on your own machine, and nothing is fetched or posted at any point — there is no request to make, because there is no source of names to call. The output lives in the page's state and in the read-only box you copy from, so closing the tab is the whole of the cleanup, and each press replaces the previous batch rather than keeping a history. Nothing real goes in either way, but the same design means it keeps working with the network off.

Why do the same names keep coming back, and how do I get unique values?

Because each field is an independent draw from a short list, and short lists collide quickly. With thirty-five first names, a repeat is more likely than not by the eighth row, and the city and job lists are shorter still. Only the id is guaranteed distinct, because it counts rather than draws. If a column has to be unique, the practical fixes are to append the id to the value in a text editor, to drop the column and let the database assign a key, or to generate more rows than you need and de-duplicate before loading.

Can I use fake records in an automated test that must pass every time?

Only if you freeze them. Nothing is seeded, so two presses with the same settings give different rows and there is no way to ask for yesterday's batch. That is fine for a screenshot or a manual walkthrough and fatal for an assertion on a value. The working pattern is to generate once, paste the block into a fixture file beside the test and let version control hold it, so a change to the data turns up in a diff. Data that varies per run and is still reproducible on failure needs a seeded generator in your own test code.