Skip to content

Repository files navigation

UnmarkPDF

中文

UnmarkPDF is a local, auditable PDF watermark cleanup tool. It produces a cleaned PDF, Markdown, page renders, and evidence for reviewing every run.

UnmarkPDF architecture

Download and open the interactive HTML diagram.

Install

Requirements:

  • Python 3.11–3.13
  • Windows, macOS, or Linux
pip install .

For development, use uv sync.

Quick Use

unmarkpdf input.pdf

Replace input.pdf with the PDF you are authorized to process. Output is written to unmarkpdf-output/ by default.

Try the bundled synthetic sample:

unmarkpdf data/sample-watermarked.pdf

It contains two pages with CONFIDENTIAL and DRAFT text watermarks. A successful run removes two text spans while preserving the body text. Regenerate it at any time with:

python scripts/generate_sample.py

For all options:

unmarkpdf --help

How It Works

  1. Discover: inspect text spans for light color, rotation, size, repetition, and stable position. Suggestions go to watermark-candidates.json and are never applied automatically.
  2. Clean: remove standard watermark annotations and artifacts; hide keyword-matched OCG layers; conservatively remove keyword-matched text and repeating watermark images.
  3. Audit: compare original and cleaned page renders, count keyword hits, and write audit.json.
  4. Convert: send cleaned.pdf to MarkItDown, falling back to PyMuPDF text extraction if parsing fails.

All core processing stays inside the local-process boundary shown above. Optional VLM review is manual and does not run inside the CLI.

Watermark Keywords

The defaults are:

机密, 水印, 内部资料, Confidential, Watermark, Draft

Keywords matter only for watermark forms that lack reliable PDF markers:

Watermark form Uses keywords
Watermark annotation No
/Subtype /Watermark artifact No
Repeating image No
Named optional-content layer (OCG) Yes
Untagged text Yes

Text is removed only when it also looks like a watermark: light or rotated, and not overlapping detected body text. This reduces false positives, but document-specific text such as a name, email, company, timestamp, or “仅供某某使用” may be missed.

--keywords replaces the defaults:

unmarkpdf input.pdf --keywords "ACME-7391,Internal Copy"

--keywords-file appends UTF-8 lines to them:

# watermark-keywords.txt
ACME-7391
Internal Copy
unmarkpdf input.pdf --keywords-file watermark-keywords.txt

Local Discovery

Every run inspects PDF text spans for light color, rotation, large size, central placement, repetition, and stable page position. Suggestions are written to watermark-candidates.json.

Candidates are advisory only and are never applied automatically. Review them, copy confirmed phrases into a keyword file, and run again with --keywords-file. This explicit step prevents a light title or repeated template text from being silently removed.

Discovery reads the PDF text layer. It cannot read watermark text flattened into a scanned image.

Optional VLM Review

UnmarkPDF makes no network or model request. A local or remote VLM can help review difficult pages:

  1. Run UnmarkPDF once.
  2. Give selected renders/page_XXXX_original.png files to a local or remote vision model.
  3. Ask for only the exact visible watermark phrases, one per line.
  4. Review the result and pass confirmed phrases with --keywords-file.
unmarkpdf input.pdf --keywords-file vlm-reviewed-keywords.txt

This provider-neutral handoff keeps the core small and works with local models. The confirmed phrases can help only when the PDF still has a matching text layer or OCG name. They do not remove words flattened into image pixels; that requires localization and image restoration, not only a VLM description.

A remote VLM receives page contents, so do not upload confidential documents without authorization. A VLM may identify text, but it cannot reconstruct pixels destroyed by an opaque watermark.

Output

Each run writes these files to the output directory:

Path Description
original.pdf Copy of the input PDF
cleaned.pdf Structurally cleaned PDF
content.md Markdown converted from cleaned.pdf
audit.json Processing stats, keyword counts, render diffs, warnings, and parser name
watermark-candidates.json Advisory local heuristic suggestions
renders/page_XXXX_original.png Rendered original page
renders/page_XXXX_structural.png Rendered structurally cleaned page
renders/page_XXXX_ocr_candidate.png Grayscale/thresholded OCR candidate render

The OCR candidate render is for inspection only. It does not replace cleaned.pdf.

Parsing

UnmarkPDF uses MarkItDown as the primary Markdown parser. If MarkItDown fails, it falls back to plain PyMuPDF text extraction and records a warning in audit.json.

Platform Support

The CLI uses platform-neutral Python paths and file operations. CI tests Python 3.11 and 3.13 on Linux, plus Python 3.13 on Windows and macOS.

Limits

  • Opaque watermarks that destroyed the original pixels cannot be reliably restored.
  • Single-page vector watermarks may be missed if they have no standard PDF watermark marker and do not match the configured keywords.
  • Local keyword discovery cannot inspect text embedded only in pixels.
  • Heuristic and VLM suggestions must be reviewed; neither is proof that text is a watermark.
  • Fixed OCR-candidate thresholds do not work equally well on every colored background.
  • Markdown quality for tables, columns, and reading order depends on the underlying parser.

Privacy and Authorized Use

UnmarkPDF runs locally and writes outputs to the selected output directory. Do not use it to remove ownership, provenance, access-control, or confidentiality marks unless you own the document or have explicit authorization.

License

UnmarkPDF is licensed under AGPL-3.0-only; see LICENSE.

PyMuPDF is also AGPL by default and offers a separate commercial licensing path. If you distribute or provide a modified service based on this project, review both this project's AGPL obligations and the licenses of its dependencies.

Contributing

Keep changes small, auditable, and covered by a representative run when behavior changes.

About

A tool to remove watermarks in pdf files

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages