Skip to content
Ghostchars

What Ghostchars detects

Every category the engine can report, the option that governs each, and the codepoints with a page of their own. Paste text into the box below to see which of them it contains.

Removed by the default passKept when load-bearingNeeds an option

Nothing is uploaded. The cleaning happens on this page.

Your text is analysed in the browser. Press Clean text to see results below.

Cleanup level

Standard removes only characters you cannot see. Maximum also rewrites text you can see (look-alike letters, quotes, dashes and spacing), so it is a choice, not a 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

Non-breaking, thin, and ideographic spaces become a plain space. Off because NBSP is often deliberate.
CRLF, CR, NEL, and Unicode line/paragraph separators become a plain newline.
Removes the bar a terminal copies beside each quoted line. Off because folder trees use the same bar.
Spaces parked at the end of a line can encode a hidden message (the SNOW technique).
Double spaces between words can carry binary data. Off because it changes fixed-width layouts.

Letters & punctuation

Cyrillic а in "аpple" becomes Latin a. Only acts inside words that mix scripts, so ordinary Russian or Greek text is untouched. Off by default because it rewrites letters.
Em dash, curly quotes, ellipsis and minus sign become ASCII. Often used as an "AI tell", but also just good typography.
Composed vs. decomposed accents (é as one character or two) can encode bits. NFC picks one form.
Also folds fullwidth, superscript and ligature forms. Changes more than you might expect, and supersedes NFC.

Controls

We already remove bidi overrides, and marks in left-to-right prose. This one also removes the marks sitting next to Hebrew or Arabic, where they do real layout work.
C0 and C1 controls other than tab and newline.
Breaks icon fonts and some brand glyphs, which is exactly where these normally live.

Aggressive

Removes every zero-width joiner and variation selector, including the ones holding 👨‍👩‍👧 together and the ones Persian, Hindi and flag sequences need. Only use this when you want plain letters and nothing else.

ZWSPTAG U+E0053

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.

The tables below say what the engine acts on. Where you run it is a separate question: if the text is inside a file, the document report opens a .docx, .odt or .html in your browser and lists hidden runs, tracked changes and authoring metadata beside the characters. If it is text you are about to paste somewhere, the Chrome extension cleans it in the box you are already typing in.

None of that is about how the prose reads. That is the prose report, which measures sentence-length variation, stock transitions, hedges and dash density and gives you the numbers without a score, a probability or a verdict about who wrote the text.

By category

Categories are tested in this order and the first match wins, which is why a zero width space is reported as a zero-width character rather than as a generic format control.

Zero-width and invisible

Governed by Default pass (always on)

Characters with no glyph and no width that are contraband anywhere in prose: zero width space, word joiner, soft hyphen, the byte order mark, the four invisible maths operators, deprecated format controls, interlinear annotation marks, musical-notation controls and Unicode's permanently reserved noncharacters.

Bidirectional marks

Governed by Bidi marks --bidi

Direction hints: the left-to-right and right-to-left marks, the Arabic letter mark, and the four isolates. Next to right-to-left text they resolve genuine ambiguity and are kept; in an English paragraph they are invisible padding and a published steganography carrier, and they go.

CodepointNameDefault pass
U+200ELEFT-TO-RIGHT MARKWhen free-floating
U+200FRIGHT-TO-LEFT MARKWhen free-floating
U+061CARABIC LETTER MARKWhen free-floating
U+2066-U+2069BIDIRECTIONAL ISOLATESWhen free-floating

Joiners, selectors and fillers

Governed by Aggressive -a

Invisible characters that bind to the character before or after them: zero width joiner and non-joiner, variation selectors, tag characters, and the script-specific fillers of Mongolian, Khmer and Hangul. Kept when their neighbours make them load-bearing, removed when they are free-floating.

CodepointNameDefault pass
U+200DZERO WIDTH JOINERWhen free-floating
U+200CZERO WIDTH NON-JOINERWhen free-floating
U+FE00-U+FE0FVARIATION SELECTORSWhen free-floating
U+E0000-U+E007FTAG CHARACTERSWhen free-floating
U+180B-U+180DMONGOLIAN FREE VARIATION SELECTORSWhen free-floating
U+17B4-U+17B5KHMER INHERENT VOWELSWhen free-floating
U+115F-U+1160HANGUL JAMO FILLERSWhen free-floating

Any other format control

Governed by Default pass (always on)

The catch-all. Every remaining character whose Unicode general category is Cf is removed, so a format control added in a future Unicode version is caught without a code change. The orthographic exceptions (the Arabic number signs, the Syriac abbreviation mark, the Kaithi number sign) are matched earlier and left alone.

Detected by Unicode property rather than from a list, so there is no fixed set of codepoints to enumerate.

Private-use characters

Governed by Private-use characters --pua

Codepoints Unicode will never assign, whose meaning is a private agreement between a font and an application. Icon fonts live here, which is why removing them is opt-in: in UI copy they are the content.

CodepointNameDefault pass
U+E000-U+F8FFPRIVATE USE AREANo

Line separators

Governed by Line endings -n

Unicode's line and paragraph separators and the EBCDIC-derived NEL. They are folded to a plain line feed rather than deleted, because deleting them would run two lines together.

CodepointNameDefault pass
U+2028LINE SEPARATORNo
U+2029PARAGRAPH SEPARATORNo
U+0085NEXT LINENo

Control characters

Governed by Control characters --controls

The C0 and C1 control codes, excluding tab, line feed and carriage return. Their presence in text usually means a decoding accident or a deliberate probe.

