🔎 Inspector
Invisible characters appear as labeled tags. Underlines mark lookalike letters and typographic substitutions. Hover or focus a mark for details. Green check-marked tags are legitimate (emoji internals, non-Latin scripts) and always stay untouched.
🧼 Cleaning settings
✨ Cleaned text
🫥 Why pasted text is not what it looks like
Unicode contains dozens of characters with zero width. They render as nothing, yet they count as real characters everywhere it hurts: string comparisons, database keys, URLs, YAML indentation, git diffs. A product name with a zero-width space in it will never match a search for the same name without one. A config value with a trailing word joiner fails validation with an error message that looks impossible.
Pasted text moves between systems with different typography and encoding behavior. Curly quotes, em dashes, single-character ellipses, unusual spaces, and invisible controls can travel from a rich editor into code, CMS fields, terminals, and billing systems. Some invisible characters are also used deliberately to carry hidden data.
Where the text came from changes what you will find. An AI chat is a typography source: it hands you em dashes, curly quotes, and ellipses, not zero-width characters. Web pages, PDFs, and word processors are where genuinely invisible characters come from. So if you paste from a chat and this tool reports no invisible characters, that is the normal and correct result, not a miss.
🕵️ What this tool finds
| Character | Code | What goes wrong |
|---|---|---|
| Zero width space | U+200B | Splits words invisibly. Breaks search, matching, and deduplication. |
| Narrow no-break space | U+202F | Appears in typographic text around times and units. Looks like a space, fails ==. |
| Soft hyphen | U+00AD | Invisible until a line wraps. Corrupts identifiers and product codes. |
| Bidi overrides | U+202A..U+202E | Reorder displayed text. Can make exe.txt read as txt.exe. |
| Tag characters | U+E0000..U+E007F | Encode ASCII-based tag strings. Preserved only in recognized subdivision flags. |
| Lookalike letters | various | A Cyrillic о inside a Latin word defeats search, filters, and reviews. |
| Smart punctuation | various | Fine in prose. Breaks shell commands, JSON, and code snippets. |
The narrow no-break space
U+202F may appear between numbers and units or around times in rich-text and chat interfaces. It is the one invisible character AI chats are actually known to produce: several ChatGPT models have emitted it in place of ordinary spaces, which OpenAI described as a quirk of training rather than a watermark, and has since reduced. In a support macro, a WHMCS email template, or a spreadsheet formula, it can arrive unnoticed through copy and paste. It is one reason two visible strings such as "9:30 AM" may fail an exact comparison.
Hidden payloads
Unicode tag characters encode ASCII-based strings without ordinary visible glyphs. Their old language-tagging use is deprecated; the current conformant use is in emoji tag sequences. Outside recognized subdivision flags, this tool decodes tag runs and shows their content for review. See Section 23.9 of the Unicode Standard. Bidirectional overrides are a separate display-reordering risk documented by Trojan Source (CVE-2021-42574).
🛡️ What gets left alone
Most cleanup scripts strip every invisible character they can match. That destroys real content, because several of these characters do essential work:
- Zero-width joiners hold emoji families together. Remove them and 👨👩👧 becomes three separate people.
- The zero-width non-joiner is required spelling in Persian and appears throughout Hindi, Tamil, and other scripts. Stripping it mangles words.
- Variation selectors decide whether ❤ renders as text or as the red emoji heart, and select glyph variants in Japanese names.
- Mongolian free variation selectors choose defined letter forms and remain attached to Mongolian text.
- The flags of Scotland, Wales, and England are built from tag characters. A naive tag stripper deletes the flag.
This cleaner checks context before it touches anything, and the inspector shows kept characters with a dashed outline so you can see the decision instead of trusting it blindly.
⌨️ Use it from your terminal
The same engine that powers this page ships as a command line tool on npm: it scans files and folders, cleans your clipboard in one line, and exits nonzero when it finds something, so it drops straight into CI. Node 22 or newer, nothing to configure, no dependencies.
Scan files and folders
npx ai-paste-cleaner README.md src/
Each finding is reported with its line and column, its name, and the planned fix, showing the first 20 per file unless you add --list. Nothing changes on disk unless you add --write. The preservation rules match this page exactly; the defaults do not, since the command line leaves typography alone until you ask for --typography.
Clean your clipboard
pbpaste | npx ai-paste-cleaner - | pbcopy
The - reads stdin and writes cleaned text to stdout, so it slots into any pipe. Shown for macOS; any clipboard tool works.
Gate your CI
npx ai-paste-cleaner docs/ README.md
Exits 1 when something needs fixing, 0 when clean, and --json emits a machine-readable report for pipelines.
The npm package also exports the engine for your own projects: import { analyze, clean } from "ai-paste-cleaner". Every flag is documented in the README.
💬 Frequently asked questions
No. It finds characters, not authorship. Clean text is not proof a person wrote something, and hidden characters are not proof a machine did. What the tool removes are the mechanical artifacts that cause practical problems and false assumptions.
No, and it will not move an AI detector either. Originality.AI tested exactly this and found that adding or removing hidden characters did not change whether text was flagged. Detectors read wording, rhythm, and structure, which are still yours to edit. Cleaning is for the mechanical problems: text that breaks a comparison, a config file, or a diff.
Nothing leaves your browser. The page is static and the analysis runs on your device, with no network requests once it has loaded. Pull the plug on your internet and it still works, or run it locally from the source.
Yes. The ruleset ships as machine-readable JSON and the engine is a dependency-free ES module under the MIT license.
Not every one. Unicode defines specialized variation sequences and a far larger confusables dataset than this focused cleaner ships with, so review mathematical, historical, and scholarly text carefully. If you hit a false positive or a missed character, the issue templates are the place to flag it.
Yes. The same engine ships as a command line tool: npx ai-paste-cleaner README.md src/ scans files and folders with line and column positions, pbpaste | npx ai-paste-cleaner - | pbcopy cleans your clipboard in place, and the scan exits nonzero when it finds something, so it drops straight into CI. The README covers every flag.
🌱 Why I built this
While checking copied text across my public repositories, I kept finding punctuation and spacing that looked ordinary but behaved differently in code and search. The invisible characters were harder to reason about because I could not see what a cleaner planned to remove. This is the review-first tool I wanted that afternoon.