Look-alike pairs test values

Pairs of values that are identical on screen and different in storage. 12 values, each with what it breaks and what a correct application does instead.

look-alike-pairs version 1.0, updated 2026-10-14 CC-BY-4.0

Type them one at a time with AltShiftN in the palette, or take them all into a script with nkb emit look-alike-pairs.

Name with a Latin a

look-alike-pairs/latin-small-a

pair 1 of 2 Latin a against Cyrillic a

pawel pawel
  • 5 graphemes
  • 5 code points
  • 5 bytes
  • 5 UTF-16 units
What it breaks
The control half of a pair - only meaningful next to its counterpart.
What a correct application does
Stored as typed.

Name with a Cyrillic a

look-alike-pairs/cyrillic-small-a

pair 2 of 2 Latin a against Cyrillic a

pаwel pаwel
  • 5 graphemes
  • 5 code points
  • 6 bytes
  • 5 UTF-16 units
What it breaks
A Cyrillic letter identical in shape to the Latin one; two accounts that look the same to every human.
What a correct application does
Either both accepted as distinct and shown as distinct, or the second rejected as a duplicate.

Word with a Latin o

look-alike-pairs/latin-small-o

pair 1 of 2 Latin o against Greek omicron

robot robot
  • 5 graphemes
  • 5 code points
  • 5 bytes
  • 5 UTF-16 units
What it breaks
The control half of a pair - only meaningful next to the Greek omicron below it.
What a correct application does
Stored as typed.

Word with a Greek omicron

look-alike-pairs/greek-omicron

pair 2 of 2 Latin o against Greek omicron

rοbot rοbot
  • 5 graphemes
  • 5 code points
  • 6 bytes
  • 5 UTF-16 units
What it breaks
The same shape from a third script; catches uniqueness checks that only handle Cyrillic.
What a correct application does
Same as above.

Accented word, composed

look-alike-pairs/nfc-lodz

pair 1 of 2 Composed against decomposed accents

Łódź Łódź
  • 4 graphemes
  • 4 code points
  • 7 bytes
  • 4 UTF-16 units
What it breaks
Control half: the accented letters written as single characters.
What a correct application does
Stored as typed.

Accented word, decomposed

look-alike-pairs/nfd-lodz

pair 2 of 2 Composed against decomposed accents

Łódź Łódź
  • 4 graphemes
  • 6 code points
  • 9 bytes
  • 6 UTF-16 units
What it breaks
The same word with combining marks; identical on screen, different in storage and in every comparison.
What a correct application does
Normalised on save, or compared in a normalisation-aware way.

Name with an ordinary space

look-alike-pairs/plain-space-name

pair 1 of 2 Ordinary space against non-breaking space

JanKowalski Jan Kowalski
  • 12 graphemes
  • 12 code points
  • 12 bytes
  • 12 UTF-16 units
What it breaks
The control half of a pair - an ordinary space, so that the non-breaking one has something to fail against.
What a correct application does
Stored as typed.

Name with a non-breaking space

look-alike-pairs/nbsp-name

pair 2 of 2 Ordinary space against non-breaking space

JanKowalski Jan\u00A0Kowalski
  • 1 space that is not an ordinary space
  • 12 graphemes
  • 12 code points
  • 13 bytes
  • 12 UTF-16 units
What it breaks
A non-breaking space where an ordinary one is expected; search never matches.
What a correct application does
Normalised, or treated as distinct consistently.

Range with a hyphen

look-alike-pairs/hyphen-minus

pair 1 of 2 Hyphen against en dash

2020-2026 2020-2026
  • 9 graphemes
  • 9 code points
  • 9 bytes
  • 9 UTF-16 units
What it breaks
The control half of a pair, with the ASCII hyphen - it parses everywhere the dash below it does not.
What a correct application does
Stored as typed.

Range with an en dash

look-alike-pairs/en-dash

pair 2 of 2 Hyphen against en dash

2020–2026 2020–2026
  • 9 graphemes
  • 9 code points
  • 11 bytes
  • 9 UTF-16 units
