Surrogate pairs · U+1D407
One visual letter, but two UTF-16 code units underneath — a surrogate pair, not a counting bug.
Why Styled Text Counts Differently Than You Expect
By fontgenerator.tech team · Published 2026-09-06 · Reviewed 2026-09-06
A character counter that says "12" for text that looks like 12 letters can disagree with another counter that says 13, 14, or more for the exact same text. Both can be right — they're counting different things. There are three distinct units in play: graphemes (what a person sees as one character), Unicode code points (one assigned Unicode number), and UTF-16 code units (what many programming languages, including JavaScript, use internally).
A worked comparison
| Text | Graphemes (what you'd count by eye) | Code points | UTF-16 units |
|---|---|---|---|
| Hello | 5 | 5 | 5 |
| café (precomposed é, U+00E9) | 4 | 4 | 4 |
| café (decomposed e + combining ́, e+U+0301) | 4 | 5 | 5 |
| 𝐇 (Mathematical Bold Capital H, U+1D407) | 1 | 1 | 2 (surrogate pair) |
| 👨👩👧👦 (family emoji, a ZWJ sequence) | 1 | 7 | 11 |
The decomposed "café" is the interesting one: it looks and reads identically to the precomposed version, but it's built from two separate Unicode characters (the letter "e" plus a separate combining acute accent) instead of one. A person sees one letter; a naive per-code-point counter sees two. This tool counts it as one character (one grapheme) for style-support purposes — see our accent-preservation guide for why that distinction matters when converting text back.
Why bold/script text takes more "space" in some counters
Most of the letters this tool produces (𝐀, 𝒜, 𝔄, and similar) live outside the Basic Multilingual Plane — the original 16-bit range most systems were designed around. In UTF-16 (used by JavaScript, and internally by many apps), each of those characters needs two 16-bit units, called a surrogate pair, instead of one. A plain "H" is 1 unit; a Unicode-bold "𝐇" is 2. That's one reason a platform's character counter can report a longer count for styled text than for the same plain text, even though a person reading it would count the same number of letters.
What we do about it in this tool
This generator's own input/output limits (2,000 graphemes, 16,000 UTF-16 code units) are enforced using exactly these definitions, and applied in that order — see the engine tests referenced in testing methodology. We don't assume a platform's displayed character counter uses the same rule; if a platform shows a specific documented counting method, we cite it rather than assume it matches ours.
Practical takeaway
If a platform's character counter looks "wrong" after you paste styled text, it's very likely counting UTF-16 units or raw code points, not graphemes — that's a counting-method difference, not evidence that your text is corrupted.
Why this isn't just a technicality
Counting method choices have real, visible consequences. A bio-length limit enforced in UTF-16 units will accept fewer visible bold letters than the same limit enforced in graphemes, because every bold letter costs two units instead of one. A message limit enforced in raw code points will count a family emoji as 7 "characters" even though it displays as a single visual glyph. Neither approach is wrong in isolation — they're different, valid engineering choices — but they can make an interface feel inconsistent if you don't know which one is in play, especially when moving text between two platforms that made different choices.
How to check which counting method a platform is likely using
A quick, informal test: type a single family emoji (👨👩👧👦) or a Unicode-bold letter into the field you're curious about, and watch how much its counter moves. If a lone family emoji drops the remaining-character count by around 11, the platform is likely counting UTF-16 units. If it drops by around 7, it's likely counting raw code points. If it drops by exactly 1, it's counting graphemes — the way a person would actually count it. This isn't a documented API you can rely on programmatically, but it's a fast way to understand what you're working with in the moment.
The same distinction shows up outside character counters too
Grapheme-vs-code-point differences aren't limited to counters — they affect anything that operates on "characters" without being careful about which definition it means. A naive text-truncation function that cuts a string at a fixed number of code points can slice a family emoji or a decomposed accented letter in half, producing a broken, partially-rendered glyph at the cut point instead of cleanly omitting the whole thing. This tool's own input handling is deliberately grapheme-aware everywhere it matters — editing, reversing text line by line, and enforcing input limits — specifically to avoid that class of bug (see our engine tests referenced in testing methodology).
A note for anyone building software, not just writing bios
If you're implementing a character limit or a truncation feature yourself, the practical takeaway is: pick your counting unit deliberately and document it, rather than assuming "length" has one obvious meaning. Most modern languages expose a grapheme-segmentation API (the same UAX #29 standard cited below) precisely because code-point or UTF-16-unit counts so often surprise both developers and users once emoji, combining accents, or Unicode-substituted text enter the picture.
Questions people actually ask
Why does a family emoji count as so many characters at all? It isn't really one emoji at the Unicode level — it's several individual emoji (a man, a woman, a girl, a boy) joined by invisible "zero-width joiner" characters that tell the renderer "draw these as one combined picture instead of four separate ones." Each of those pieces, plus each joiner, is its own code point, which is why the code-point and UTF-16 counts are so much higher than the single grapheme a person sees.
Does this affect how many characters I can style at once? This generator's own caps (2,000 graphemes / 16,000 UTF-16 code units, whichever is reached first) are designed around exactly this distinction, so ordinary typed text rarely comes close to either limit — it mainly matters for very long pastes or text with many multi-unit emoji sequences.
Is there a "correct" way to count characters? For matching what a person perceives as one character, graphemes are the right unit — that's literally what the Unicode grapheme segmentation standard (cited below) is designed to define. For raw storage size, code points or UTF-16 units are more relevant. Neither is universally "correct" — they answer different questions.