Skip to content
Ghostchars

Joiners, selectors and fillers

ZERO WIDTH JOINER (U+200D)

An invisible character that asks two neighbours to be drawn as one. It is what turns three separate people into a family emoji and what joins Arabic and Indic letters that would otherwise stand apart.

Codepoint
U+200D
Removed by default
When free-floating
Governing option
Aggressive -a
Can be load-bearing
Yes

Where it comes from

Every emoji sequence you have ever sent: 👨‍👩‍👧 is three people and two joiners. In text it comes from Persian, Hindi, Malayalam and Arabic typing, from copy-pasted web content, and from zero-width steganography, where it is one half of a two-symbol alphabet with U+200C.

Why it matters

It is the character that makes naive cleaners dangerous. Strip every U+200D and you turn one family emoji into three separate people and you break real words in half a dozen scripts. Leave every U+200D and you leave the most common hidden channel in place.

Before and after

BeforeheU+200Dllo 👨U+200D👩U+200D👧
Afterhello 👨U+200D👩U+200D👧

The same codepoint twice. The one between "he" and "llo" is removed; the two inside the family are kept, because removing them would leave three separate people.

The character is shown as a labelled chip so you can see where it sits. In your text it draws nothing at all.

When it is legitimate

Between two emoji bases, and between two letters of the same joining script — Arabic, Persian, Devanagari, Malayalam. Ghostchars keeps it in exactly those positions and removes it everywhere else.

How to remove it

A free-floating joiner — one sitting between two Latin letters — is removed by the default pass. A load-bearing one is kept and reported as "kept — load-bearing"; `-a` (aggressive) removes those too, at the cost of your emoji and your Persian.

Is it an AI watermark?

Used to hide data — not a watermark

No. A zero width joiner between two Latin letters is contraband, but it is hand-placed contraband — it is the oldest trick in text steganography. Inside an emoji it is simply how emoji work. Neither case identifies an author.

A known carrier for deliberately hidden payloads. Someone put it there on purpose, which is a different question from who wrote the words.

Questions

Will cleaning break my emoji?

Not with the default settings. Ghostchars checks the characters on both sides: a joiner between two emoji bases is kept. Only `-a` (aggressive) removes those, and the option says so.

What about Persian, Hindi or Arabic text?

A joiner between two letters of the same joining script is kept for the same reason. Removing it would change how the word is shaped and, in some words, what it means.

How do I know which ones were kept?

Every finding is listed with its line and column and an action: removed, replaced, kept — load-bearing, or found but not targeted. Nothing is decided silently.

Check your own text

Paste anything into the cleaner to see every hidden character it contains, with position, codepoint and what happens to each one. Nothing is uploaded.

Check your own textAll characters