How to Remove Claude Watermarks from Text, Code, and Files
In this article
- Step 1: Understand What Type of Watermark You Are Handling
- Step 2: Rewrite Prose Instead of Moving It Between Files
- Step 3: Use a Rewrite Pass for Text
- Step 4: Treat Code as Refactoring, Not Text Cleaning
- Step 5: Use an AST Rewrite for Python Source
- Step 6: Inspect File Provenance Before Transforming Media
- Step 7: Build a Clean Workflow
- Key Takeaways
Claude watermarks are easy to misunderstand because "watermark" sounds like one hidden marker that can be deleted. In practice, Claude output can be marked in different ways depending on the output type.
For prose, the signal is statistical. The watermark lives in the pattern of wording choices, not in a visible tag or hidden character. For code, the same general idea is constrained by syntax and runtime behavior. For generated files, the relevant signal is usually C2PA provenance metadata attached to supported formats such as PNG, JPG, or SVG.
This guide walks through each case separately. Use these techniques only on content and files you own or are authorized to transform, and keep auditability requirements in mind when working in publishing, legal, compliance, or enterprise settings.
Step 1: Understand What Type of Watermark You Are Handling
The first decision is whether the output is prose, code, or a generated file. Each case behaves differently.
| Output Type | Where the Signal Lives | What Usually Changes It | What to Watch |
|---|---|---|---|
| Text | Statistical word and phrase patterns | Substantial rewriting | Light paraphrasing may leave the pattern intact |
| Code | Text-level choices inside syntax constraints | Refactoring, renaming, comment changes, AST reconstruction | Source changes can break behavior without tests |
| Files | C2PA provenance metadata on supported media | Conversion, re-save, screenshot, derivative export | Removing provenance can weaken audit trails |
Step 2: Rewrite Prose Instead of Moving It Between Files
Claude's text watermarking is not a special character, a document property, or a visible label. It is a distributed pattern created through word selection across a long enough passage.
That means changing the file wrapper is not enough. Copying the text into a new editor, saving it as a different document, or converting Markdown to plain text does not meaningfully change the underlying pattern. The practical lever is rewriting the language itself.
A strong rewrite should preserve the facts while changing sentence structure, paragraph flow, transitions, and wording. A weak synonym swap is not the same thing.
Step 3: Use a Rewrite Pass for Text
The following Python script sends text through a generic OpenAI-compatible endpoint and asks for a full rewrite. The surrounding workflow is simple: read input.txt, rewrite it, and write the result to output.txt.
import os
from openai import OpenAI
def rewrite_text(text: str) -> str:
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
prompt = f"""
Rewrite the following text completely in new wording.
Rules:
- Preserve the facts and meaning.
- Preserve technical accuracy.
- Change sentence structure throughout.
- Do not merely replace a few words with synonyms.
- Rebuild paragraphs where useful.
- Return only the rewritten text.
TEXT:
{text}
"""
response = client.responses.create(
model=os.getenv("REWRITE_MODEL", "gpt-5"),
input=prompt,
)
return response.output_text
if __name__ == "__main__":
original = open("input.txt", "r", encoding="utf-8").read()
rewritten = rewrite_text(original)
with open("output.txt", "w", encoding="utf-8") as f:
f.write(rewritten)
This does not guarantee that every detector will report zero watermark signal. It is a starter pipeline for producing a materially new draft. If your workflow depends on a detection threshold, add a detector check after the rewrite and review the result manually.
Step 4: Treat Code as Refactoring, Not Text Cleaning
Code has less linguistic freedom than prose. It must keep valid syntax, preserve imports, respect function signatures, and continue calling the right APIs. That makes watermarking weaker in some code contexts, but it also makes transformation more fragile.
For example, this loop:
for i in range(len(users)):
process(users[i])
could legally become:
for index in range(len(users)):
process(users[index])
The behavior is the same, but only because the identifier change is applied consistently. The same is not true for arbitrary keywords, public APIs, decorators, or external interface names.
Good code transformation requires normal engineering controls:
- Run tests before and after the rewrite.
- Avoid renaming public interfaces unless you intend an API change.
- Be careful with reflection, serialization, decorators, and framework conventions.
- Treat comments and docstrings separately from executable code.
For production-grade code review processes, pair this with the broader controls in our AI risk management guide.
Step 5: Use an AST Rewrite for Python Source
For Python, one practical way to make source-level changes is to parse the program into an abstract syntax tree, alter selected identifiers, remove standalone docstrings, and regenerate the source.
This is not a watermark decoder. It is a source transformation. It can change formatting and some source-level details, so the rewritten file needs tests before use.
import ast
import keyword
import random
import string
from pathlib import Path
class IdentifierRenamer(ast.NodeTransformer):
def __init__(self, seed: int = 42):
self.rng = random.Random(seed)
self.mapping = {}
def _new_name(self, old_name: str) -> str:
if old_name in self.mapping:
return self.mapping[old_name]
prefix = random.choice(["tmp", "value", "item", "obj", "data"])
suffix = "".join(
self.rng.choice(string.ascii_lowercase)
for _ in range(5)
)
candidate = f"{prefix}_{suffix}"
while keyword.iskeyword(candidate):
suffix = "".join(
self.rng.choice(string.ascii_lowercase)
for _ in range(6)
)
candidate = f"{prefix}_{suffix}"
self.mapping[old_name] = candidate
return candidate
def visit_Name(self, node):
node.id = self._new_name(node.id)
return self.generic_visit(node)
def visit_arg(self, node):
node.arg = self._new_name(node.arg)
return self.generic_visit(node)
def visit_alias(self, node):
if node.asname:
node.asname = self._new_name(node.asname)
return self.generic_visit(node)
def remove_docstrings(tree: ast.AST) -> None:
for node in ast.walk(tree):
if not isinstance(node, (ast.Module, ast.FunctionDef,
ast.AsyncFunctionDef, ast.ClassDef)):
continue
if not node.body:
continue
first = node.body[0]
if (
isinstance(first, ast.Expr)
and isinstance(first.value, ast.Constant)
and isinstance(first.value.value, str)
):
node.body.pop(0)
def rewrite_python(source: str) -> str:
tree = ast.parse(source)
remove_docstrings(tree)
transformer = IdentifierRenamer()
tree = transformer.visit(tree)
ast.fix_missing_locations(tree)
return ast.unparse(tree)
def rewrite_file(input_path: str, output_path: str) -> None:
source = Path(input_path).read_text(encoding="utf-8")
rewritten = rewrite_python(source)
Path(output_path).write_text(
rewritten,
encoding="utf-8",
)
if __name__ == "__main__":
rewrite_file(
"input.py",
"rewritten.py",
)
There are important caveats. This script renames every Name node it sees, which can affect global names and references that should not be touched in real projects. Treat it as a starting point, not a drop-in production refactoring engine. For serious use, restrict renaming to local scopes, preserve imports and public names, and run the test suite.
Step 6: Inspect File Provenance Before Transforming Media
Files are different from text. Claude-supported files can carry a signed C2PA content credential that records provenance. The pixels or SVG markup may not contain a hidden watermark. The relevant evidence is metadata attached to the file.
Before transforming a media file, inspect whether it contains a readable C2PA manifest. Install the Python package first:
pip install c2pa-python
Then run:
import json
from c2pa import Context, Reader
def inspect_c2pa(path: str) -> dict | None:
try:
with Context() as context:
with Reader(path, context=context) as reader:
data = reader.json()
return json.loads(data)
except Exception as exc:
print(f"No readable C2PA manifest: {exc}")
return None
if __name__ == "__main__":
manifest = inspect_c2pa("image.png")
if manifest:
print(json.dumps(manifest, indent=2))
This answers the operational question: does the file contain a readable C2PA manifest?
If the answer is yes, decide whether the provenance should stay with the file. In many publishing and enterprise workflows, preserving that metadata is better than removing it. If you create derivative media through conversion, re-saving, screenshotting, or export pipelines, document that the derivative no longer carries the same credential.
Step 7: Build a Clean Workflow
A clean watermark-handling workflow separates the three cases:
- For prose, rewrite the text substantially and review it.
- For code, refactor through language-aware tools and test the result.
- For files, inspect C2PA metadata and decide whether provenance should be preserved.
That is more reliable than treating all Claude output as if it has one removable marker. It also gives teams a cleaner compliance story: they can explain what changed, why it changed, and what review steps happened before publication or deployment.
Key Takeaways
- Text watermarks are statistical patterns, not hidden characters.
- Code transformations should be treated as refactors and verified with tests.
- File provenance is metadata-driven and should be handled as an audit decision.
- Removing or altering provenance can have policy, compliance, and trust implications.
- The right workflow depends on whether you are handling prose, source code, or media files.
Related Guides

Self-Consistency Voting with Outlines and gpt-4o-mini
Generate ten reasoning chains in one API call, extract integer answers with regex, and vote for the majority—reliably solving multi-step arithmetic.

AI Web Scraping in Python: When an LLM Earns Its Cost
An LLM can read any page without a selector, and it bills you every time. Here is the decision rule, the Crawl4AI code for both paths, and the hybrid that pays for a model once and then runs free.

Build a Text-to-SQL Agent with smolagents in One File
Wire a Hugging Face CodeAgent to a SQLite database so it answers plain-English questions with verified SQL queries.