Skip to main content
⚖️ Cross-Language Standards Standard: Unicode Standard Annex #15 / W3C Character Model Time: 8 min read Reviewed: September 2024

Unicode Normalization: NFC, NFD, NFKC & NFKD

When and how to normalize Unicode strings for reliable string comparison, database queries, and secure user identifier matching.

TL;DR — Direct Answer

Direct Technical Answer

Unicode Normalization converts visually equivalent strings into a unique, deterministic binary sequence so that string equality (===) and database queries work accurately. The four official normalization forms are NFC, NFD, NFKC, and NFKD.

💡
Production Rule: Always use NFC (Normalization Form C) for web input, database storage, and identifier matching. Use NFD only for accent-stripping search indexing, and use NFKC/NFKD with caution because compatibility forms alter semantic formatting.

Canonical equivalence and string comparison with String.prototype.normalize()

JAVASCRIPT normalization-demo.js
// 1. Precomposed 'é' (U+00E9) vs Decomposed 'e' + acute (U+0065 U+0301)
const s1 = '\u00E9';       // é
const s2 = 'e\u0301';       // e + accent

console.log(s1 === s2);       // false (different byte sequences!)
console.log(s1.length);       // 1
console.log(s2.length);       // 2

// 2. Normalizing to NFC (Canonical Composition)
const n1 = s1.normalize('NFC');
const n2 = s2.normalize('NFC');

console.log(n1 === n2);       // true!
console.log(n1.length);       // 1
Program Output
false
1
2
true
1

The Four Normalization Forms

Unicode defines two types of equivalence: Canonical Equivalence (exact visual and functional identity) and Compatibility Equivalence (formatting differences like subscript, superscript, circled, or ligature).

NFC (Normalization Form C: Canonical Decomposition followed by Canonical Composition)

The standard for the World Wide Web. Characters are decomposed and then re-composed into precomposed characters wherever possible. "e" + combining acute becomes precomposed "é" (U+00E9).

NFD (Normalization Form D: Canonical Decomposition)

Characters are decomposed into their base characters and combining marks in a standardized order. Precomposed "é" (U+00E9) becomes "e" (U+0065) + combining acute (U+0301). Excellent for stripping accents in search search indexes.

NFKC (Normalization Form KC: Compatibility Decomposition followed by Canonical Composition)

Applies compatibility decomposition before composing. Ligatures like "fi" become "fi", circled "①" becomes "1", and superscript "²" becomes "2". Useful for search indexing, but destructive for general storage.

NFKD (Normalization Form KD: Compatibility Decomposition)

Applies compatibility decomposition without re-composing.

Common Mistakes vs Production Patterns

Learn which patterns fail in production and the modern standards-compliant alternatives.

Comparing Usernames or Passwords

Authentication, account registration, database queries.
AVOID: ❌ Comparing raw user input
// Attacker registers 'admin' with decomposed characters
if (dbUser === req.body.username) {
  // Can be bypassed or duplicated with visually identical strings!
}
Why it fails: Visual duplicates with different code points can bypass uniqueness constraints or create duplicate accounts.
RECOMMENDED: ✅ Normalize to NFC on ingestion
const cleanUsername = req.body.username.normalize('NFC');
// Query DB with cleanUsername
Why it's better: Guarantees that all canonically equivalent strings map to identical binary keys.

Edge Cases & Invariants Matrix

A diverse cross-character test matrix comparing character behavior across ASCII, combining marks, emojis, flags, and surrogate fragments.

Test Case Input Glyph Code Units Code Points Graphemes Category Technical Explanation
Precomposed vs Decomposed é (U+00E9) vs e + \u0301 Canonical Equivalence Both NFC outputs evaluate strictly equal (===) after normalization.
Circled Number ① (U+2460) Compatibility Equivalence NFC preserves circled styling; NFKC decomposes into ASCII digit 1.
Ligature fi (U+FB01) Compatibility Equivalence NFC keeps ligature character; NFKC expands to two separate ASCII letters.

Standards & Source Provenance

All technical invariants, APIs, and behaviors in this guide are verified against official primary specifications.

Unicode Consortium

Unicode Standard Annex #15: Unicode Normalization Forms

Clause: §1 Normalization Forms

W3C

Character Model for the World Wide Web: String Matching

Clause: §3 Normalization