What it breaks
The typographic dash that arrives with every copy from a document; breaks parsing of ranges.
What a correct application does
Normalised before parsing, or accepted as an equivalent separator.

Capital i, lowercase L and one

look-alike-pairs/capital-i
Ill1 Ill1
  • 4 graphemes
  • 4 code points
  • 4 bytes
  • 4 UTF-16 units
What it breaks
Capital i, lowercase L and the digit one in one value: indistinguishable in many typefaces.
What a correct application does
Displayed in a typeface where the characters can be told apart, wherever the value must be read back.

Letter O and digit zero

look-alike-pairs/digit-zero-letter-o
O0 O0
  • 2 graphemes
  • 2 code points
  • 2 bytes
  • 2 UTF-16 units
What it breaks
The same problem for the letter O and the digit zero, in codes people retype by hand.
What a correct application does
Same as above, or the ambiguous characters excluded from generated codes.

Pairs

Each pair is two of the values above, worth typing side by side: into two fields, or into one field twice. AltShiftN types them in turn, and the palette says which half of a pair comes next.

Latin a against Cyrillic a

look-alike-pairs/latin-vs-cyrillic-a
look-alike

pair 1 of 2 Name with a Latin a

pawel
  • 5 graphemes
  • 5 code points
  • 5 bytes
  • 5 UTF-16 units

pair 2 of 2 Name with a Cyrillic a

pаwel
  • 5 graphemes
  • 5 code points
  • 6 bytes
  • 5 UTF-16 units
What it breaks
Two visually identical usernames become two accounts, and support cannot tell which is which.
What a correct application does
Either both accepted as distinct and shown as distinct, or the second rejected as a duplicate.

Latin o against Greek omicron

look-alike-pairs/latin-vs-greek-o
look-alike

pair 1 of 2 Word with a Latin o

robot
  • 5 graphemes
  • 5 code points
  • 5 bytes
  • 5 UTF-16 units

pair 2 of 2 Word with a Greek omicron

rοbot
  • 5 graphemes
  • 5 code points
  • 6 bytes
  • 5 UTF-16 units
What it breaks
Uniqueness checks that special-case one script miss the next one.
What a correct application does
Either both accepted as distinct and shown as distinct, or the second rejected as a duplicate.

Composed against decomposed accents

look-alike-pairs/nfc-vs-nfd
look-alike

pair 1 of 2 Accented word, composed

Łódź
  • 4 graphemes
  • 4 code points
  • 7 bytes
  • 4 UTF-16 units

pair 2 of 2 Accented word, decomposed

Łódź
  • 4 graphemes
  • 6 code points
  • 9 bytes
  • 6 UTF-16 units
What it breaks
The same name saved twice from two devices produces two records.
What a correct application does
Normalised on save, so both spellings end up as one record.

Ordinary space against non-breaking space

look-alike-pairs/space-vs-nbsp
look-alike

pair 1 of 2 Name with an ordinary space

JanKowalski
  • 12 graphemes
  • 12 code points
  • 12 bytes
  • 12 UTF-16 units

pair 2 of 2 Name with a non-breaking space

JanKowalski
  • 12 graphemes
  • 12 code points
  • 13 bytes
  • 12 UTF-16 units
What it breaks
Search finds one and not the other, and nobody can see why.
What a correct application does
Both found by the same search, either because the space is normalised on save or because search treats both as a space.

Hyphen against en dash

look-alike-pairs/hyphen-vs-endash
look-alike

pair 1 of 2 Range with a hyphen

2020-2026
  • 9 graphemes
  • 9 code points
  • 9 bytes
  • 9 UTF-16 units

pair 2 of 2 Range with an en dash

2020–2026
  • 9 graphemes
  • 9 code points
  • 11 bytes
  • 9 UTF-16 units
What it breaks
A range pasted from a document stops parsing, with no visible difference.
What a correct application does
Both forms parse as the same range, or the dash is normalised before parsing.