# Zero-Width Steganography Decoder

> Find invisible zero-width characters in text and decode the message hidden in them.

- Page: https://decoder.tools/zero-width-decoder
- Category: Classical & Obfuscated Ciphers
- Status: live, runs in the browser
- Last reviewed: 2026-10-23

A zero-width decoder looks for invisible Unicode characters such as the zero-width space (U+200B) and the zero-width non-joiner (U+200C), reads them as bits, and converts the bits back into the hidden text.

## Example

The input below looks like an ordinary sentence, but 16 invisible characters sit between "to" and "see". Copy it from this page to try it.

```text Input
Nothing to​‌‌​‌​​​​‌‌​‌​​‌ see here
```

```text Output
hi
```

The decoder reports **Hidden bits: 16**, which is two characters of 8 bits each.

## How zero-width steganography works

Unicode has several characters that take up no space on screen:

| Code point | Name | Normal purpose |
|---|---|---|
| U+200B | Zero-width space (ZWSP) | Marks a line-break opportunity |
| U+200C | Zero-width non-joiner (ZWNJ) | Stops two letters from joining (Persian, Arabic) |
| U+200D | Zero-width joiner (ZWJ) | Joins characters, for example in emoji sequences |
| U+FEFF | Zero-width no-break space / BOM | Byte order mark at the start of a file |

Text survives copy and paste with these characters intact, so they can carry a hidden payload. A common scheme writes each bit of the secret as one of two zero-width characters. This decoder reads **U+200B as 0 and U+200C as 1**, groups the bits into 8-bit bytes, and turns them into text. Other characters, including U+200D, are skipped.

The same trick is used to **watermark** text: a leaked document or chat message can carry an invisible code that identifies the person it was sent to.

## How to use the zero-width decoder

1. Paste the suspicious text exactly as you received it.
2. Read the hidden message and the number of hidden bits.
3. If it says zero-width characters were found but no message was decoded, the text uses a different scheme. Use the [Hexdump viewer](/hexdump-parser) to see which characters are there (`e2 80 8b` is U+200B, `e2 80 8c` is U+200C, `e2 80 8d` is U+200D).

## Find zero-width characters in code

```python Python
import re

text = "Nothing to​‌ see here"
print([f"U+{ord(c):04X}" for c in re.findall("[​-‍﻿]", text)])  # ['U+200B', 'U+200C']
print(re.sub("[​-‍﻿]", "", text))  # strip them
```

## At a glance

| | |
|---|---|
| Characters read | U+200B = 0, U+200C = 1 |
| Grouping | 8 bits per character |
| Common uses | Steganography, text watermarking, CTF puzzles |
| Removal | Delete U+200B–U+200D and U+FEFF |

## FAQ

### How can I tell if text has hidden characters?

Use the arrow keys: the cursor seems to stop between letters for no reason. Or compare the length: a string with hidden characters is longer than it looks. The [Hexdump viewer](/hexdump-parser) shows them as `e2 80 8b`-style byte sequences.

### Why are zero-width characters dangerous?

They can make two strings that look identical compare as different, which breaks searches, logins and code. They're also used to sneak words past content filters and to fingerprint leaked text.

### Is a zero-width joiner in emoji a hidden message?

No. Emoji sequences such as 👨‍👩‍👧 use U+200D to join several emoji into one. This decoder ignores U+200D for that reason.
