data.placeholder.com/people
Synthetic people and datasets
Realistic, fully synthetic personas for Sweden, Norway, the United Kingdom and the United States. Names fit the country, addresses validate, and identifiers come from official test ranges. Person 4711 in Sweden is the same person forever.
Quick start
https://data.placeholder.com/people/se/1one Swedish persona (JSON)https://data.placeholder.com/people/no/42.jsonNorwegian persona 42https://data.placeholder.com/people/gb.csv?count=100&seed=1100 British personas as CSVhttps://data.placeholder.com/people/us.ndjson?count=10001,000 American personas, one JSON object per linehttps://data.placeholder.com/people/se.sql?count=500&table=customersaCREATE TABLE customersplus 500INSERTshttps://data.placeholder.com/peopleindex: countries, ranges and their sources
curl -s "https://data.placeholder.com/people/se.csv?count=10000" -o people-se.csv
psql mydb -f <(curl -s "https://data.placeholder.com/people/no.sql?count=1000&table=users")
Endpoints
| URL | Returns |
|---|---|
/people/<cc>/<pid> | One persona. cc: se, no, gb, us. pid: 1 to 1,000,000. .json optional. |
/people/<cc>.<format>?count=N&seed=S | A batch. format: json (default), ndjson, csv, sql; as extension or ?format=. |
/people | Index with every country's ID, phone and IBAN rules and sources. |
| Parameter | Values | Default |
|---|---|---|
count | 1 to 10,000 per request | 10 |
seed | 1 to 100. Seed S returns persona IDs (S−1)×10,000+1 onwards, so seeds never overlap and a smaller count is a prefix of a larger one. 100 seeds × 10,000 = a million distinct people. | 1 |
table | SQL table name, [A-Za-z_][A-Za-z0-9_]{0,62} | people |
download | 1 adds Content-Disposition: attachment to JSON. CSV, NDJSON and SQL always download as a file. | off |
Errors are JSON, e.g. {"error": "...", "status": 400}. Too large a count is a 400, not a silent truncation.
What a persona looks like
{
"id": "se-1",
"country": "SE", "locale": "sv-SE", "version": "v1", "synthetic": true,
"first_name": "Magnus", "last_name": "Magnusson", "full_name": "Magnus Magnusson",
"gender": "male", "birth_date": "1968-05-22", "age": 57,
"national_id": {
"type": "personnummer", "value": "680522-9272",
"test_range": true, "format_valid": true,
"source": "https://www.skatteverket.se/…", "note": "Skatteverket test personnummer, never issued …"
},
"email": "[email protected]",
"phone": { "e164": "+46701740633", "national": "070-174 06 33", "type": "mobile",
"fictional_range": true, "source": "https://www.pts.se/…" },
"address": { "street": "Ringvägen", "house_number": "71", "postal_code": "214 13",
"city": "Malmö", "region": "Skåne län", "country": "SE",
"country_name": "Sverige", "formatted": "Ringvägen 71, 214 13 Malmö" },
"iban": { "value": "SE3550000000054910000003", "test": true, "kind": "psp_test",
"source": "https://docs.stripe.com/testing?payment-method=sepa-direct-debit" },
"employer": { "name": "Arkvant Energi AB", "title": "Sjuksköterska" },
"username": "magnus_magnusson1",
"avatar_url": "https://via.placeholder.com/avatar/Magnus%20Magnusson.png?seed=se-1"
}
All keys are always present; nested values can be null where a country has no such thing (US personas have no IBAN). CSV and SQL flatten nested objects into national_id_value, phone_e164, address_city and so on, with the same 38 columns for every country. SQL is a portable subset: standard types, booleans as SMALLINT 0/1, one INSERT per row.
How safe is each field?
Every value is generated, but some formats can collide with reality. Each persona says how safe its values are:
national_id.test_range: true: an officially reserved test or never-issued range.format_validsays whether ordinary validators accept it.phone.fictional_range: true: a regulator-reserved number for fiction and tests.iban.test: true: a published payment-provider test IBAN. Shared by many personas.- Emails are always on
example.com,example.orgorexample.net(RFC 2606) and can't be delivered. - Addresses: postcode and city pairs are real, so address validation passes; street names and numbers are generated.
- Names and employers are random combinations. Any match with a real person or company is coincidence.
| Country | National ID | Phone | IBAN |
|---|---|---|---|
| SE | Skatteverket test personnummer, picked from the official CC0 list | PTS fiction ranges, e.g. 070-174 06 05 to 99, 08-465 004 xx | Stripe test SE35… |
| NO | Synthetic fødselsnummer (month + 80), valid mod-11 | Nkom 68 05 xx xx | Stripe test NO93… |
| GB | National Insurance number with prefix QQ (never issued; fails strict validators) | Ofcom drama numbers: 07700 900xxx, city ranges, 01632 960xxx | Stripe test GB82WEST… |
| US | SSN 000-xx-xxxx (never assigned; fails strict validators) | NANP NPA-555-0100 to 0199 | none |
Don't add UNIQUE constraints on national_id, phone or iban: the safe pools are small (95 Swedish mobile numbers, one test IBAN per country). id, email and username are unique per country.
Finland and Denmark are implemented but withheld: neither has an official fictional phone range, and Denmark has no test CPR range. /people/fi/1 returns 404 with the reason. The safe test values reference covers them anyway.
Determinism
- Same country and ID → identical persona, forever. Version 1 is frozen; a change would be
v2. - No field depends on the clock:
ageis computed against the fixed date 2026-01-01. Adults only, aged 18 to 79. - Everything is derived from a hash of the country, ID and field name. No random module, no database.
- Responses are cached for a year (
immutable) and carryX-Placeholder: data.placeholder.com.
Address data
SE and US: GeoNames postal codes (CC BY 4.0); US filtered to US Census 2020 ZCTAs (public domain). NO: Kartverket, Postnummerområder (CC BY 4.0). GB: OS Code-Point Open, Open Government Licence v3. Contains OS data © Crown copyright and database right 2026; contains Royal Mail data © Royal Mail copyright and database right 2026; contains National Statistics data © Crown copyright and database right 2026. GB city labels are derived from local-authority districts and post towns; Northern Ireland is not covered.