Make equal-looking text actually equal
Unicode often lets you write the same character more than one way. The letter “é” can be a single precomposed code point (U+00E9), or an “e” (U+0065) followed by a separate combining acute accent (U+0301). Visually identical, byte-for-byte different. Normalization rewrites text into one of four canonical forms so that equivalent strings become identical, which is essential for comparison, search, sorting and security. This tool shows all four forms — NFC, NFD, NFKC, NFKD — for any text you paste, with the resulting code-point count for each.
The four forms explained
Normalization runs in two stages: decompose, then optionally re-compose.
- NFD (Canonical Decomposition) breaks composed characters into base + combining marks, ordered by Canonical Combining Class. The string may get longer.
- NFC (Canonical Composition) decomposes, then recombines into precomposed characters where one exists. This is the shortest canonical form and the recommended form for the web and storage.
- NFKD (Compatibility Decomposition) decomposes using compatibility mappings too, so the ligature
fibecomesf+i, full-widthAbecomesA, and the superscript²becomes2. This is lossy. - NFKC (Compatibility Composition) applies compatibility decomposition, then recomposes. Best for identifiers, search indexes, and deduplication.
Browsers expose all four directly through "text".normalize("NFC"), which is exactly what this tool calls under the hood.
Worked example
Paste the string café where the é was typed as two code points (e + combining accent). NFD keeps it decomposed at 5 code points; NFC composes it back to 4 code points. NFKC additionally folds the full-width space or superscript if present. The code-point count shifts visibly in the output column, even though the rendered text looks identical in all four forms — which is exactly the kind of surprise that breaks naive === comparisons in code.
For a clearer compatibility transformation: the Roman numeral Ⅷ (U+2167, one code point) becomes VIII under NFKC — four separate letters. The canonical forms leave it untouched.
When to use each form
| Goal | Form |
|---|---|
| Store or display text (web, database) | NFC |
| Compare accent-sensitive with separate marks | NFD |
| Fold lookalikes for search or matching | NFKC |
| Decompose for custom collation | NFKD |
Common mistakes and edge cases
Only normalise both sides. Normalising only the input and comparing to an unnormalised stored string still breaks equality. Both strings must share the same form.
K forms are lossy. Once you apply NFKC or NFKD, you cannot recover the original ligature or width variant. Never use a K form as the stored representation of user-visible text.
Length changes are expected. A string that is 10 characters in NFC may be 12 in NFD because combining marks split off. Never assume .length is stable across normalization — this is a frequent source of off-by-one bugs in text processing.
Security implication. Username systems that skip normalization allow admin (ASCII) and аdmin (Cyrillic а, U+0430) to co-exist as separate accounts that look identical. NFKC catches width variants; a separate confusable-character check is needed for script mixing.