MarkCleaner / Field notes
ChatGPT Watermark Remover: Compare the Text Before You Strip Anything
A character scan tells you what is present. A before-and-after comparison tells you what changed during your own copy-and-paste step. Neither result identifies who wrote the text or proves a watermark.
Why compare two versions?
A scan of one text can report that a code point exists, but it cannot tell whether the character was already in your source, arrived from an editor, or appeared during paste. The practical question for a publishing workflow is often narrower: what changed between my saved draft and the text I pasted?
In the competitor pages reviewed for this guide, the common workflows scan one text, highlight characters, or remove a predefined set. This page adds a paired-input check: compare the saved source with the pasted copy and inspect only the net code-point changes. It is a diagnostic step, not a watermark detector.
A small reproducible example
These are synthetic strings, not collected ChatGPT outputs. In the first pair, one zero-width space is inserted between A and the emoji. The report should show one added U+200B; the emoji itself is one Unicode code point but two UTF-16 code units.
| Before | After | Code-point change | What the result means |
|---|---|---|---|
A😀B3 code points; 4 UTF-16 code units | A😀B4 code points; 5 UTF-16 code units | U+200B: +1 | One code point differs between these constructed inputs. This does not establish who inserted it or why. |
A B | A B | U+0020: −1; U+00A0: +1 | A normal space was replaced by a no-break space; the visible result may look nearly identical. |
👩💻 | 👩💻 | U+200D: +1 | The inserted joiner participates in an emoji sequence. A blanket “delete every invisible character” rule may alter intended text. |
The counts above are derived directly from the displayed Unicode strings. To reproduce them, run the code below with the same before/after pairs. Use your own original and pasted text for a real comparison; synthetic examples cannot say what happened in your editor.
Compare code-point counts in your browser
This short script reads two strings that you paste into the variables. It performs no network request. It reports count differences, not character positions, and intentionally does not remove or rewrite either string.
const before = `PASTE YOUR SAVED SOURCE HERE`;
const after = `PASTE THE COPIED VERSION HERE`;
function counts(text) {
const result = new Map();
for (const character of text) {
const cp = character.codePointAt(0);
const label = `U+${cp.toString(16).toUpperCase().padStart(4, "0")}`;
result.set(label, (result.get(label) || 0) + 1);
}
return result;
}
const a = counts(before);
const b = counts(after);
const labels = [...new Set([...a.keys(), ...b.keys()])].sort();
console.table(labels
.map(codePoint => ({
codePoint,
before: a.get(codePoint) || 0,
after: b.get(codePoint) || 0,
delta: (b.get(codePoint) || 0) - (a.get(codePoint) || 0)
}))
.filter(row => row.delta !== 0));
For the first synthetic pair, the only row is U+200B | before 0 | after 1 | delta +1. For the second, the changed rows are U+0020 | delta −1 and U+00A0 | delta +1. A zero-row table means the two strings have the same per-code-point counts; it does not prove their order is identical, so also compare the text itself if order matters.
Use the result without damaging the text
- Save the source. Keep an untouched copy before pasting into a CMS, word processor, or web form.
- Compare locally. Run the snippet on the saved source and copied result. Avoid pasting private drafts into a third-party inspector if you do not want that service to process them.
- Interpret the delta. A changed code point is a difference, not an authorship marker. Check whether the character has a formatting, language, or emoji function before removing it.
- Make a copy, then clean selectively. Apply the smallest change that fixes the issue you observed. Re-run the comparison and inspect the rendered result in the destination.
- Keep evidence separate from claims. A character-level difference does not predict an AI detector score and does not establish that a text is human-written or AI-written.
What this check can and cannot answer
| It can answer | It cannot answer |
|---|---|
| Which code-point counts differ between the exact two strings you supplied. | Which application or person introduced the difference. |
| Whether a copy/paste step changed a space-like or format character in this example. | Whether text contains a reliable ChatGPT watermark or hidden author ID. |
| Whether selective cleanup changes the measured counts. | Whether an AI detector will accept the text or whether its prose is original. |
Sources and scope
- OpenAI: Understanding the source of what we see and hear online — provenance research and the status of text watermarking.
- Unicode Core Specification, Chapter 23 and Unicode Line Breaking Algorithm — format and line-break behavior.
- Pages reviewed: gptwatermark.com, getgpt.app/watermark, and gpt-watermark-remover.com: Invisible Characters in ChatGPT.
This guide reports a reproducible comparison method and synthetic examples. It does not claim to remove a proven watermark.