Unicode & Encoding Inspector

Developer

Every character, every length, and the invisible ones that break things.

Visible characters
29
Something below needs a look
Code points
29
UTF-16 units
29
UTF-8 bytes
38
What to look at
Invisible1 · U+200B

Invisible characters. They render as nothing, so the text LOOKS correct and compares unequal. A zero-width space in a password field or a BOM at the front of a CSV are the usual causes of “but it looks identical”.

Unusual space1 · U+00A0

Spaces that are not the ordinary U+0020. Almost always pasted from a word processor or a web page. They survive a trim() that only strips ASCII whitespace, and they break a split on " ".

Smart punctuation3 · U+2014 U+201C U+201D

Typographic punctuation substituted by a word processor — curly quotes, en and em dashes, a single-character ellipsis. Fine in prose, and a syntax error in code, a CSV or a JSON string.

Character by character
JU+004ABasic Latin1B
uU+0075Basic Latin1B
aU+0061Basic Latin1B
nU+006EBasic Latin1B
 U+00A0NO-BREAK SPACE2B
DU+0044Basic Latin1B
eU+0065Basic Latin1B
lU+006CBasic Latin1B
aU+0061Basic Latin1B
U+0020SPACE1B
CU+0043Basic Latin1B
rU+0072Basic Latin1B
uU+0075Basic Latin1B
zU+007ABasic Latin1B
U+0020SPACE1B
—U+2014EM DASH3B
U+0020SPACE1B
“U+201CLEFT DOUBLE QUOTATION MARK3B
dU+0064Basic Latin1B
eU+0065Basic Latin1B
vU+0076Basic Latin1B
eU+0065Basic Latin1B
lU+006CBasic Latin1B
oU+006FBasic Latin1B
pU+0070Basic Latin1B
eU+0065Basic Latin1B
rU+0072Basic Latin1B
”U+201DRIGHT DOUBLE QUOTATION MARK3B
·U+200BZERO WIDTH SPACE3B
38 bytes in UTF-8. A VARCHAR limit and an HTTP header limit count BYTES, not characters, which is why a name with an ñ can be rejected by a field that looks long enough.

How to use

What it's for

Find the hidden characters in a piece of text — an invisible space, a curly quote, an odd dash — when a form rejects it or two copies that look identical do not match.

Before you start

Have the text that is misbehaving to hand, copied from wherever it came from — Word, a PDF, a chat app. It is inspected in your browser and nothing is sent anywhere.

  1. Clear the sample

    Press Clear to empty the box of the sample.

  2. Paste your text

    Paste it into Text. Paste it rather than typing it again: typing it again would leave out the very characters you are looking for.

  3. Inspect

    Press Inspect. The counts at the top also update as you paste or type.

  4. Read what it found

    What to look at names each kind of problem, how many there are and their codes, such as U+200B. Under Character by character, every character is listed in order; a hidden one shows as a dot, so you can see where it sits.

  5. Standardise accented letters, if offered

    If a Normalise to NFC button appears, some accented letters are stored in an unusual way. Press it to rewrite them in the standard form, so two copies of the same word match.

Reading the result

  • Visible characters: the number of characters you can actually see. The line under it says Nothing unusual found, or that something needs a look.
  • Code points, UTF-16 units and UTF-8 bytes: three other ways computers count length. A field with a byte limit can refuse text that looks short enough, because a letter such as ñ takes more than one byte.
  • Invisible, Unusual space, Smart punctuation and the like: the kinds of character found. Curly quotes are fine in a letter but break code, a CSV or JSON.

If it goes wrong

  • Two pieces of text look the same but do not match: paste each one here in turn and compare what What to look at finds. An Invisible character or an Unusual space is the usual cause.
  • To get rid of a flagged character, find it in Character by character, then delete it in your own copy, or type that part again by hand.
  • Direction control characters change the order text is shown in, so it can read differently from what it really contains. Remove them unless you know why they are there.

What this is

There are four answers to “how long is this”, and they are all different.

"👨‍👩‍👧" is 8 to JavaScript’s .length, 5 code points, 18 bytes in UTF-8, and 1 character to the person who typed it.

A VARCHAR(20) measures bytes. A form validator usually counts UTF-16 units. The user counts what they can see. Pick one, call it “length”, and a field that looks long enough starts rejecting somebody’s name.

Then there are the characters that are there and do not render. A zero-width space in a password. A BOM at the front of a CSV that breaks the first column header. A non-breaking space pasted out of Word. The text looks right and compares unequal.

Direction controls get their own heading here. They do not merely fail to render — they reorder the text around them, so what you read and what runs can differ.

Questions

Why are there four different lengths?

Because four different things measure "length". A VARCHAR column and an HTTP header count BYTES. JavaScript's .length counts UTF-16 units. A character limit on a form usually means code points. And the person typing counts what they can see. For "👨‍👩‍👧" those are 18, 8, 5 and 1. Picking one and calling it the length is how a field that looks long enough rejects somebody's name.

My two strings look identical but compare unequal. Why?

Usually one of three things, and this finds all of them. An invisible character — a zero-width space, a soft hyphen, a BOM at the front of the file. A space that is not U+0020, typically a non-breaking space pasted from a word processor. Or a different normalisation form: "é" can be one code point or two, and the two versions render identically and compare unequal in almost every language.

What are the direction control characters and why are they separate?

They reorder the text around them. That makes them different in kind from a character that merely fails to render: a line of source code containing U+202E can read one way and execute another, which is the Trojan Source class of attack. They get their own finding, ranked above everything except already-broken text, rather than sitting in a list beside a smart quote.

What should I do about a character it flagged?

It depends what the text is for. Smart quotes are correct in prose and a syntax error in JSON or a CSV. A non-breaking space is deliberate in "10 kg" and a bug in a database key. Astral characters are perfectly valid and only a problem if something downstream slices by .length. The tool names what is there and why it matters; whether it belongs is your call.

Why do some characters get a block name instead of a real name?

Because the full Unicode character database is megabytes and this engine ships with no dependencies at all. Every character worth warning about is named exactly. Everything else is identified by its Unicode block, which is factual and short. Inventing a plausible-sounding name would be worse than an honest one.

What is NFC and should I normalise?

NFC is the composed normalisation form, and it is what the web defaults to. If you are comparing strings, using them as keys, or storing them for a uniqueness check, normalise first — otherwise two identical-looking values will both be accepted and your duplicate check will never fire. The button appears only when the text is not already in NFC.

The maths

Four measures of one string
Visible characters1
Code points5
UTF-16 units (.length)8
UTF-8 bytes18
One family emoji, four different counts. Each is the right answer to a different question.

Keep going

Important

Runs entirely in your browser; nothing is transmitted. Full Unicode names are not shipped — every character worth warning about is named exactly, and the rest are identified by block rather than guessed at. Nothing you type here is sent to our servers — the calculation runs entirely in your browser.