Skip to content
FindTool

    Unicode Converter

    Inspect and convert between characters, code points, escape sequences and UTF-8 bytes.

    Unicode Converter tool

    Normalisation

    Canonical composition — combines base letters with their marks where a single code point exists. What you almost always want before storing or comparing text.

    What this tool does

    It takes text apart. Every code point is listed with its U+ notation, its name, its UTF-8 bytes and its escape sequence in the format you choose — and the same text is counted four different ways, because "how long is this string" has four different answers.

    It also runs in reverse, reconstructing characters from escapes, numeric references or U+ notation — mixed freely. Runs of percent-escapes are decoded together, so a four-byte emoji comes back whole rather than as four pieces of mojibake.

    Common uses

    • Finding the invisible character that is breaking a comparison — a no-break space, a zero-width joiner, or a byte order mark at the start of a file.
    • Working out why an emoji counts as 8 characters against a 280-character limit.
    • Diagnosing a name that "looks the same but does not match": one copy is composed, the other decomposed.
    • Producing ASCII-safe escapes for a config or properties file.

    A short example

    A single family emoji, taken apart:

    1 grapheme
    5 code points   U+1F468 U+200D U+1F469 U+200D U+1F467
    8 UTF-16 units  (each emoji is a surrogate pair)
    18 UTF-8 bytes

    The joiners are U+200D, zero-width joiner. Remove them and the same data renders as three separate people.

    Why the four counts differ, and which one your code uses

    A grapheme is what a reader calls a character. A code point is one Unicode scalar value. A UTF-16 code unit is what JavaScript's String.length, Java's length() and C#'s Length all return. A byte is what a database column limit and an HTTP header size measure.

    They diverge exactly where bugs appear. Slicing at a UTF-16 index can cut a surrogate pair in half, producing a code unit that no longer encodes to valid UTF-8; a byte-counting VARCHAR(10) holds only two emoji. Grapheme counting here uses Intl.Segmenter and its UAX #29 rules, falling back where unavailable to an approximation that handles combining marks, variation selectors, skin tones, joiners and flags but over-splits Indic conjuncts.

    Worth knowing

    Normalisation is not cosmetic. NFC composes é into one code point; NFD splits it into e plus a combining acute. Both render identically and neither is equal to the other under ===, which is why usernames and filenames should be normalised — almost always to NFC — before they are stored or compared.

    The compatibility forms, NFKC and NFKD, go further and are lossy: they turn the fi ligature into fi, a superscript ² into 2, and full-width Latin letters into ordinary ones. That is useful for building a search key and wrong for anything you intend to display again.

    Frequently asked questions

    What is the black diamond question mark, and can I get the original character back?

    It is U+FFFD, the replacement character a decoder substitutes when bytes are not valid in the encoding it was told to expect. The original is unrecoverable by then — the information was discarded before the string reached you, so no later conversion or normalisation brings it back. Fetch the source bytes again and decode them correctly; the hex viewer shows what they really are.

    Why does my regular expression miss emoji?

    Without the u flag, JavaScript matches UTF-16 code units, so . matches half of a surrogate pair and a character class can slice one emoji into two meaningless halves. /./u matches a whole code point, and property escapes such as \p{Letter} are a syntax error unless that flag is set. Even then a flag or a family is several code points — try it in the regex tester.

    How do I strip accents from text?

    Normalise to NFD so each accent becomes a separate combining mark, then delete the marks: text.normalize("NFD").replace(/\p{Diacritic}/gu, ""). That handles é, ü and ñ, and quietly does nothing for letters with no decomposition — ø, ł, đ and ß come through unchanged, so a transliteration table is still needed. The slug generator applies the table first and the fold second, in that order.