CodepointNameDefault pass
U+0000-U+001FC0 CONTROL CHARACTERSNo
U+0080-U+009FC1 CONTROL CHARACTERSNo

Typographic punctuation

Governed by Punctuation --punct

Curly quotes, em and en dashes, the ellipsis, the minus sign and the primes. Nothing is hidden here, since these are visible characters, but they are a different codepoint from their ASCII forms, and the straight-versus-curly choice is a published one-bit-per-apostrophe channel.

CodepointNameDefault pass
U+2013EN DASHNo
U+2014EM DASHNo
U+2019RIGHT SINGLE QUOTATION MARKNo
U+2026HORIZONTAL ELLIPSISNo

Terminal quote bars

Governed by Quote bars --gutters

The bar a terminal draws down the left of a quoted block, which is copied as text at the start of every line along with the quote. A bar counts only when it opens its line and the same glyph does not appear again later on that line, so a table drawn with box characters is left alone. It goes with the one space after it. Opt-in, because a folder tree printed in a terminal starts its lines with the same bar.

CodepointNameDefault pass
U+2502│ BOX DRAWINGS LIGHT VERTICALNo
U+2503┃ BOX DRAWINGS HEAVY VERTICALNo
U+258C▌ LEFT HALF BLOCKNo
U+258D▍ LEFT THREE EIGHTHS BLOCKNo
U+258E▎ LEFT ONE QUARTER BLOCKNo
U+258F▏ LEFT ONE EIGHTH BLOCKNo

Lookalike letters

Governed by Lookalike letters --confusables

Cyrillic, Greek, Armenian, Cherokee, fullwidth and mathematical letters that are drawn identically to Latin ones. The mapping has 1,513 entries generated from Unicode's own confusables data, and one only counts inside a mixed-script word: a run of letters that also contains an ASCII letter or digit, like "аpple". A pure Cyrillic or Greek word is never reported and never rewritten. Opt-in even so, because it rewrites letters you can see.

The options

The default pass needs no option and is always on. Everything else is off until you turn it on, and every one of them changes text you can see, which is exactly why it is off.

OptionCLI flagWhat it doesWhy it is not the default
Default pass(always on)Zero-width characters, the byte order mark, soft hyphens, invisible maths operators, bidi overrides, free tag characters, free variation selectors, noncharacters, every remaining Cf format control, and free-floating glue.Always on. Nothing it removes is visible or load-bearing.
Aggressive-aRemoves glue even where it is load-bearing.Breaks family emoji, Persian and Indic spelling, subdivision flags and CJK glyph variants.
Spaces-sReplaces no-break and exotic spaces with an ordinary space.A no-break space is usually doing its job: French punctuation, "10 km", CJK layout.
Line endings-nFolds CRLF, CR, NEL, U+2028 and U+2029 to a plain line feed.Changing line endings changes the file, and some pipelines depend on them.
Bidi marks--bidiRemoves direction marks and isolates even next to right-to-left text.Breaks the layout of mixed Hebrew, Arabic and Persian text.
Control characters--controlsRemoves C0 and C1 controls, keeping tab and the line breaks.Rare in ordinary text, and their presence usually points at an encoding problem worth fixing at the source.
Private-use characters--puaRemoves codepoints from the private-use areas.Icon-font glyphs live there; removing them empties your interface labels.
Punctuation--punctConverts em and en dashes, curly quotes, the ellipsis and the minus sign to ASCII.It is typography, not hiding. Converting it makes prose worse, not more human.
Lookalike letters--confusablesMaps 1,513 lookalike codepoints to their Latin twins, inside mixed-script words only.It rewrites letters you can see. Pure Cyrillic, Greek or Turkish text is left alone, but a word that mixes scripts is changed, so you ask for it.
Quote bars--guttersRemoves the quote bar a terminal copies at the start of each line, with the space after it.A folder tree or a box drawn in text can start its lines with the same bar.

Whole-text options

Four more options rewrite patterns rather than individual characters, so they have no category of their own.

Normalize (NFC)

Composes a letter and its accent into one codepoint.

It changes bytes that are already correct, and it defeats normalisation-form steganography only when you ask for it.

--nfc

Normalize (NFKC)

NFC plus styled mathematical letters, ligatures and fullwidth forms folded to plain equivalents.

Lossy: 𝐛𝐨𝐥𝐝 becomes bold and the styling is gone for good.

--nfkc

Trailing whitespace

Removes spaces and tabs at the end of every line.

Two trailing spaces are a hard line break in Markdown.

--trailing

Collapse spaces

Collapses runs of spaces inside a line to one, keeping indentation.

Some formats depend on the runs: aligned tables, ASCII art, code.

--collapse

Every character with a page

Each of these has its own page: what it is, where it comes from, when it is legitimate, and the honest answer to whether it is an AI watermark.

Browse the character index

Questions

How many characters does it detect?

The tables name several hundred codepoints exactly, and two catch-all rules cover every remaining format control and every private-use codepoint by Unicode property, so a character added in a future Unicode version is detected without a code change. On top of that the lookalike map covers 1,513 codepoints.

Is the default pass safe to run on anything?

It is designed to be: the default pass only removes characters that are invisible AND not doing a job in their context. It leaves every visible character alone, including no-break spaces, curly quotes and em dashes. If you want those changed you have to ask.

What if my character is not listed here?

Paste the text into the tool and reveal it. Anything the engine classifies is reported with its position, codepoint, Unicode name and category, whether or not it has a page here.

Anonymous usage stats?

Ghostchars processes your text in the browser and never uploads it. We would like to count page views with a self-hosted, cookie-light analytics endpoint. No content, ever.