Understanding Unicode Normalization: NFC vs NFD
Have you ever typed the word “café” on a Mac and then copied it to a Linux server, only to find that a simple string comparison suddenly fails? This is not a bug in your code. It is a direct result of how Unicode handles text representation through a process called normalization.
Unicode allows the same visible character to be represented in more than one way. For example, the letter “é” can be stored as a single precomposed character or as two separate characters: the base letter “e” followed by a combining acute accent mark. These two forms look identical on screen but are completely different at the binary level.
What Are NFC and NFD?
NFC stands for Normalization Form C, also known as composed form. In this format, characters are combined whenever possible into a single code point. NFD, or Normalization Form D, is the decomposed form, where characters are broken down into their base letter and separate combining marks.
Most Windows and Linux applications use NFC by default. Apple’s macOS and iOS, however, use NFD as the standard file system and text storage format. This difference creates silent incompatibilities when text moves between platforms.
Why Does This Matter?
- File names that appear identical may not match in comparisons
- Database searches can miss results if one entry is normalized and another is not
- User input from different devices can cause duplicate records
- Security systems may fail to detect malicious homograph attacks using combining marks
The Solution: Always Normalize
The most reliable approach is to normalize all text to a single consistent form as early as possible, ideally at the point of input. Converting everything to NFC is the most widely recommended practice because it reduces storage size and improves performance in most text-processing operations.
Modern browsers already include built-in support for this through JavaScript’s normalize method, making it possible to perform instant, private, client-side normalization without any external dependencies or data transmission.
Understanding normalization is essential for building robust, cross-platform applications that handle text reliably in any environment.