Get the invisible junk out of your text.
Paste anything. We find zero-width spaces, smuggled tag characters, look-alike letters and other characters you can't see — and we don't wreck your emoji or your non-English text doing it.
- Runs in your browser
- No sign-up
- Free, no limits
- Open source
Your text is analysed in the browser. Press Clean text to see results below.
Advanced— extra cleanups, off by default
The defaults already remove every character that is invisible and doing no work: zero-width characters, byte-order marks, soft hyphens, invisible math operators, bidi overrides, free-floating tag characters and variation selectors, noncharacters, and other format controls. Everything below goes further than that — it either changes text you can see or removes characters that are doing a job — so you decide.
Whitespace & layout
Letters & punctuation
Controls
Aggressive
Press Clean text and we'll show you exactly what was hiding in there — in plain language first, with the codepoints underneath if you want them.
- Your text never leaves this pageThere is no upload, no server call, no analytics on what you paste. Turn off your wifi and it still works.
- Free, unlimited, no accountNo character cap, no daily quota, no email wall in front of the results.
- Beaten 11 real hiding schemesZero-width binary, tag smuggling, variation-selector bytes, SNOW whitespace, homoglyph and NFC/NFD binary, and five more.
- Same engine as the CLIThe Python tool and this page share one rulebook, so a pre-commit check and a browser paste agree.
Paste, clean, copy.
That's the whole thing. Everything else on this page is optional reading.
Paste it in
Straight from a chat window, a PDF, a translation tool, an AI assistant, or a colleague's email. The hidden characters come along for the ride — that's the point.
Press Clean text
We walk your text character by character and decide, for each suspicious one, whether it is hiding or working. The visible words are never touched.
Copy the clean version
One button. If you want the receipts, open the findings table and see every character with its position, codepoint and official Unicode name.
Six families of characters you can't see.
Roughly 26 distinct character types, grouped into the families that actually behave differently.
Zero-width characters
Take up no space, survive copy-paste, and can encode a whole message in binary. The classic way to fingerprint a document per recipient.
U+200B ZWSP · U+200C ZWNJ · U+200D ZWJ · U+2060 WORD JOINER · U+FEFF BOM
Bidi controls
Reorder how text is displayed. Harmless next to Hebrew or Arabic; a way to make source code read one way and compile another when they aren't.
U+202A–202E · U+2066–2069 · U+200E LRM · U+200F RLM · U+061C ALM
Tag characters
A shadow ASCII alphabet. An entire English sentence can sit inside plane 14 and render as absolutely nothing — the trick behind ASCII smuggling into AI assistants.
U+E0001 · U+E0020–E007E · U+E007F CANCEL TAG
Variation selectors
Meant to pick an emoji or glyph style. Free-floating ones carry a byte each, which makes a long invisible payload trivially easy to attach to any character.
U+FE00–FE0F · U+E0100–E01EF
Spaces & separators
Not all spaces are the space bar. Swapping NBSP for a plain space, or leaving one extra space at the end of a line, encodes bits nobody sees.
U+00A0 · U+2000–200A · U+202F · U+205F · U+3000 · U+2028 · U+2029
Look-alike letters
Cyrillic а is not Latin a, but nothing on screen tells you that. Our map has 1,513 entries generated from Unicode's own confusables.txt.
U+0430 а · U+043E о · U+0435 е · U+03BF ο · U+0456 і · U+FF41 a
Why your emoji survive.
The same character can be a hiding place or load-bearing structure. Tools that delete by codepoint alone break things; tools that play it safe miss things. We look at the neighbours.
Kept — it's holding the family together
U+200D sits between two emoji. Remove it and the family emoji falls apart into three separate people. Same character, same codepoint, completely different job.
Removed — it's hiding between two letters
The identical U+200D between two Latin letters joins nothing. It is there to survive a copy-paste and carry a bit of someone’s watermark.
🏴 stays a flag
Tag characters spell out “gbsct” inside the Scotland flag. Free-floating tag characters get removed; the ones inside a valid flag sequence don’t.
Persian and Hindi keep their joiners
A zero-width non-joiner inside a Persian word changes how the letters connect. Delete it and you have misspelled the word. We keep it and tell you it's there.
Hebrew keeps its direction marks
An RLM next to Hebrew text is doing real layout work. An RLM in a run of English is not. Both are U+200F.
What this tool cannot do.
Plenty of sites promise to “remove AI watermarks”. Here is where character cleaning genuinely stops, so you don't rely on it for something it was never able to do.
- Statistical watermarks stay put. Schemes like Google's SynthID-Text are embedded in which words the model chose, not in any character. Nothing we strip touches them. Rewriting the text does.
- Stylometry is untouched. Sentence rhythm, vocabulary and structure are what AI-detection classifiers actually read. Straightening your quotation marks changes none of it.
- Format-level hiding is out of scope here. Metadata in a DOCX, white text on white in a PDF, comments in HTML — that lives in the file, not the text. Paste the text and we clean the text; take the whole file to the Documents page.
- An em dash is not evidence. We can convert typographic punctuation on request, but a person who writes well uses em dashes too. Treat it as formatting, not proof.
What we do claim: eleven published character-level steganography techniques, each one defeated in testing with the visible text byte-for-byte identical afterwards.
Mostly people with something pasted.
Writers & students
Text moved through three apps before it reached your document. Clean it once so a submission portal or plagiarism checker doesn't choke on characters you never typed.
Translators
CAT tools and MT engines leave behind NBSPs, soft hyphens and stray bidi marks. Clean the invisible layer without touching the joiners your target language depends on.
Publishers & CMS teams
Author submissions arrive from Word, Docs and email. Normalise them before they hit the database, and keep a report of what changed.
Developers
Run --check in a pre-commit hook and fail the commit when an invisible character or bidi override lands in source, config or a locale file.
Security & AI-safety teams
Inspect suspected prompt-injection payloads: see the tag-character sentence, the codepoints and the exact offsets before deciding what to do with the input.
Anyone who got a weird file
If a document looks fine but behaves strangely — search fails, sorting breaks, a name won't match — paste it here first. It's usually a character you can't see.
The same engine, in your terminal.
strip_invisible.py is a single dependency-free Python file. No install step, no package to trust — download it, read it, run it.
# See what is hiding, without changing anything python3 strip_invisible.py --show file.md # Clean in place, and normalise spaces and punctuation while you are there python3 strip_invisible.py -i -s --punct draft.md # Fail the build if invisible characters made it into the repo python3 strip_invisible.py --check src/**/*.ts # Documents too: hidden runs, tracked changes, metadata, rsids python3 clean_file.py --show essay.docx
Exit code 1 when anything is found, so it drops straight into a pre-commit hook or CI step. Every toggle in the Advanced panel above maps to one flag.
Reasonable things to ask.
Is my text uploaded anywhere?
No. Everything runs in JavaScript on this page. There is no request to any server when you press Clean text, and nothing you paste is logged or stored. If you want to verify that, open your browser's network tab, or just disconnect from the internet and use the page offline.
Will it break my emoji?
Not with the default settings. Zero-width joiners between emoji, variation selectors that pick an emoji presentation, and tag characters inside flag sequences are all recognised as load-bearing and kept — and reported, so you can see them. The only way to remove them is to deliberately switch on “Strip joiners even when they matter” under Advanced.
Does it work with Arabic, Hebrew, Hindi or Persian?
Yes, and that is the main reason this tool exists. Zero-width non-joiners inside Persian words, joiners in Indic scripts, and directional marks next to right-to-left text all change how the text reads, so they are kept by default. The same characters floating in a run of English are removed.
Can it remove an AI watermark?
It removes character-level watermarks — the kind that hide data in invisible codepoints, whitespace patterns or look-alike letters. It does not remove statistical watermarks such as SynthID-Text, which live in word choice, and it does not change how an AI-detection classifier scores your writing. Any tool claiming otherwise is overselling.
Why is a character listed but not removed?
Two reasons. Either it is load-bearing — removing it would change how your text renders — or it needs a setting that is off by default because it would alter visible text, like look-alike letters or curly quotes. In both cases the findings table names the exact setting that would remove it, so nothing is silently ignored.
What is an ASCII smuggling attack?
Unicode has a block of “tag” characters (U+E0000–E007F) that mirror ASCII but render as nothing at all. A full instruction can be written in them, pasted into a document, and read by a language model while being completely invisible to the person reviewing it. We strip free-floating tag characters by default and show you what they spelled.
What is the difference between NFC and NFKC?
NFC picks one consistent spelling for accented characters — é as a single codepoint rather than e plus a combining accent. Choosing between the two forms at random is itself a way to encode bits. NFKC goes further and also folds fullwidth letters, ligatures and superscripts into plain equivalents, which is more aggressive than most text wants.
Is there a limit on how much text I can clean?
No quota and no account. The practical limit is your browser: a few hundred thousand characters is fine, and beyond that the terminal version is a better fit — it streams files and handles whole directories.
Does cleaning change how my text looks?
With the defaults, no — every character removed is one that renders as nothing. That is the test we hold the tool to: run it against a steganography scheme and the visible text should come out byte-for-byte identical. Options under Advanced deliberately break that rule, which is why each one says what it changes.
How is this different from a find-and-replace?
A find-and-replace deletes every instance of a codepoint. That is how tools end up shredding family emoji and Persian spelling. This one decides per occurrence, based on the characters either side, and shows you the reasoning for each decision with a line and column number.