aitextcleaner.top

ChatGPT Watermark Detector — Scan Text for Hidden Characters

A read-only scan. See what invisible characters are in your text without changing a single one of them.

Scanning never changes your text.

Hidden character report

Paste text to scan

What the scan reports

The scan reads your text and produces a list. Each row is one character type that was found: its name, its Unicode code point, and how many times it appears. The total at the bottom is the sum of those counts, which is the number of characters that would change if you ran the cleaner over the same text.

Nothing is removed, replaced or reordered. The text you pasted stays exactly as it was, in the box, for as long as the page is open.

How to read the report

A row for a zero-width character means the character is present and invisible. A row for a non-breaking space means it is present and looks like a space but will not break at a line ending. Two rows with similar names are two different characters — the code point column is what distinguishes them.

If the report says no hidden characters were found, the scan looked for every entry in the published table and matched none of them. That is a complete answer for the characters this tool knows about, and it is worth knowing before you spend time debugging a layout problem elsewhere.

Why a scan-only view exists

Sometimes you do not want the text changed. If you are checking a quotation, auditing a document someone sent you, or trying to work out which step of a pipeline is adding noise, a clean copy is not the useful output — the report is.

It is also the honest way to show what the cleaner does. Scan a paragraph, note the counts, then run the cleaner on the same text and compare. The numbers match, because both views call the same engine.

What a character-level scan cannot tell you

This scan knows about characters, and nothing else. It cannot tell you who wrote a piece of text, what model produced it, whether it was edited, or how any system will treat it. Those are different questions with different evidence, and a character table is not evidence for any of them.

It also cannot see anything outside the character stream: file metadata, authorship fields, revision history and platform logs are all outside its reach. What it covers, it covers exactly — a scan for the specific invisible characters listed in the table on this page.

Zero-width characters, one by one

U+200B is the zero width space. Its design purpose is to mark a legal line-break opportunity inside a word in languages that do not use spaces to separate words, such as Thai or Khmer. In ordinary Latin prose it serves no typographic function, so finding it in a copied paragraph almost always means it came from a webpage that inserted it for layout reasons. U+200C is the zero width non-joiner. It suppresses a cursive connection between two adjacent letters, which matters in Arabic, Persian and Devanagari script. In a plain English sentence it has no visible effect and no intended meaning, so its presence is a residue from rich-text formatting rather than deliberate punctuation. U+200D is the zero width joiner. It has the opposite job: it asks two adjacent characters to connect as though they were ligatures. Emoji sequences rely on it heavily — a family emoji is typically four or five base emoji joined by U+200D, which is why that sequence counts as more than one code point. When a ZWJ appears in non-emoji text it is almost certainly accidental.

U+FEFF was originally the byte order mark, placed at the start of a UTF-16 file so a reader could detect whether the bytes were big-endian or little-endian. In UTF-8 it has no byte-order function, but some Windows tools still prepend it, which is why pasting from Notepad or Excel occasionally produces a stray character at position zero. U+FEFF is also defined as the zero width no-break space, which is a second, distinct role at the same code point. That dual identity is not a typo: the Unicode standard formally assigned both meanings to U+FEFF, and tools that process text must account for both. U+2060 is the word joiner, added later to take over the no-break-space job from U+FEFF, leaving U+FEFF as byte-order-mark only. The two share a conceptual purpose but are different code points at different positions in the Unicode table, which is why a scan that reports both is not double-counting.

All of these characters enter copied text for the same structural reason: the source document used them for a formatting purpose the receiving application does not share. A webpage might insert U+200B to prevent a long URL from overflowing a fixed-width column. The browser renders the page correctly, the character is invisible, and when you select and copy the text, the character travels with the visible letters into your clipboard. The destination has no column to worry about, so the character is now noise. The scan surfaces these characters by code point so you can see exactly what arrived, regardless of whether any of them are visible at normal reading size.

Where invisible characters come from in practice

Copying from a webpage is the most common source. Browsers render HTML text with a layer of CSS that can insert soft hyphens (U+00AD) at hyphenation points, use zero-width spaces to manage overflow, or apply directional control characters for mixed-language pages. None of those render as visible glyphs at body text size, but all of them move into the clipboard when you select and copy a passage. PDF-to-text conversion is a second major source. PDFs store text as positioned glyphs, not as a continuous character stream. When a converter reassembles the stream, it often inserts extra spaces or line-break characters to approximate the visual spacing of the original layout, and the result can contain non-breaking spaces (U+00A0) wherever the original column had a fixed-width gap between words.

Google Docs and Word both export to plain text through their own conversion layers. Google Docs preserves smart quotes (U+2018, U+2019, U+201C, U+201D) and em dashes (U+2014) by default; Word adds the same plus occasionally inserts U+00A0 to hold table cell padding. If you export to .docx and then copy from a preview app, you may get a third layer of conversion on top of those. UTF-16 files from Windows tools often carry a U+FEFF byte order mark at position zero. A UTF-8 reader that does not strip BOM silently passes it through, so the first character of the pasted text is invisible. Emoji in modern text are a different kind of compound: a family or couple emoji is assembled from two to five base characters connected by U+200D zero width joiners. Those joiners are structurally correct inside that sequence, and the scan notes them but treats them as part of the emoji rather than as stray formatting noise.

Bidirectional text control characters form their own category. U+202A through U+202E and U+2066 through U+2069 tell renderers how to order characters in paragraphs that mix left-to-right and right-to-left scripts, such as a Hebrew sentence that contains an English product name. In a document originally written in Arabic or Hebrew, these characters are doing their intended job. When that document is copied into a context that does not need mixed-direction rendering, the control characters persist and can confuse downstream systems that count characters, apply regex matches, or compare strings. The scan identifies them by name so you can distinguish a purposeful bidi marker from one that arrived as baggage.

How to verify a scan result by hand

If you want to confirm what the scan found, open a browser console on any page and run this one-liner: [...text].map(c => c.codePointAt(0).toString(16)). Replace text with the string you want to inspect. The spread operator splits the string by Unicode code point rather than by UTF-16 code unit, which matters for characters above U+FFFF. The result is an array of hexadecimal code points. Look for values like 200b, 200c, 200d, feff, 00ad, or 00a0 — those are the most common invisible characters. If you need to find where in a long document a particular character sits, the array index corresponds directly to the code point position in the string, so index 47 means the 48th code point from the start.

A few patterns look suspicious but are not invisible characters. U+00A0 non-breaking space renders as a space character at normal size and behaves like one for most purposes; it only differs at line-break time and in string comparison. If you paste text into a field and it looks fine but a downstream system rejects it, a non-breaking space in a field that expects U+0020 ordinary space is a common culprit. Emoji with U+200D inside them are not formatting errors. The ZWJ is structurally required for the combined glyph to render as intended; removing it splits the emoji into its component parts. The scan reports it because it is in the zero-width-character category, but the fix depends on whether you need the combined emoji or are happy with the components. Line endings are also not invisible characters in the sense this tool covers. A CRLF sequence (U+000D U+000A) is a normal Windows line ending. It is not hidden; it just does not print as a visible glyph. The scan does not flag CRLF as an invisible formatting character.

The most reliable way to cross-check a scan result is to run the cleaner on the same text immediately after the scan and compare the two outputs side by side. The scan report tells you the before state: how many of each character type were present. The cleaner output is the after state. If the scan said three instances of U+200B and the cleaner removed three characters, the numbers match and the result is consistent. If they do not match, the most likely explanation is that the text changed between the two operations, which can happen if you edited the input box between runs.

Characters this tool looks for

25 invisible characters and formatting controls, with the action taken on each one.

CharacterCode pointActionWhat it does
Zero-width characters
Zero Width SpaceU+200BRemovedInvisible separator with no width. Commonly left behind when text is copied out of a chat window.
Zero Width Non-JoinerU+200CRemovedInvisible character that blocks two letters from joining in scripts such as Arabic or Devanagari.
Zero Width JoinerU+200DRemovedInvisible character used to glue emoji sequences together. Stray copies can break word wrapping.
Zero Width No-Break Space (BOM)U+FEFFRemovedByte order mark. Harmless at the start of a file, invisible noise anywhere else.
Word JoinerU+2060RemovedTells a text engine not to break a line here. Invisible, and easy to carry along by accident.
Mongolian Vowel SeparatorU+180ERemovedA legacy invisible separator from Mongolian script that now renders as nothing at all.
Bidirectional controls
Left-to-Right MarkU+200ERemovedDirectional hint for mixed-script lines. Invisible on screen but present in the character stream.
Right-to-Left MarkU+200FRemovedMirror of the left-to-right mark, used to steer the order of mixed-direction text.
Arabic Letter MarkU+061CRemovedInvisible directional marker for Arabic text. Rarely intentional outside its original document.
Left-to-Right EmbeddingU+202ARemovedOpens an embedded left-to-right run. Unpaired copies can scramble the order of a sentence.
Right-to-Left EmbeddingU+202BRemovedOpens an embedded right-to-left run. Left behind after copy-paste, it can flip nearby punctuation.
Pop Directional FormattingU+202CRemovedCloses an embedded directional run. Without its partner it is pure invisible noise.
Left-to-Right OverrideU+202DRemovedForces following characters to display left-to-right regardless of their own direction.
Right-to-Left OverrideU+202ERemovedForces following characters to display right-to-left. A common cause of text that looks reversed.
Left-to-Right IsolateU+2066RemovedModern replacement for the embedding controls. Still invisible, still travels with copied text.
Right-to-Left IsolateU+2067RemovedIsolates a right-to-left run from the surrounding paragraph direction.
First Strong IsolateU+2068RemovedIsolates a run whose direction is decided by its first strong character.
Pop Directional IsolateU+2069RemovedCloses an isolate opened by one of the isolate controls above.
Formatting controls
Soft HyphenU+00ADRemovedA hyphen the reader only sees if the word happens to break at the end of a line.
Carriage Return (CR)U+000DRemovedHalf of a Windows line ending. Kept on its own it produces doubled spacing in most editors.
Markdown Asterisk MarkerU+002ARemovedBold or italic marker such as ** left behind when text is copied in its raw form. Turn this group off to keep Markdown styling marks.
Markdown Backtick MarkerU+0060RemovedInline-code backtick left behind after copying raw assistant output. Turn this group off to keep inline code marks.
Invisible spaces
No-Break SpaceU+00A0→ spaceLooks exactly like a space but stops a line from breaking there. A frequent copy-paste leftover.
Figure SpaceU+2007→ spaceA space as wide as a digit, used to align numbers in tables. Replaced with a normal space.
Narrow No-Break SpaceU+202F→ spaceA thin, non-breaking space from French typography. Replaced with a normal space.

Frequently Asked Questions

▸Does the scan change my text?

No. The scanner never writes to the input box. It calls the same engine the cleaner uses and reads only the report half of the result, discarding the cleaned output. Your text stays byte-for-byte identical until you choose to copy it somewhere else.

▸What does 'no hidden characters found' mean?

It means every character in your text was compared against the published table and none of them matched. Your text is free of the invisible characters this tool looks for. It is not a statement about anything else in the text.

▸Can this tell me whether text was written by an AI?

No, and no character-level scan can. This tool reads invisible formatting characters. Authorship is a different question that a table of Unicode code points has nothing to say about. Anyone claiming otherwise is selling you something this page does not do.