The zero-width space is U+200B ZERO WIDTH SPACE: ​ or ​ as a numeric reference, or ​ by its HTML5 name. In UTF-8 it’s E2 80 8B. It takes no room on the line; it marks a place where a line may break.
Character U+200B ZERO WIDTH SPACE
Named ​ (HTML5 only, plus four &Negative…Space; aliases)
Numeric ​ ​
UTF-8 E2 80 8B
Prefer the numeric form. HTML 4 had no name for this character, and JSX compilers only know HTML 4’s names: in Babel, TypeScript, esbuild and oxc, ​ renders as literal text, while ​ works. XML doesn’t know the name either. Browsers and CommonMark read all three.
Find the hidden ones
Pasted into code, a username or a search box, a zero-width space makes equal-looking strings unequal. Encoding username with one inside shows it:
user​name
The tool writes it as a hex reference, in lower case, because it uses names only from HTML 4 and a few common HTML5 ones. In JavaScript that string is 9 characters long and !== 'username'. Unlike U+00A0, it isn’t white space: trim(), the regex \s and Python’s str.strip() all leave it in. Remove it explicitly:
text.replace(/\u200B/g, '')
Line breaks in long strings
Its legitimate job is to allow a break inside a long URL, file path or identifier without adding a hyphen. HTML has an element for that, <wbr>, and it’s better: you can see it in the source, and it isn’t part of the text, so it doesn’t come along when someone copies the address. In Chromium and WebKit, both break incomprehensible in a narrow box where the plain word overflows.
<code>/var/log/<wbr>nginx/<wbr>access.log</code>
For text you don’t control, let CSS break it:
.path { overflow-wrap: anywhere; }
Its neighbors
U+200B zero width space ​ a break may happen here
U+200C zero width non-joiner ‌ keeps letters from joining
U+200D zero width joiner ‍ joins emoji sequences
U+2060 word joiner ⁠ no width and no break
U+00AD soft hyphen ­ a hyphen only at a break
Don’t strip U+200D along with U+200B: it holds multi-person and profession emoji together.