Remove Accents/Diacritics
Type or paste accented text below and get back the plain ASCII equivalent instantly, é becomes e, ñ becomes n, and letters like ß, æ or ø get mapped to their closest plain-letter spelling too.
About the Remove Accents/Diacritics Tool
Most accented letters (é, ñ, ü, â and similar) are Unicode characters built from a plain base letter plus a separate "combining mark" glued on top. This tool first runs your text through normalize("NFD") to split each accented letter back into that base letter and its mark, then deletes every combining mark in one pass. A handful of letters don't work this way because they are not a base letter plus a mark in Unicode, ß, æ, œ, ø, đ, ł, ð and þ (plus their capital forms) are their own standalone characters, so those are swapped using a small hand-written lookup table (ß to ss, æ to ae, œ to oe, ø to o, and so on) before the normalization step runs.
- NFD normalization, decomposes precomposed accented letters into base letter + combining mark, then strips the marks.
- Fallback map, handles the letters that Unicode doesn't decompose, like ß, æ, œ, ø, đ, ł, ð, þ.
- Characters changed, counts how many original characters were altered or replaced by the conversion.
NFD specifically, not NFKD — canonical decomposition only
Unicode defines four normalization forms, and this tool uses NFD (canonical decomposition without recomposition), not NFKD (compatibility decomposition). The difference matters at the edges: NFD splits an accented letter into its base letter plus a combining mark, which is exactly what's needed here, but it leaves compatibility characters alone — things like the "fi" ligature (a single Unicode character, not two letters) or full-width Latin letters sometimes used in East Asian typesetting. NFKD would additionally unpack those into their ordinary equivalents, but this tool deliberately doesn't reach that far, since the goal is stripping accent marks specifically, not normalizing every visually-equivalent character variant in Unicode.
The combining-mark range covers the common case, not every diacritic block
After NFD decomposition, any character whose code point falls between U+0300 and U+036F is dropped — this is the "Combining Diacritical Marks" block, which covers the accents used on virtually all everyday Latin-script text: acute, grave, circumflex, tilde, umlaut, cedilla, and the rest of the marks that show up on café, naïve, or Zürich. Unicode does define a few other, much rarer combining-mark blocks outside that range, used mostly for specialized phonetic transcription or historical text, and those wouldn't be caught by this specific range check. For essentially all ordinary accented text in Latin-alphabet languages, though, this single block covers everything you'll actually encounter.
Every loop iterates by Unicode character, not by raw string index
Both passes through the text use for...of, and the total character count uses Array.from(), rather than a plain indexed loop or .length. That distinction matters because for...of and Array.from() both iterate by full Unicode code point, correctly treating a multi-byte character like an emoji as a single unit, where a naive index-based loop or raw .length call would split it into two meaningless surrogate halves. This is a more careful approach than this site's own Line Counter, whose character-length stat uses plain .length and so does inflate slightly on text containing emoji — a difference worth knowing about if you're comparing character counts between the two tools on the same input.
The fallback map runs before NFD, because those letters don't decompose either way
The order here is fallback substitution first, NFD decomposition second. It works this way because letters like ß, æ, ø, and the rest of the fallback list aren't a base letter plus a combining mark in Unicode at all — they're their own standalone characters, so running NFD on them wouldn't change them regardless of when it happens. Substituting them first just means the generic NFD-and-strip pass afterward only ever has to deal with genuinely decomposable accented letters, keeping the two steps cleanly separated by what kind of character each one is built to handle.
"Characters Changed" counts affected input characters, not the net change in length
The counter increments once for every original character that gets altered, whether that character is deleted (a combining mark) or replaced (a fallback substitution) — but several fallback substitutions actually expand into more than one output character. ß becomes "ss," æ becomes "ae," and þ becomes "th," each counted as a single "changed" character even though the output is two characters long for each one. So the stat measures how much of your original input was touched, not the difference in total length between the input and output text, which can end up slightly longer than what went in in text with several of these expanding letters.
Frequently Asked Questions
Does this handle ligatures like the "fi" character or full-width letters?
No. The tool uses NFD (canonical decomposition), which splits accented letters into a base letter plus a combining mark, but it doesn't perform compatibility decomposition, so ligatures and full-width character variants are left untouched. That's outside the scope of accent removal specifically.
Does it strip every kind of combining mark in Unicode?
It strips any character in the U+0300–U+036F range, the "Combining Diacritical Marks" block, which covers virtually all accents on everyday Latin-script text. A few much rarer combining-mark blocks used for specialized phonetic or historical text fall outside that range and wouldn't be affected.
Will an emoji in my text get miscounted or corrupted?
No. Every loop in this tool iterates by full Unicode code point using for...of and Array.from(), which correctly treats a multi-byte emoji as one character rather than splitting it into broken fragments the way a plain index-based loop or raw .length check would.
Why does the output text sometimes end up longer than the input?
Some fallback substitutions expand into two letters — ß becomes "ss," æ becomes "ae," þ becomes "th" — so text containing several of those letters can come out slightly longer than it went in, even though each substitution only counts as one "changed" character in the stat.
Is my text sent to a server when I use this tool?
No. All conversion happens locally in your browser using JavaScript's built-in Unicode normalization; nothing is uploaded anywhere.