One character, one heart; one name, one fate

Chinese Surnames as Open Data

Anyone who has tried to build something with Chinese surnames runs into the same wall. A surname list for a registration form has no pinyin, so you cannot sort it, search it or transliterate it. A genealogy table has pinyin but no licence. A scraped CSV has three thousand rows, half of them duplicates, and "欧阳" split into two separate characters somewhere in row 1,842.

So I compiled one properly and released it. 109 surnames, 16 fields per record, Mandarin pinyin with tone marks, the era each surname took shape, the founding ancestor recorded in the histories, the place of origin, the commanderies and hall names that identify a clan branch, the 2020 national population rank where one has been published, notable historical bearers, and a prose note explaining how the surname came to exist.

109records
30compound surnames
30with 2020 rank
42with a population figure
16fields

Quick start

Both files are served with Access-Control-Allow-Origin: *. No key, no signup, no proxy — a plain fetch from the browser works.

From the shell:

curl -s https://naming-cn.pages.dev/data/surnames.json \
  | jq -r 'sort_by(.rank_num | . // 999) | .[] | select(.rank_num) | "\(.rank_num)\t\(.surname)\t\(.pinyin)"'

From JavaScript:

const rows = await fetch('https://naming-cn.pages.dev/data/surnames.json')
  .then(r => r.json());

const byRank = rows.filter(r => r.rank_num)                  // the 30 with a 2020 rank
  .sort((a, b) => a.rank_num - b.rank_num);
const byName = rows.find(r => r.surname === '李');            // exact lookup
const li     = rows.filter(r => /^li/.test(r.slug));         // pinyin prefix, tone-free

From Python:

import pandas as pd
df = pd.read_csv('https://naming-cn.pages.dev/data/surnames.csv')
ranked = df.dropna(subset=['rank_num']).sort_values('rank_num')   # 30 rows, already numeric
populated = df.dropna(subset=['population_est'])                  # 42 rows

The CSV is UTF-8 with a BOM so Excel opens it without mojibake. Array fields (junwang, tanghao, notables) are pipe-separated (|) in the CSV and proper arrays in the JSON; use the JSON if you need the hall names' derivations, which the CSV flattens to names only.

What a record looks like

This is the Li 李 entry, complete except for one hall name trimmed for length:

{
  "surname": "李",
  "slug": "li3",
  "pinyin": "lǐ",
  "era": "商末",
  "ancestor": "李利贞(血缘始祖皋陶)",
  "origin": "河南鹿邑",
  "junwang": ["陇西", "赵郡"],
  "tanghao": [
    { "name": "陇西堂", "note": "以郡望立堂,出自陇西一系" },
    { "name": "青莲堂", "note": "李白自号青莲居士,后世一支取为堂号" }
  ],
  "rank": "全国第 2 位",
  "rank_num": 2,
  "population": "约 1.01 亿人",
  "population_est": 101000000,
  "notables": ["李耳(老子)", "李广", "李世民", "李白", "李时珍"],
  "origin_note": "嬴姓。舜时皋陶任大理(掌刑狱),子孙以官为氏称「理」。……遂改「理」为「李」。",
  "url": "https://naming-cn.pages.dev/xing/li3"
}

The story compressed into origin_note is the reason this surname exists: Gao Yao served as minister of justice under Shun, his descendants took the office as a clan name (理, "to judge"), and in the last years of the Shang a persecuted official's widow fled with her infant son and survived by eating the fruit of a plum tree — so 理 became 李, "plum". slug is the tone-numbered pinyin, which is also the URL key for the detail page.

Field reference

FieldTypeMeaning
surnamestringThe surname in Chinese characters, one character or two for a compound
slugstringTone-numbered pinyin used as the site's URL key, e.g. li3, ouyang2
pinyinstringMandarin reading with tone marks, e.g. lǐ
erastringPeriod in which the surname mainly took shape, e.g. 商末 (late Shang), 西周 (Western Zhou)
ancestorstringFounding ancestor as recorded in the histories; competing traditions are listed side by side
originstringPlace of origin, given as a modern administrative location for join-ability
junwangstring[]Commanderies — the regions where a clan branch rose to prominence, the key coordinate for rank from the Wei–Jin to the Tang
tanghaoobject[]Hall names, each with name and note explaining its derivation
rankstring | emptyNational population rank per the 2020 MPS report, as a display string — "全国第 2 位"; empty when no official rank exists
rank_numinteger | nullThe same rank as a number, 2. Sort on this one; null when there is no rank
populationstring | emptyPopulation estimate as written in the source, e.g. "约 1.01 亿人"; "人数稀少" means recorded as rare with no figure; empty means unknown
population_estinteger | nullPopulation in persons, e.g. 101000000. null for both "rare" and unknown — never filled with 0
population_sourcestringProvenance of the figure: mps2020 (quoted verbatim from the 2020 report, compound surnames only), estimate (other statistics or estimates, mixed years), qualitative ("人数稀少" only), or empty
notablesstring[]Historical bearers of the surname, useful for judging how a name reads in context
origin_notestringProse account of the surname's origins, in Chinese
urlstringFull detail page for that surname

