About this tool
What it does, what it deliberately cannot do, what happens to your text, and how to use it.
What markcheck is
Some characters occupy real bytes but draw nothing on screen — or draw something that looks exactly like an ordinary space. A zero-width space between two letters. A narrow no-break space standing in for a normal one. A right-to-left override that silently reverses the words after it. You cannot see them, copy them out, or count them by eye.
markcheck reads the bytes and tells you what is present, exactly where, and what it is. It can hand back a cleaned copy. That is the whole product.
Watermarking
Hidden characters inserted to mark a document's origin or track who leaked it.
Steganography
Payloads encoded in invisible code points, riding inside ordinary prose.
Trojan Source
Bidirectional controls that make source code read differently to a human than to a compiler (CVE‑2021‑42574).
Prompt injection
Instructions smuggled to an AI model in the invisible Unicode Tags block.
What happens to your text
Nothing. It never leaves this page. The scan runs in your browser, in JavaScript, on your own machine. You can disconnect from the internet and it will still work.
connect-src 'none' in its Content-Security-Policy. That is
not a promise, it is an instruction to your browser: the page is
forbidden from making a network request, and the browser enforces it even
if the code tried.The one thing that does touch a server
The visit counter in the footer. It is incremented on the server before the page is sent to you, which is precisely why the page itself still makes no network request. What gets stored is a single number — no IP address, no browser details, no per-visitor record, no timestamp. There is nothing kept that could connect a visit to a person, or to anything you scanned.
index.html and open it with your wifi off.What it cannot do
Three different techniques get called "AI watermarking." Only one of them puts anything in the bytes, and that is the only one a byte scanner can ever find.
| Technique | Where it lives | markcheck |
|---|---|---|
| Hidden characters | In the text itself, as real code points | Detects this |
| Statistical watermarks | In which ordinary words a model chose — no characters added | Cannot detect, and neither can any byte scanner |
| C2PA provenance | A signed manifest in an image or PDF container | Out of scope — use c2patool or
exiftool |
Also deliberately out of scope
- Homoglyphs and confusables — a Cyrillic letter standing in for a Latin lookalike. Those are visible and legitimate in their own scripts; catching abuse needs mixed-script analysis, a different tool.
- Normalization. markcheck inspects the bytes as given. It does not NFC/NFD-normalize or compare equivalent sequences.
- Attribution. A hidden character proves presence, not origin. markcheck carries no list of vendors and takes no position on who put something there or why.
How to use it
1. Get your text in
- Paste it into the box, or
- drag a text file onto the page, or
- press
Choose a file….
It scans as you type. Check text forces a rescan.
2. Read the verdict
The large number is how many hidden characters are in scope. The bar underneath shows how they split by severity, and the table lists each one with its line, column, code point, and name. Below that, a preview of your text with every hit marked in place, so you can see exactly where they sit.
3. Narrow it down
Suspicious only hides the hits markcheck has annotated as likely legitimate — a byte-order mark at the start of a file, a joiner holding an emoji together, French punctuation spacing. Turn it on when you only want the things worth explaining.
4. Clean it
Copy cleaned puts a cleaned copy on your clipboard.
Before / after shows you what would change first.
Keyboard
⌘K / Ctrl K |
Command palette — every action, searchable |
⌘↵ / Ctrl ↵ | Scan now |
Esc | Clear the text box |
Reading the results
Every hit is rated, so a watermark does not get lost among emoji joiners.
Categories
Six by default — zero-width, invisible format, bidi, variation selector, tag, and nonstandard whitespace — plus a seventh, opt-in category in the command line tool covering every remaining Unicode default-ignorable code point, for forensic work.
The command line tool
The same scanner, for files, pipelines, and CI. One Python file, standard library only, no dependencies.
pip install markcheck
markcheck essay.md
Exit codes make it a linter: 0 clean, 1 hidden
characters found, 2 a usage or I/O error.
markcheck *.md --suspicious-only # skip the benign annotations
markcheck notes.md --strip # write notes.clean.md
markcheck report.md --json # machine-readable output
cat file.txt | markcheck --strip --stdout > clean.txt
This page is generated from the same character tables the command line tool uses, and a parity test proves the two agree on every hit, position, name, note, severity, and cleaned result.
Why you can check rather than trust
A tool that inspects your writing for hidden marks is asking for a lot of trust. The point of the design is that you should not have to give much.
connect-src 'none' is checked by your
browser, not by us.