•9 min read

OpenAI textGrain Watermark: How It Works and Why It Breaks

OpenAI textGrain watermark ships in the EU for AI Act compliance. See how the statistical signal works, where it breaks, and what counter-tooling exists.

#textGrain#OpenAI watermark#AI provenance#EU AI Act#SynthID#AI watermark detection#LLM watermarking#content provenance
Crissa

Crissa

Author

OpenAI textGrain Watermark: How It Works and Why It Breaks

What textGrain Actually Does

On 5 October 2026, OpenAI published Our approach to EU text provenance rules and a 20-page technical report. The method is called textGrain, and the headline is simple: it hides a statistical signal inside the model's word choices.

There is no visible mark, no invisible Unicode, no file metadata. The signal lives in the words themselves, which is why it survives copy-paste. To detect it, you need two things: the text, and a secret key held by OpenAI.

This is not a new idea in the field (Kirchenbauer-style green-list watermarks and Aaronson's keyed-Gumbel/EXP scheme have been around for a while), but it is the first time OpenAI has shipped one at scale. The trigger is legal, not technical: EU AI Act Article 50 transparency obligations came into force on 2 August 2026, and textGrain is OpenAI's answer.

Scope matters more than the maths for most readers:

  • EU only for ChatGPT and Codex, all plans, rolling out "over the coming weeks".
  • API customers worldwide can opt in, off by default.
  • Outside the EU, ChatGPT text is not watermarked unless you deliberately opted in.
  • The detector is not public. Access is by application, limited to approved researchers and expert organisations.
  • OpenAI says it plans to open-source the technique.

If you are not in the EU and not on the API with the flag on, textGrain does not touch your output. That is the practical headline.

How Detection Works

textGrain is an entropy-calibrated watermark. The technical report (co-authored with researchers from UPenn and Yale) frames it as an optimal-transport problem with Gumbel random variables and an "entropy budget".

In plain terms: every time the model picks a word, it has some freedom (high entropy) or almost none (low entropy). textGrain spends its watermarking budget where the model has real choices, and stays quiet where the next token is basically forced. The result is a signal that is statistically detectable with the right key but imperceptible to a reader.

The detector checks the text against that statistical pattern. No key, no detection. OpenAI explicitly states the watermark does not encode your identity, account, prompts, or conversations, and it does not measure human contribution, establish ownership, verify accuracy, or identify the user.

One line worth memorising: absence of a watermark does not mean human authorship.

How Well It Works (OpenAI's Own Numbers)

OpenAI published detection rates at a 1% false-positive target, measured on ELI5 English (a psychology-style Q&A dataset):

  • ~95% detection on 400-token passages.
  • ~80% on 200-token passages.
  • Mathematics and structured content: "substantially lower", because there is less flexibility in word choice to hide a signal in.
  • No meaningful quality regression on Astra benchmarks (the blog includes the table; GPQA Diamond moved from 94.44% to 93.94%, for example).

Editing is where it gets interesting. On 400-token passages:

  • Unedited: ~92% detection.
  • 10% of words swapped for synonyms: drops to ~66%.
  • 25% of words swapped: drops to ~17%.

Translation is an explicit degradation vector. Across 24 EU languages at the same 1% false-positive target, Spanish came out best at 69.0% detection and Romanian worst at 42.2%. Those multi-language figures come from the OpenAI Help Center article on provenance signals, not the blog post, which is a sourcing detail worth knowing if you cite them.

Three Caveats That Change How You Read Those Numbers

  1. Every number is self-reported. The detector is closed. No independent third party has replicated the 92/66/17 figures. They are OpenAI's own evals on OpenAI's own English dataset.

  2. The technical report contains none of those percentages. The 20-page PDF is pure theory and methods (entropy budget, optimal transport, Gumbel variables). The empirical numbers live only in the blog post and the Help Center article. If someone writes "the technical report found 92% detection", they are misattributing.

  3. 92% is a ceiling, not a typical case. Best case means English, unedited, long passage, psychology Q&A. Real-world text is shorter, edited, translated, or structured, and all of those degrade the signal.

Read the numbers with those three filters and the story shifts. textGrain works in a lab-shaped corner of reality and degrades fast outside it.

Open-Source Counter-Tooling Already Exists

This is the part that turns "the watermark exists" into "the watermark is the opening shot, not the end state". Open-source counter-tooling for exactly this class of mark is already shipping, and it is worth understanding why it fits.

The repo is guillaumemeyer/watermarks-remover: MIT-licensed, Python, 26,069 stars and 2,969 forks as of early November 2026, last pushed the day before this post was written, on v0.7.0. It is actively maintained, not a toy.

What It Targets

The repo ships three layers of counter-tooling:

  • Layer A removes invisible Unicode: exotic spaces, bidirectional control characters, tag characters. Pure Python, no dependencies.
  • Layer B counters statistical (token-sampling) text watermarks by rewriting rather than stripping, via an optional rewrite_text.py hook.
  • File-layer stripping for C2PA, EXIF, XMP, and document properties across roughly 25 formats (PNG, JPEG, WebP, AVIF, HEIC, PDF, DOCX, XLSX, PPTX, EPUB, MP4, WAV, MP3, and more).

The vendors it names by class are Claude, Gemini/SynthID-Text, OpenAI provenance surfaces, and open-LLM Kirchenbauer green-list plus keyed-Gumbel/EXP (Aaronson) marks. That last class is the relevant one: textGrain is Gumbel-based, so this repo addresses exactly the family of watermark OpenAI just shipped.

The Technically Interesting Module: stealer/

stealer/ is a black-box watermark-stealing pipeline for SynthID-class text watermarks. It does not recover the secret key. Instead:

  1. Query a watermarked model with many benign prompts and collect long replies.
  2. Count next-token frequencies per short context against a non-watermarked baseline (the baseline does not have to be the same model).
  3. Emit s*(token | context), an estimator of how much each token is being boosted by the watermark.
  4. A paraphraser then subtracts delta * s* from candidate logits to demote the "green" tokens.

s* is an estimator, not the true green set, which is the honest limitation. But the architecture is the point: the watermark is a statistical bias, and a statistical bias can be estimated and countered from black-box access alone, without the key.

Architecture: Thin Client Plus a Service

The skill is a thin client. All cleaning runs in a separate HTTP service under service/, so the agent host needs no Python, venvs, or cleaning tools. A .claude-plugin/ marketplace plugin ships a PostToolUse hook that fires on Write|Edit|MultiEdit|NotebookEdit. In check mode it reports marks to the model; in clean mode it strips them in place.

There is a meaningful design distinction here worth pausing on. A skill is advice the model can choose to ignore. A hook is executed by the harness on every matching write. The deterministic half of this repo is the hook, not the skill, and that is why it actually runs.

Real Install on a Headless Box

The repo's own installer targets Claude Code, Codex, Cursor, and Cowork. There is no native Hermes target (zero mentions of "hermes" anywhere in the repo), but it works via symlink. The verified commands:

python3 install_skill.py --skill remove-ai-marks --target claude-code

It also ships clean-user-facing-text, a self-contained text-only skill.

The service starts cleanly:

make serve
# or
python3 service/scripts/server.py --host 127.0.0.1 --port 8765

A health check returns the expected response:

curl http://127.0.0.1:8765/health
# {"ok": true, "version": "dev"}

The honest caveat: on a small headless box, GET /capabilities reports only Layer A (Unicode), the metadata layer, and a stylometry scorer as available. c2patool, exiftool, qpdf, ghostscript, the markllm and SynthID text detectors, and the pixel/diffusion backends are all absent (ffmpeg is present). The statistical-watermark and C2PA tooling needs extra server-side dependencies. The Unicode and container-metadata layers work out of the box.

The Ethics Boundary the Repo Ships

The repo includes an ethics stance in references/ethics.md, and it is worth quoting the shape of it: the tool is for content you own or are authorised to process. It is not for academic fraud, not for circumventing lawful disclosure rules, and not for claiming cleaned content is human-written for compliance theatre. It also warns that a successful metadata strip does not mean no provenance remains, because SynthID-class and soft-bound signals can survive.

This post is not a how-to-remove-your-watermark tutorial, and the repo's own ethics line is the right frame: treat it as research-grade tooling that demonstrates the attack surface, not an endorsement of evasion.

What textGrain Does Not Prove

This is the section to read twice. OpenAI is explicit about the limits, and they matter more than the detection percentages:

  • textGrain does not measure how much of a text a human wrote.
  • It does not establish ownership or responsibility.
  • It does not verify the accuracy of the content.
  • It does not identify the user.
  • Absence of a watermark does not prove human authorship.

A watermark that says "a model generated this" is not the same as a watermark that says "a human did not." OpenAI is careful not to claim the second, and anyone building policy on top of textGrain should be equally careful.

The Backstory: OpenAI Almost Shipped This In 2024

OpenAI built a working text watermark in 2023 to 2024 and then shelved it for roughly a year. Per a WSJ report, the reasons were commercial and social, not technical:

  • About a third of surveyed ChatGPT users said a watermark would turn them off.
  • Concern that it would disproportionately flag non-native English speakers.
  • Fear that users would switch to non-watermarked rivals.

One insider's quote: "It's just a matter of pressing a button."

What changed is the law, not the calculus. EU AI Act Article 50 forced the issue, and OpenAI shipped. The earlier classifier (killed in July 2023 at 26% true positive and 9% false positive) is the cautionary tale: detection tools that overpromise and underdeliver get retired publicly.

A social-media claim of "99.9% accuracy" is still circulating. It is a stale rumour about the shelved 2024 watermark, a different system, misapplied to textGrain. Ignore it.

Images and Audio Are Already Handled

Text was the gap because it carries no file metadata. Images and audio are not: OpenAI uses Google DeepMind's SynthID for images and audio, plus C2PA Content Credentials, and ships a public verification tool at openai.com/verify.

One open question worth flagging, not concluding: an arXiv paper ("Abductive Corroboration of Probabilistic AI Models for Forensic Synthetic Media Detection") found that 36 of 200 AI-generated images carried SynthID, with the earliest dated 25 April 2026, roughly a month before OpenAI's 19 May announcement. The dating comes from X post timestamps, not generation dates, so it is circumstantial. Frame it as "researchers found evidence of pre-announcement deployment", not as fact.

The Practical Takeaway

For most of the world, textGrain is not on your output. If you are in the EU or opted in via the API, it is, and it is detectable only by approved parties with the key. The numbers are real but self-reported, fragile to editing and translation, and best-case is a long, unedited English passage. Open-source counter-tooling for the Gumbel-based class textGrain belongs to is already shipping with 26,000 stars and an active maintainer.

The honest read: textGrain is a compliance-driven first move, not a forensic lock. Treat the detection rates as a ceiling, treat the detector as closed until independently replicated, and treat the counter-tooling as evidence that the watermark arms race is already running in both directions.


Join the Verse

Get exclusive insights on Next.js, System Design, and Modern Web Development delivered straight to your inbox.

No spam. Unsubscribe at any time.