Fake ID > Articles > 573 Taiwanese Have a Surname Unicode Cannot Encode

This article has not been translated into English yet — you are reading the English original. Also available in:Deutsch, Українська

573 Taiwanese Have a Surname Unicode Cannot Encode

Taiwan's Ministry of the Interior publishes a surname registry with no privacy threshold. Every surname is listed with its exact bearer count, down to the 643 surnames held by exactly one person out of 23.4 million. It is one of the most complete national name datasets in existence.

Read it to the bottom and you hit rows where the surname column is not a surname. It is a code point that Unicode has never assigned to anything.

There are 23 such rows, carrying 573 people. Those 573 citizens have a legal, registered, government-recognised surname that no standards-conformant piece of software can display, transmit or agree on.

This page is about those 23 rows, and about a second, quieter class of 14 rows in our own corpus that look fine until something normalises them.

What we measured

MeasurementValue
Registry rows (2,731 surnames × 3 age bands)8,193
Distinct surnames2,731
Population base23,373,283
Surname entries containing a Private Use Area code point23
People carrying them573
Distinct PUA code points involved22
RangeU+F9000U+FFFEE
Unicode plane15 (Supplementary PUA-A)
Share of population0.00245%

Verified against tw_surname_112.csv (the ministry's open-data release, reference date 30 June 2023) on 21 July 2026. Twenty-two distinct code points across twenty-three entries, because U+FD13A is used in two different compound surnames.

What a Private Use Area code point is

Unicode reserves three regions where it promises never to assign a character:

BlockRangeSize
Private Use Area (BMP)U+E000U+F8FF6,400 points
Supplementary PUA-A (plane 15)U+F0000U+FFFFD65,534 points
Supplementary PUA-B (plane 16)U+100000U+10FFFD65,534 points

These are not "characters Unicode has not gotten around to." They are code points Unicode has permanently declined to define, so that private parties can agree among themselves what they mean. The Apple logo is at U+F8FF in Apple's fonts and is a blank box everywhere else. That is not a bug; that is the entire design.

The consequence is that a PUA code point has no meaning outside the system that assigned it. It has no name, no character properties worth relying on, no canonical shape, and no guarantee that the next version of anything will render it the same way. Two systems can both be perfectly correct and disagree completely about what U+FBF33 is.

All 23 Taiwanese entries sit in plane 15, between U+F9000 and U+FFFEE.

Why a government registry contains them

Taiwanese household registration (戶籍) records the written form of a name, not its pronunciation. If a family's surname is a rare character that appeared in Qing-era registers and never made it into any modern character standard, the household registration system still has to store it — the citizen exists, the name is on their identity card, and "we cannot encode it" is not an administrative option.

So the ministry did what every East Asian registry has done since the 1980s: it allocated internal code points for the characters it needed and put them in the space Unicode set aside for exactly this. Japan's 住基ネット, China's GB 18030 user-defined area and Hong Kong's pre-HKSCS supplementary sets all did the same thing. The registry is not broken. It is ahead of Unicode, and it has a legal obligation not to wait.

The counts are small but not vanishing:

Code pointBearersNote
U+FBF33179most common unencodable surname
U+FFFEE117
U+FFFD664
U+FC03B63
U+F900044lowest code point used
U+FD70838
U+FCDF416
U+FCBAF12
U+FBD289
U+FB56C7
13 more1–4 each

Five of the 23 are compound surnames that mix an ordinary ideograph with a private one, which is worth seeing because it kills the idea that these are junk rows:

EntryBearers
手 + U+FD13A3
平 + U+FD13A3
山 + U+FB5721
飯 + U+FDFF8 + 谷1
U+FCBAE + 原1

The last two are recognisably Japanese-pattern surnames (飯?谷, ?原) held by one person each — exactly the kind of residue a household register accumulates and a character standard does not.

The 179-bearer surname is not a curiosity. In the registry it would rank 458th by bearer count. That puts it just below 諸葛 (180 bearers — the surname of Zhuge Liang, which every reader of the Three Kingdoms knows) and comfortably above 皇甫 (115), 尉遲 (63) and 司馬 (49). The most common surname Unicode cannot encode is more common than several surnames everyone can name.

What it looks like in a browser

Nothing. A PUA code point with no font coverage renders as the replacement glyph — the notdef box, universally called "tofu" (豆腐), sometimes with the hex digits printed inside it. Which of those two you see depends on the font stack, not on the data.

There is a worse case than a blank box, and it is the reason we do not ship these rows at all. Because PUA is private, some font on some machine may well have a glyph there — a different one. Segoe UI Emoji, Apple's system fonts, a corporate icon font, a legacy Big5 font from a Taiwanese vendor, and a Chinese IME's user-defined character area all claim overlapping parts of the PUA. A surname stored as U+F9000 can render as a box on one machine, a rare ideograph on a second, and a dingbat on a third. The bytes are identical. The name is not.

That is the actual failure mode: not "unreadable", but silently readable as something else.

What we do with them

We exclude all 23. Our Taiwanese corpus carries 2,707 of the registry's 2,731 surnames, and the 24 excluded rows are these 23 plus the aggregate bucket 其他 ("other", 5,174 people), which is a statistical category and not a name.

Measured on the shipped file:

MetricValue
Surnames shipped2,707
Sum of bearer counts23,367,536
Coverage of the registry base99.975%
Excluded rows24
Excluded people5,747

The rule is narrow and worth stating precisely: we do not delete rare surnames, we delete surnames we cannot render. 慕容 (1 bearer), 呼延 (1), 公羊 (1) and 澹臺 (2) are all in the file. Rarity is never a reason to drop a row; a row that produces a blank box on the reader's screen is.

There is no honest alternative here. We cannot substitute a similar-looking character, because "similar-looking" is a judgement about a glyph we have never seen. We cannot transliterate, because there is nothing to transliterate from. We cannot invent a placeholder, because a generated identity carrying U+F9000 is worse than one carrying a real surname. The 573 people are simply outside what a text-based system can represent, and the correct response is to say so rather than to approximate.

The second class: 14 surnames that survive until something normalises them

Zero PUA code points reach our shipped file. But the file does contain 1,780 distinct code points, and they are not all in the block you would expect:

Unicode blockDistinct code points
CJK Unified Ideographs (U+4E00U+9FFF)1,737
CJK Extension B (U+20000U+2A6DF)21
CJK Compatibility Ideographs Supplement14
CJK Extension A (U+3400U+4DBF)6
CJK Extension C (U+2A700U+2B73F)2

The 14 in CJK Compatibility Ideographs Supplement (U+2F800U+2FA1F) are the interesting ones. That block exists purely for round-trip compatibility with older standards, and every character in it has a singleton canonical decomposition: the standard says it decomposes to exactly one other character, and the composition step never puts it back.

The practical translation: NFC, NFD, NFKC and NFKD all turn these characters into an ordinary unified ideograph. Not "may" — the Unicode Standard requires it.

For all 14, the unified twin is already a separate row in the same file, with its own bearer count:

Compat formCode pointBearers→ normalises toCode pointBearersRatio
U+2F8DB87U+675E4615.3×
U+2F84261U+551040,579665×
U+2F87754U+5C6058510.8×
U+2F83F25U+5468282,18511,287×
U+2F81B23U+51B51104.8×
U+2FA1515U+9EBB27518.3×
U+2F96A8U+7D0040,7475,093×
U+2F8D23U+51927424.7×
U+2F9933U+82B13,4991,166×
U+2F8011U+4E3811.0×
U+2F8291U+53054,8004,800×
U+2F85E1U+592222.0×
U+2F8C91U+656C134134×
U+2F9D71U+8D7744.0×

The two columns look identical because on your screen they are identical — same glyph, same shape, different code point. 284 bearers sit on the left-hand side, 0.0012% of the corpus weight.

These are not defects. The ministry keeps them as separate rows because for household registration they are separate written forms, and our file mirrors the registry. But they are a loaded gun pointed at the consumer.

Why the normalisation is the dangerous part, not the encoding

An unencodable surname fails loudly. You see a box, you file a bug. A compatibility ideograph fails silently, and only in some layers of your stack.

Consider a single record travelling through an ordinary web application:

  1. The database holds 周 U+2F83F (25 bearers) and 周 U+5468 (282,185 bearers) as two rows.
  2. A JavaScript front-end runs name.normalize() before sending a search query — the current, recommended practice. U+2F83F becomes U+5468. Two surnames are now one.
  3. A PHP back-end without the intl extension cannot normalise at all: Normalizer does not exist. (Our local PHP 8.5.8 build is exactly this case — we verified it.) So the same string travelling the other way stays U+2F83F.
  4. A search index with an ICU normalisation filter folds them; a LIKE query does not.
  5. A macOS client writing the name into a filename gets NFD from the filesystem; a Linux client does not.

Nothing in that chain is wrong. Every component behaves as documented. The record still ends up with two different identities depending on which door it came through.

Two more concrete symptoms:

Length is not length.U+2F83F is 4 bytes in UTF-8 and 2 code units in UTF-16; 周 U+5468 is 3 bytes and 1 code unit. So LENGTH() in MySQL returns 4 vs 3, JavaScript's .length returns 2 vs 1, and a VARCHAR(1) column will reject one of the two. A "one character" surname fails a one-character validation.

Unique indexes go either way and you cannot tell which. Whether utf8mb4_unicode_ci treats these as equal depends on the UCA version your server implements and on whether the collation normalises at all — and we have deliberately not tested a live MariaDB for this page, so we are not going to tell you what yours does. What we can tell you is that the answer is not obvious, that it can change on a server upgrade, and that if your uniqueness constraint on a name column silently starts rejecting an insert after a minor version bump, this is the family of reasons why.

The row that makes the point best is 丸: U+2F801 has one bearer and U+4E38 has one bearer. Normalise, and you have one surname with two bearers and no record that two separate households registered two different glyphs. The arithmetic is preserved. The fact is gone.

What to do

Decide where normalisation happens, once, and write it down. Not "we use NFC" — which layer applies it, on write or on read, and what the storage form is. A system where three layers each normalise independently is a system where the storage form is whatever the last writer happened to be.

Store the registered form; derive the search form. Same shape as the sorting problem for prefixed European surnames: display and matching want two different strings. Keep the byte sequence the registry gave you in one column, and build an explicitly normalised key in another for lookup, joins and uniqueness. Do not make the normalised form the only form.

Do not normalise names as a cleanup step. NFC on user-supplied text at the edge of your API is reasonable; NFC over a name column in a migration is data loss with a commit message. The 14 rows above are 284 people whose registered surname differs from another surname only in code point, and a single UPDATE ... SET name = NORMALIZE(name) merges them with no error and no way back.

Validate on renderability, not on plausibility. If you filter name input at all, a reasonable rule is "reject code points in the Private Use Areas" — not because they are invalid, but because you cannot promise the recipient will see what the sender typed. That rule is narrow, defensible, and does not accidentally reject 慕容 or 澹臺.

Expect the registry to be right and the standard to be behind. Every time we have found a name our tooling could not handle, the tooling was the problem. U+FBF33 is 179 living people; the fact that ISO 10646 has no code point for their surname is a fact about ISO 10646.

Known limitations

  • We cannot tell you what the 23 characters look like. We have their code points, not their glyphs. The ministry does not publish a glyph mapping with the open dataset, so we can report that these people exist and not what their surname is.
  • We have not tested collation behaviour on a live database. The claim in this page about MariaDB is deliberately an admission of uncertainty, not a finding.
  • The 14 compat rows are shipped unmerged, on purpose. Merging them would change 14 bearer counts and destroy a distinction the registry makes. Our position is that a consumer who needs them merged should merge them knowingly, in their own key column.
  • The registry's own reconciliation is unexplained. The ministry elsewhere states that Taiwan has 1,785 surnames, while the open dataset carries 2,731 rows. We have a plausible reading of the gap and no confirmation of it.

Data as of 2026-07-21

Registry reference date 30 June 2023 (民國112年6月30日), published by 內政部戶政司 under the Government Open Data Licence v1. All figures on this page were recomputed from the raw CSV and from our shipped weight file on 21 July 2026; the male and female surname files are byte-identical, because Taiwanese surnames do not inflect for gender.

Sources

← Articles