Coverage and known gaps

The records were not chosen by population. They are the surnames that already have a finished detail page on the site, which is why rare compounds like Wanyan 完颜 and Yuchi 尉迟 sit next to Wang 王 and Li 李. Read the following four caveats before you trust a join:

Common questions

What exactly is in the 109 records?

Every surname that already has a full detail page on the site — not the 109 most common surnames by population. 79 are single-character surnames and 30 are compounds such as Ouyang 欧阳, Sima 司马 and Zhuge 诸葛, so rare names like Wanyan 完颜 and Yuchi 尉迟 sit next to Wang and Li.

Is it free for commercial use?

Yes. CC BY 4.0 permits copying, modification, commercial use and redistribution. The only requirement is attribution plus a link to the licence.

Why do only 30 records have a national population rank?

Because that is all the source publishes. The 2020 national name report ranks the top 100 surnames and publishes no per-surname headcount in that table; nothing official exists below the cut-off. Rather than interpolate, the other records leave the rank fields empty. 12 compound surnames do carry an official figure — from the report's separate compound-surname section — but no rank.

Why keep rank as a string once rank_num exists?

rank is what the detail pages render, and keeping it means the data matches what a reader sees on the site. rank_num is what code should use. Keeping both is cheaper than asking every consumer to parse Chinese numerals.

Can the JSON be fetched straight from a browser?

Yes. Both files are served with Access-Control-Allow-Origin: *, so a plain fetch works with no proxy, API key or signup.

Are the origin notes in Chinese?

Yes. Field names and structural values are in English, but the free-text origin note, ancestor names and place names are in Chinese, because the source material is Chinese historical literature. The fields you filter or join on — pinyin, era, rank_num, population_est, slug — are machine-friendly.

Where the numbers come from

Ranks: the Ministry of Public Security's 2020 national name report — the only official Chinese surname statistics published at national scale, and it ranks the top 100 without publishing headcounts. Figures for the 12 compound surnames: the same report's "common compound surnames" section, quotable verbatim. Figures for the 30 ranked single-character surnames: other statistics and estimates of mixed vintage, labelled estimate in population_source — treat them as magnitudes, not as official counts. Commanderies: the standard surname books of the Tang and Song. Hall names: clan genealogies and surviving ancestral halls. The synthesis — pulling these into one record per surname with a readable origin note — is the site's own work, and errors in that synthesis are the site's own responsibility.

Licence and citation

CC BY 4.0. Copy it, modify it, ship it in a product, redistribute it — the only condition is attribution and a link to the licence.

Chinese Naming (2026). Chinese Surnames Open Dataset.
https://naming-cn.pages.dev/en/chinese-surnames-dataset (CC BY 4.0)

BibTeX, if you need it:

@misc{chinesenaming_surnames_2026,
  title  = {Chinese Surnames Open Dataset},
  author = {{Chinese Naming}},
  year   = {2026},
  note   = {109 records, CC BY 4.0},
  url    = {https://naming-cn.pages.dev/en/chinese-surnames-dataset}
}

In a README, one line is enough: Surname data from Chinese Naming — https://naming-cn.pages.dev/en/chinese-surnames-dataset (CC BY 4.0).

This dataset is compiled from the site's 109 surname pages. National ranks and the 12 compound-surname figures are quoted from the Ministry of Public Security's 2020 national name report; figures for other surnames are estimates from mixed sources and are labelled as such in population_source — please do not cite them as official. Commanderies and hall names come from Tang and Song surname books and clan genealogies. Where the sources disagree, the record preserves both readings instead of deciding between them — check the primary literature before using the data in academic work. Corrections are welcome via the message board; verified fixes ship as a new version.

Version history

VersionDateChange
2.12026-11-15Added population_source (mps2020 / estimate / qualitative / empty) so the provenance of every figure is explicit. Also corrected the documentation: the 2020 report ranks the top 100 without headcounts, so only the 12 compound-surname figures are quotable verbatim. Five rows where the estimate sorts against the rank are now documented rather than hidden.
2.02026-11-15Added rank_num (integer rank) and population_est (population in persons), so sorting no longer requires parsing Chinese display strings. Both are null where the figure is unknown. No other field changed.
1.02026-11-13First release: 109 records, 13 fields.

A v1 consumer keeps working: the two new fields are additive, and every existing field name, order and value is unchanged. If you would rather pin a version, take the file now and keep a copy — the URLs always serve the latest release.

Related