Unicode Graphemes, Code Points, and Character Counts
Understand why one visible symbol can contain several code points and how the site’s counters and reverse tools handle it.
The word “character” can mean at least three different things in software: a user-perceived unit, a Unicode code point, or a UTF-16 code unit. They coincide for many plain Latin letters and diverge for accented text and emoji. Knowing which unit a tool uses explains why a character counter and a string-length check can disagree.
In this guide
- One display unit can have several parts
- Why reversal needs segmentation
- Choose the right unit
- Test with your destination
One display unit can have several parts
The string “é” can be stored as e followed by a combining acute accent. Many readers see one letter, but the encoding contains two code points. A family emoji may involve several people symbols joined by zero-width joiners and still appear as one displayed cluster. Unicode calls a default user-perceived text unit a grapheme cluster.
The Character Counter reports grapheme clusters first, then code points, then JavaScript UTF-16 units. For “A😀,” those counts are two clusters, two code points, and three UTF-16 units: the emoji needs a surrogate pair in UTF-16. For a decomposed accented letter, clusters and code points also differ.
InputA😀Output
2 characters (2 code points, 3 UTF-16 units)
Why reversal needs segmentation
Reversing a JavaScript string one UTF-16 unit at a time can split a surrogate pair. That is how the legacy homepage Reverse Text, Horizontal mirror, and Flip tabs reverse order, so an emoji may become broken text. Reversing code points avoids that specific damage but may detach a combining accent from its base letter or split a joined emoji. The separate /tools/flip-text page uses Intl.Segmenter when available to reverse grapheme clusters within each line.
The separate newer tool pages fall back to Array.from when Intl.Segmenter is unavailable, which groups by code point and may still split combining sequences or joined emoji. That fallback does not describe the homepage: its older reversal script uses split('') over UTF-16 units regardless of browser segmentation support. If Unicode integrity matters, choose a grapheme-aware dedicated tool page and inspect the result in the target browser.
Choose the right unit
For visible text limits, grapheme clusters are often useful. For debugging Unicode data, inspect code points. For storage or network protocols, count encoded bytes; Text to Hex and Text to Binary show UTF-8 bytes. None of these counts is inherently wrong: each answers a different question.
Word segmentation is another separate problem. This site’s Word Counter uses a regular expression for runs of letters and numbers, including internal apostrophes. It does not apply Unicode’s full language-aware word-boundary rules. A script with no spaces deserves particular scrutiny when a word limit matters.
- Visible units: grapheme clusters.
- Unicode identities: code points.
- JavaScript storage length: UTF-16 units.
- Encoded transfer size: UTF-8 bytes.
Test with your destination
Paste a sample containing a combining accent and emoji into both this counter and the destination platform. If limits differ, use the destination’s definition for submission. For reversal, check that the displayed units remain intact after copying the output.
A further source of confusion is normalization: the same visible accented letter may be represented as one precomposed code point or as a base letter plus combining mark. Both can form one grapheme cluster while producing different code-point and byte counts. If a system compares raw strings, those forms may differ unless it normalizes them. The counters expose the difference; they do not alter the source. For debugging, record the exact input alongside its code points.
Frequently asked questions
Is one emoji always one character?
No. Some emoji are multi-code-point sequences that form one grapheme cluster; the count depends on the specific sequence and segmentation support.
Why does JavaScript length differ?
JavaScript strings use UTF-16 code units, and supplementary code points occupy two of them.
What happens without Intl.Segmenter?
The character counter and newer dedicated reversal tools fall back to code-point iteration, which can split multi-code-point graphemes. The homepage’s legacy Reverse Text, Horizontal, and Flip tabs reverse UTF-16 units regardless of Intl.Segmenter.