ForHosting KIT · Developer Utilities

Unicode NFD normalizer

The word café, written with one é, comes out as five code points: c, a, f, e and a combining acute accent. Every precomposed letter is split into its base and marks, so strings that look identical compare as equal once both are in NFD. Free in your browser.

  • Free
  • Runs in your browser
  • No sign-up
  • Your data stays on your device
Use it from WebAPIEmailTelegramApp soon
If you enter
Text
café
You get
Result
café
Form
NFD
Length in
4
Length out
5

Unicode Normalization Form D, or NFD, rewrites a string so that every precomposed character is expanded into a base character followed by the combining marks that define its appearance. A single café with a precomposed e-acute becomes the five code-point sequence c-a-f-e plus combining acute; Hangul syllables split into jamo; Å becomes A plus a combining ring.

What NFD canonical decomposition actually does

Unicode stores many accented letters in two ways: as a single precomposed code point such as U+00E9 for Latin small letter e with acute, or as a base letter U+0065 followed by the combining acute accent U+0301. Both sequences look the same when rendered, but they are different byte sequences, break string equality, and can surprise length checks, regexes, and database unique constraints.

Normalization Form D, defined in Unicode Standard Annex 15, applies canonical decomposition: every character that has a canonical decomposition mapping is replaced by that mapping, and combining marks are ordered by their combining class so that equivalent sequences become identical. NFD does not recompose afterward; that recomposition step is NFC. NFD also does not apply compatibility mappings, so a ligature such as fi or a fullwidth digit stays as itself—compatibility decomposition belongs to NFKD and NFKC.

Hangul syllables receive a special algorithmic decomposition into leading, vowel, and trailing jamo, which is why a short Korean word can grow several times in code-point length while remaining the same linguistic text. Because the mapping table and mark ordering are fixed by the Unicode version of the runtime, the same input always yields the same NFD string on a given engine.

Where NFD shows up in real engineering work

Search and autocomplete pipelines often strip diacritics after NFD so that cafe matches café without maintaining a hand-written accent table for every language. Identifier and slug generators decompose first, then drop combining marks, producing stable ASCII-ish keys from user-facing titles. Localization QA compares two exports that look the same on screen but fail equality tests until both sides are forced into NFD.

Font and shaping engineers inspect decomposed sequences when debugging mark attachment and glyph substitution. Security reviewers normalize usernames and domain labels before allow-list checks so that precomposed and decomposed lookalikes cannot bypass a filter that only listed one form. Data migration jobs convert legacy NFC-heavy corpora to NFD when a downstream system documents NFD as its storage form.

Programming courses teach encoding by showing that one visible character can become two code points after NFD, and a dedicated normalizer landing serves that search intent better than burying it under general Unicode code-point converters or Base64 tools. Prefer a separate NFC or NFKC tool when you need composition or compatibility folding; this page targets people who specifically need Unicode NFD canonical decomposition and a deterministic normalized string they can trust in tests and pipelines.

Diacritic-aware search keys

Decompose product titles and user queries to NFD, then strip combining marks to build accent-insensitive search and autocomplete indexes.

Username and label normalization

Normalize account names and labels before allow-list or uniqueness checks so precomposed and decomposed forms cannot diverge.

What is Unicode NFD?

NFD is Normalization Form D from Unicode Standard Annex 15. It applies canonical decomposition so precomposed characters become a base character plus combining marks, without recomposing them into NFC.

How is NFD different from NFC or NFKD?

NFC decomposes then recomposes to precomposed forms where possible. NFKD and NFKC also apply compatibility mappings (ligatures, fullwidth forms). This tool only applies NFD canonical decomposition.

What happens if text is missing or invalid?

Missing text, non-string objects, non-finite numbers, and oversized input are rejected. Validation failures are not charged.

Does Hangul get decomposed?

Yes. Precomposed Hangul syllables are algorithmically decomposed into jamo under NFD, so short Korean text can grow in code-point length while remaining the same text.

What does it cost?

The browser tool is free and runs locally.

Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.

POSThttps://api.kit.forhosting.com/enc/unicode-nfd

Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.

curl -X POST https://api.kit.forhosting.com/enc/unicode-nfd \
  -H "Authorization: Bearer $KIT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"café"}'
{
  "text": "café"
}
{
  "task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
  "type": "enc.unicode_nfd",
  "status": "queued",
  "_links": {
    "result": "/tasks/tsk_…/result"
  }
}

The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.

Per request$0.002

Published price — no tokens, no invented credits. A failed task is never charged.

HTTPCodeMeaning
401unauthorizedMissing or invalid API key.
402insufficient_balanceYour balance doesn't cover the task price.
404unknown_typeThat task type doesn't exist.
429rate_limitedToo many requests. Use the webhook instead of polling.

Invalid or missing input fails immediately with invalid_input so bad payloads never invent a silent wrong string.

What NFD canonical decomposition actually does

This capability uses the JavaScript String.prototype.normalize method with the NFD form, which is available in modern Workers and browsers and is deterministic: no network calls, no random seeds, and no wall-clock timestamps participate in the result.

How to call the API and read the response

Empty strings are valid and return an empty NFD result with changed set to false. A classic café example grows from four scalars to five and reports changed true with one combining mark. Plain ASCII such as Hello stays identical with changed false. Send a JSON object with a required string field named text. Aliases input, value, data, s, str, and string are accepted when text is omitted so ad-hoc clients still work. Finite numbers and booleans are coerced to their string form; objects, arrays, null text, NaN, and Infinity are rejected with invalid_input and a clear English message. Strings longer than the documented maximum of sixty-five thousand five hundred thirty-six UTF-16 code units are rejected so a single request cannot monopolize a Worker. On success the response echoes the original text, sets result to the NFD-normalized string, form to the constant NFD, changed to whether result differs from text under ordinary JavaScript string inequality, length_in and length_out to Unicode scalar counts before and after normalization, code_units_in and code_units_out to the UTF-16 lengths, combining_marks to a count of common combining mark code points in the result, and standard to a short UAX #15 label. Failed validation does not consume prepaid balance. Pricing for successful API calls is the published base of $0.002 per item with unit item.

Where NFD shows up in real engineering work

Because this capability is a pure parse engine, API pricing is the published base of $0.002 per successful item and failed validation does not consume balance.

Stable golden tests across platforms

Force fixture strings into NFD so equality assertions pass whether source data arrived precomposed or already decomposed.

Read the full KIT documentation →