OpenAI · web chat

ChatGPT Watermark Remover for Copied Code

ChatGPT is reached through a browser far more often than through the API, and the browser is where watermarks attach themselves to code. This page walks the routes text takes out of ChatGPT, the copy button, canvas, the desktop and mobile apps and the API, and says what each route is capable of adding. Paste your text in and the checker names every removal by codepoint, count and line number.

Scan your ChatGPT code now

Free, and it reports every removal by codepoint and line.

Open the scanner

What we measured

68

code-generation calls

17

provider and model targets

59,486

characters generated

0

contained a hidden character

On 2026-08-12 we sent identical code-writing prompts to every model our own gateway can reach and scanned each raw API response. Not one of them contained a zero-width character, a bidirectional control, or a tag character.

3 of the 68 answers contained typographic punctuation, and only in the prose-heavy prompts rather than in the plain code one. The most common was the non-breaking hyphen, which is visible but still breaks a copied command. 2 left trailing whitespace.

The useful conclusion is the boring one: raw model output is essentially clean, so when you do find hidden characters in your file, they almost certainly came from the path the text travelled rather than from the model. That is what the section below is about.

Scope: this measured API output from models we can reach directly. It did not measure the ChatGPT web app, which is the point being made, since the browser is where the characters get added.

How code gets out of ChatGPT, and what each path adds

Copy button on a chat code block medium risk

The code block is HTML in the page, and the copy button hands the clipboard a string built from that HTML. Anything the renderer put there travels with it: no-break spaces used to stop a line wrapping, soft hyphens, and any zero-width character that survived from the model output itself. It is the cleanest browser route, but it is still a browser route.

Selecting prose and copying by hand high risk

Dragging a selection across explanatory text picks up the typographic layer of the page: curly quotes, en and em dashes, and non-breaking spaces around units and short words. If the fragment you wanted was inline code inside a sentence, it arrives with all of that attached and will not parse. This is the single most common way a working snippet turns into a syntax error.

Canvas medium risk

Canvas is an editable document living inside the page, so text in it is shaped by the editor formatting model as well as by whatever you paste in from elsewhere. Getting code back out is the same DOM to clipboard step as a chat code block, with an extra editing surface in front of it where a stray character can be introduced and then never seen again. Treat a paste into canvas the way you would treat a paste into a word processor.

The OpenAI API low risk

A response read from the API is the raw string the model produced, with no HTML layer between the model and your file, which removes the whole category of copy-paste artefacts. It does not make the string clean by construction. A model can emit a zero-width joiner or a tag-block sequence as ordinary tokens, and anything you retrieved from the web and put in the prompt can come back out, so scan the generated file rather than trusting the transport.

ChatGPT has an unusually wide set of exits: the web app, a desktop app that is largely the same web surface in a window, iOS and Android, canvas, and Codex on the command line. The browser-shaped ones behave the same because they share a DOM, so advice about the web app applies to the desktop app unchanged. On mobile the clipboard passes through the operating system and then through whatever app you paste into, and a notes or mail app with autocorrect will happily substitute curly quotes before the text ever reaches a file. Codex is the outlier in the other direction: it writes into your working tree, so there is no clipboard step, and what you check is the committed file rather than the paste.

What this does not do

It does not remove statistical watermarking. Schemes of the SynthID family add no characters at all: they bias which token the model samples, so the signal lives in word choice across the whole output and nothing you can delete carries it. Attacking that means rewriting the text, which for source code risks changing what it does.

This is a hygiene and security tool, not an attribution bypass. Formatters already normalise surface signals, and what identifies generated code is structure and style rather than hidden bytes. Disclose AI assistance wherever you are asked to.

ChatGPT questions

Does the copy button on a ChatGPT code block give me clean text? +

Usually much cleaner than selecting by hand, because you get the contents of a preformatted block rather than a rendered paragraph. It is not a guarantee. The string is still assembled from the page, so it can carry no-break spaces, soft hyphens and zero-width characters, and the report will list any that are present with their line numbers.

Is reading from the API safer than copying from the web app? +

For copy-paste artefacts, yes. An API response has no HTML round trip, so typographic substitution never happens. It says nothing about characters the model itself emitted, or characters that entered through your prompt from a scraped page, a PDF or a pasted log. Check generated files either way.

Will this defeat AI text detection or watermarking? +

No, and it is not intended to. Statistical watermarking works by biasing which token gets sampled, so it lives in word choice rather than in any character you can delete. Stripping hidden characters leaves it entirely untouched. This tool is a correctness tool for files, not a way to pass work off as human-written.

I moved a snippet through canvas and it stopped compiling. What happened? +

Text can pick up formatting going into an editing surface as well as coming out of one. The usual culprits are a no-break space where the parser wanted U+0020, and a curly quote where the language wanted a straight one. Both are invisible in a proportional font and both survive a careful reread. Paste the file in and the report gives you the exact lines.

Other tools