Zero-Width Character Remover
Text copied from the web, PDFs or chat often carries invisible characters that break length counts, search and comparisons. This tool lists every one by type and position, then removes only those characters — spacing, line breaks and content stay untouched.
Text copied from a web page, a PDF or a chat window often carries a few characters that cannot be seen: zero-width spaces, zero-width joiners, byte-order marks. The trouble they cause is very visible — a character count that will not match, a search that fails although the phrase is plainly there, a compiler reporting a bizarre syntax error, a database column longer than it looks. This tool scans character by character and lists each invisible one with its type and position.
Cleaning removes only those invisible characters and leaves everything else untouched, so a result that looks unchanged afterwards is normal — they were invisible to begin with. Two kinds are deliberately left alone: the variation selectors that follow emoji (the codepoints after a heart or a check mark) and ordinary CJK punctuation, both of which would change how the text renders if removed.
Did this tool solve your problem?
Submitting sends the tool name, your input and the current result to the server. Please do not include ID numbers, phone numbers or other private data.
AI assistant It answers using your current input and result
Asking again sends your current input and result to the server once more. Please do not include private data.
How to use
- Paste the text to inspect.
- Read the list of invisible characters, each with its type and position.
- Clean the text; only the invisible characters are removed.
- Copy the cleaned result and check the count that was previously off by a little.
How it works
Which invisible characters are covered
The scan covers 19 code points in three groups: zero-width format characters — zero-width space U+200B, non-joiner U+200C, joiner U+200D and word joiner U+2060; stray controls — byte-order mark U+FEFF, soft hyphen U+00AD, Mongolian vowel separator U+180E and Arabic letter mark U+061C; and bidirectional controls — U+200E/U+200F, U+202A–U+202E and the direction isolates U+2066–U+2069. The third group is rare but can silently reorder how text displays.
Why variation selectors aren't stripped
The variation selectors U+FE0E and U+FE0F are deliberately not cleaned. They aren't "leftover invisible characters" but functional modifiers: the text selector U+FE0E renders certain symbols as black-and-white text, the emoji selector U+FE0F renders hearts and check marks as color emoji. Removing them changes the visible text, so they're reported but preserved.
Using the position list to locate them
The result area provides three things: the cleaned text (one-click copy), a "marked version" replacing each invisible character with a tag like {ZWSP} (to spot where it hides in long text), and a position list — one line per hit with type, character index, line and column. Rows and columns count from 1; columns count characters. Positions beyond 200 show only the first 200 with a notice.
Code example
JavaScript Detecting and cleaning
// The most common kinds of invisible characters
const ZERO_WIDTH = /[\u200B\u200C\u200D\u2060\uFEFF\u00AD\u200E\u200F]/g;
const scan = (s) => {
const hits = [];
[...s].forEach((c, i) => {
if (ZERO_WIDTH.test(c)) hits.push({ i, code: 'U+' + c.codePointAt(0).toString(16).toUpperCase() });
ZERO_WIDTH.lastIndex = 0; // reset the global regex, or test() starts skipping characters
});
return hits;
};
const clean = (s) => s.replace(ZERO_WIDTH, '');
scan('a\u200Bb'); // [{ i: 1, code: 'U+200B' }]
clean('a\u200Bb'); // 'ab'
Shell Inspecting and batch-cleaning on the command line
# Show invisible characters (cat -A marks them explicitly)
printf 'a\u200bb\n' | cat -A
# List code points precisely with Python (handy when inspecting API responses)
python3 - <<'PY'
s = open('data.txt', encoding='utf-8').read()
for i, c in enumerate(s):
if c in '\u200b\u200c\u200d\u2060\ufeff':
print(i, hex(ord(c)))
PY
# Batch clean
perl -CS -pe 's/[\x{200B}\x{200C}\x{200D}\x{2060}\x{FEFF}]//g' data.txt > clean.txt
FAQ
What are zero-width characters, and how did they get into my text?
They're Unicode characters that occupy a code point but no width and no shape — the zero-width space U+200B is the classic. You usually didn't type them; copy-paste brought them in: sites insert zero-width spaces between characters to deter scraping, and PDF conversion, Word exports, phone IME suggestions and editor auto-formatting all smuggle them too. Visually nothing changes, but length, search and comparisons all break.
After cleaning, the text looks identical — did it work?
That's the point — zero-width characters are invisible, so "looks the same" is what success looks like. Confirm via the character counts below the result (before vs. after differ by exactly the deleted count), or check the marked version for leftover {ZWSP} tags.
Why wasn't the selector after the heart or check mark removed?
That's a variation selector U+FE0E/U+FE0F — not a stray ghost but a display switch: U+FE0F makes the symbol color emoji, U+FE0E makes it plain text. Deleting it changes appearance, so the tool counts but keeps them. To purge all non-ASCII characters, use the Unicode escape tool or a range-based regex instead.
What do zero-width characters actually break?
Four common failures: length and character limits stop matching (a few extra characters counted); search, dedup and database unique constraints fail (two visually identical strings aren't equal); code or configs throw inexplicable syntax errors (a zero-width character inside an identifier); and layout shows odd line breaks or misalignment. Links with smuggled zero-width characters may not even open.
Can I jump from the position list to the original text?
The positions are a human-locating reference: line numbers count newlines, columns count characters (UTF-16 code units), both from 1. Editors differ in newline and character counting conventions (is \r\n one line or two?), so prefer the marked version — searching {ZWSP} together with surrounding context hits most reliably.
Do zero-width characters take up length in databases?
Yes. Column lengths count characters, zero-width included — a nickname "10 characters long" may actually store 25, tripping length errors. Worse, unique indexes treat two visually identical strings with different zero-width characters as distinct. Cleaning before insert is common practice.
Why did two scans of the same text find different counts?
Something happened in between: a copied web page re-inserted tracking zero-width characters, an editor stripped some controls, or the content itself changed. Make sure both scans use the same text — paste into a plain-text editor first, then copy uniformly from there.
Does cleaning change the original layout?
No. Only those 19 invisible code points are removed — spaces, newlines, punctuation and normal text are untouched, and relative order is fully preserved. The only change is the disappearance of the invisible ones, so before and after look exactly alike on screen.