Unicode Character Inspector

Break text into code points, spot invisible and confusable characters, and generate escape sequences — for debugging text that looks right and behaves wrong.

0
Characters seen
0
JavaScript length
0
UTF-8 bytes
0
Visible symbols

Two strings can look identical and not be equal

The letter é can be written as one code point, or as a plain e followed by a combining acute accent that draws itself over whatever came before. Both render as é. Every font shows them the same. Paste each into the box above and the difference appears immediately:

SpellingShows asLengthCode points
composedé1U+00E9
decomposed2U+0065 U+0301

They are not equal, they do not have the same length, and a search for one will not find the other. This is the most useful thing an inspector tells you, precisely because it is invisible by construction: if a name will not match, a search returns nothing, or a duplicate check lets two identical-looking rows through, this is the first thing to test.

It is not exotic either. All 27 of the accented letters common in Western European languages split into more than one code point — every single one. Plain unaccented letters have nothing to split, which is why this only ever bites text that crossed a system boundary: one keyboard layout, one operating system's file names, one export.

The fix is a single call. Normalising both sides to the same form before comparing makes them equal, and the composed form — NFC — is the one to pick, because it is what nearly all text on the web already uses.

Four normal forms answering two questions

C or D decides whether accents are folded into single characters or split apart. Adding K decides whether characters that are merely formatted differently are also merged. Here is one string — an fi ligature followed by "ancé" — through all four:

FormResultLength
NFCfiancé5
NFDfiancé6
NFKCfiancé6
NFKDfiancé7

K is lossy, and that is the point of it. It is right for a search index, where a circled numeral and a plain one should match, and wrong for storing what somebody actually typed:

CharacterUnder NFKCCode points
fullwidth a — a U+0061
circled one — 1 U+0031
the fi ligature — fi U+0066 U+0069
one half — ½ 1⁄2 U+0031 U+2044 U+0032

The last row is worth checking rather than assuming, and it corrected this page's author. One half under NFKC does not become the ASCII 1/2 — it becomes 1⁄2, using U+2044 FRACTION SLASH. NFKC merges compatibility characters; it does not convert anything to ASCII, and those are different jobs. If you were normalising in order to get plain ASCII out, that is a separate step you still have to write.

And normalising will not save you from lookalikes

The other reason two identical-looking strings differ is that one of them is not in the alphabet you think it is:

LatinLookalikeWhich letterMerged by any form?
a U+0061 а U+0430 Cyrillic a no
o U+006F ο U+03BF Greek omicron no
p U+0070 р U+0440 Cyrillic er no
e U+0065 е U+0435 Cyrillic ie no
x U+0078 х U+0445 Cyrillic ha no

Not one of them, under any of the four forms — and that is correct behaviour rather than a gap. A Cyrillic a is a genuinely different letter that happens to share a shape with the Latin one, so there is nothing to merge. Compare it with the fullwidth a in the table above, which is the same letter formatted differently and does fold.

That is the dividing line worth carrying away. Normalisation is about spelling one character consistently. Telling apart different characters that look alike is a separate problem, and reading the code points — which is what this page is for — is how you do it.

How to use

  1. Paste the text you want to inspect.
  2. Read each character's code point, name and category.
  3. Look for invisible or bidirectional characters flagged in the output.
  4. Copy an escape sequence for use in code.

Frequently asked questions

What is a code point?

The number Unicode assigns to a character, written as U+ followed by hexadecimal digits. Capital A is U+0041. It identifies the character abstractly, separate from how it is stored in bytes or drawn on screen.

Why does my string length not match what I see?

Because a visible character is not always one unit of storage. Characters beyond the basic range take two units in JavaScript and Java, and a single visible emoji may combine several code points with joiners. A family emoji can report a length of eleven.

What are confusable characters?

Characters from different scripts that look identical — Latin a and Cyrillic a, for instance. They are the basis of homograph attacks, where a domain name looks legitimate but contains a substituted letter. Inspecting the actual code points is the only reliable way to tell.

What is a zero-width character?

A character occupying no visual space, such as the zero-width space, joiner and non-joiner. Some are essential in Arabic and Indic scripts, and some are used to fingerprint copied text or to smuggle data past filters. Either way they break comparison and search invisibly.

What is Unicode normalisation?

The process of resolving characters that can be written more than one way. An accented e can be a single code point or a plain e followed by a combining accent — visually identical, byte-wise different. Normalising to a common form before comparing avoids strings that look equal and are not.

What is a bidirectional override?

A control character that reverses the display order of text, needed for mixing Arabic or Hebrew with Latin script. It can also be abused to make source code display differently from how it compiles, which was published as the Trojan Source vulnerability in 2021.

🔒 This tool runs entirely in your browser. Nothing you enter is uploaded, logged, or stored.