Short answer: a Claude watermark, in the practical sense, is a set of invisible Unicode characters that ride along with the text when you copy it out of Claude. You do not need any online tool to find them — you can list every one of them in your own file with the twelve-line script below, in about ten seconds.
The characters that actually show up are these:
| Code point | Name | What it does |
|---|---|---|
U+200B | Zero Width Space | Breaks a word without adding a visible space; also defeats spell check and word count |
U+200C | Zero Width Non-Joiner | Blocks a ligature, invisible |
U+200D | Zero Width Joiner | Joins characters; breaks grep and diff output |
U+2060 | Word Joiner | Stops a line break; invisible |
U+FEFF | Zero Width No-Break Space (BOM) | At the start of a file it is a byte-order mark; inside text it is invisible |
U+200E / U+200F | Left-to-Right / Right-to-Left Mark | Directional marks; reorder punctuation in some renderers |
U+061C | Arabic Letter Mark | Same family as the directional marks |
U+00AD | Soft Hyphen | Hidden hyphen that appears only at a line break |
U+034F | Combining Grapheme Joiner | Invisible, no effect on rendering |
U+180E | Mongolian Vowel Separator | Legacy separator, still invisible |
U+202A–U+202E, U+2066–U+2069 | Bidirectional embedding / isolate controls | Change text direction from that point onward |
U+2028 / U+2029 | Line / Paragraph Separator | Looks like nothing, breaks CSV and JSON parsers |
U+2061–U+2063 | Invisible operators (function application, times, separator) | Math-notation controls, invisible |
Everything else you read about — "Claude adds a secret marker to every answer" — is a different topic. Statistical watermarks, if a provider uses them, live inside the model's output distribution, not inside your file. Nothing you can run on a .txt will find them, and nothing can strip them from text that is already written. What you can find and remove, deterministically, are the characters above.
Save this as find_watermark.py and run it against any UTF-8 text file. It walks the file character by character and prints the position, the code point and the Unicode name of everything invisible.
import unicodedata, sys
path = sys.argv[1] if len(sys.argv) > 1 else "draft.txt"
text = open(path, encoding="utf-8").read()
for i, ch in enumerate(text):
if unicodedata.category(ch) in ("Cf", "Cc", "Zl", "Zp"):
print(i, "U+%04X" % ord(ch), unicodedata.name(ch, "UNKNOWN"))
Run it like this:
python find_watermark.py draft.txt
Empty output means your file is clean. A list of code points is your evidence — keep the output, it is the "before" half of the before-and-after pair you will want if anyone ever asks.
The reason this works is that every invisible character in the table above belongs to Unicode general category Cf (format), Cc (control), Zl or Zp (separators). Normal letters, digits and punctuation never fall into those categories, so the script cannot produce false positives on ordinary prose.
If you would rather not install Python, the same check in one line:
Windows PowerShell
Select-String -Path draft.txt -Pattern "[\u200B-\u200F\u202A-\u202E\u2060-\u2063\uFEFF\u00AD]" -AllMatches
macOS / Linux
grep -oP "[\x{200B}-\x{200F}\x{202A}-\x{202E}\x{2060}-\x{2063}\x{FEFF}\x{00AD}]" draft.txt | sort | uniq -c
This is the part most guides skip. Each editor behaves differently, and two of the three big ones simply refuse to show you these characters.
Microsoft Word (Windows). The ¶ button on the Home tab reveals paragraph marks, spaces and tabs — it will not reveal zero-width characters, so do not trust an empty-looking page. To find one anyway, put the cursor in the Find box (Ctrl+H), hold Alt and type 8203 on the numeric keypad: that inserts U+200B into the search field. Leave Replace empty and hit Replace All. Repeat with 8204, 8205, 8288 and 65279 for the other four common ones. This only works with a physical numeric keypad, and it will not catch the directional marks, which is why the script in Step 1 remains the reliable path.
Google Docs. There is no built-in inspector. The practical route is to paste with Ctrl+Shift+V (paste without formatting), which drops most invisible characters, and then export the document as plain text and run the Step 1 script on the export to confirm. If the export is clean, the document was clean.
VS Code. This one has a real inspector. Invisible characters are highlighted by default — you will see a thin box around them. The settings that control it are editor.unicodeHighlight.invisibleCharacters (default true), editor.unicodeHighlight.ambiguousCharacters and editor.unicodeHighlight.includeComments. Turn on editor.renderControlCharacters as well, and use Ctrl+F with the "Use Regular Expression" toggle and the pattern [\u200B-\u200F\u202A-\u202E\u2060-\u2063\uFEFF\u00AD] to jump straight to each one. This is the fastest way to clean a file you are about to commit.
Sublime Text / Notepad++. Notepad++ → View → Show Symbol → Show All Characters will show control characters but not the zero-width family; search with the same regex instead.
Cleaning is a one-liner once you know the set. This keeps the characters you want and drops the invisible ones:
import re, sys
path = sys.argv[1] if len(sys.argv) > 1 else "draft.txt"
text = open(path, encoding="utf-8").read()
pattern = re.compile(
"[\u200B-\u200F\u202A-\u202E\u2060-\u206F"
"\uFEFF\u00AD\u034F\u180E\u061C\u2028\u2029\uFFF9-\uFFFB]"
)
cleaned = pattern.sub("", text)
open(path, "w", encoding="utf-8").write(cleaned)
print("removed", len(pattern.findall(text)), "characters")
Then run the Step 1 script again on the same file. It should print nothing. That pair of outputs — the list before, the empty list after — is the only verification that means anything. A tool that says "cleaned!" without showing you what it removed has not told you anything.
Two cautions. First, do not run this on source code blindly: U+2028 and U+2029 have been legal inside JavaScript string literals since ES2019, but plenty of older parsers and line-based tools still treat them as line breaks, so removing them can change behaviour — read the diff before you commit. Second, keep a copy of the original until you have confirmed the output, because a blanket strip will also remove legitimate characters from non-Latin scripts that use U+200C and U+200D for correct rendering. If you need to do this across a whole folder, the batch script and git hook are in the folder cleanup guide.
Our Claude Watermark Remover runs the same logic in your browser, with no upload. The list is fixed and published, so you can compare it against the code points you found:
class attributes: attribute values that contain only invisible characters, a pattern used to mark pasted AI text in some editors and CMSsAPP1 segments (Exif, XMP, and C2PA/JUMBF provenance manifests), APP13 (Photoshop IRB / IPTC), and PNG ancillary chunks — while keeping the ICC colour profile and the image data untouchedIt does not rewrite your wording, does not "humanise" anything, and does not add its own watermark. If you need the statistical layer handled, that is a writing problem, not a file problem.
Search for a Claude watermark checker and most results are a text box on someone else's server. Whatever you paste is transmitted to that server, and for a draft, a contract, a support ticket or anything with a name in it, that is a bigger problem than the invisible characters you were trying to remove. The character set is not secret — it is a public part of Unicode, and it is printed in full on this page. Once the list is public, there is no reason to send your document anywhere to have it checked.
The script above runs locally. The tool on the home page runs locally. Neither one has a backend to leak from.
Can I see a Claude watermark with my eyes?
No. Zero-width characters occupy no visual space by definition. If you can see it, it is not one of these characters — it is probably a real mark, a styling artefact, or a hyphenation soft hyphen that only appears at a line break.
Does finding one of these characters prove the text came from an AI?
No. The same characters appear in ordinary copy-paste from web pages, in exported PDFs, from Word's own autocorrect, and in text written on a phone keyboard. They are evidence that something invisible is in your file, not evidence about who wrote the words.
I removed them and a checker still flags my text. Why?
Because those checkers are looking at writing patterns — sentence rhythm, vocabulary, punctuation habits — not at invisible characters. Those two layers are independent. Stripping characters cannot change how a statistical detector scores your prose.
Does this affect code?
Yes, and code is where it hurts most. A U+200B inside an identifier makes two visually identical variables, breaks git diff and merge, and can make linters report a syntax error on a line that looks fine. Run the Step 1 script on any file before you commit it.
Is there a bulk option?
Run the cleaning script in a loop over a folder — it takes a file path as its argument, so for f in *.txt; do python clean.py "$f"; done handles a directory. Test on copies first.