Skip to main content

unmark

Remove pen/pencil markings from a PDF - fully offline. No AI, no network. Your files never leave your machine.

pip install unmark
unmark erase "marked.pdf"            # -> "marked clean.pdf"

erase - the main feature

Strips the markings and hands back a clean PDF. It picks the right path automatically:

  • Digital annotations (marks added in GoodNotes / Preview / Adobe, etc.) → deleted losslessly; the original page is restored exactly, text stays text.
  • Marks baked into a scan → colour ink (red/blue/green pen) is removed by channel-dominance detection that leaves the printed text untouched. Options: --pencil (light-grey graphite), --lines (experimental underline erase).
unmark erase "scan.pdf" out.pdf --pencil     # also remove light pencil
unmark erase "scan.pdf" --sat 10             # remove more colour (may leave less)
unmark erase "notes.pdf" --lossless          # PNG pages instead of JPEG

What erase can and can't do (honest)

mark result
digital annotation ✅ removed perfectly (lossless)
red / blue / green pen ✅ removed; text preserved
light-grey pencil ⚙️ removed with --pencil
dark pen / heavy pencil at the same tone as the print ❌ cannot be removed offline - it carries no colour or brightness difference from the real letters. Only AI or manual erasing gets those.

reflow - experimental

⚠️ Experimental. reflow OCRs the printed text (offline, via RapidOCR) and re-typesets a fresh PDF. On clean, single-column papers it's decent. On dense, two-column, or heavily marked papers it is unreliable - it misreads circled option markers, over-splits questions, and leftover dark handwriting bleeds into the text. Always proofread. Offline OCR simply can't match a vision model on messy scans; that's a hard ceiling, not a bug.

pip install "unmark[ocr]"                     # adds the offline OCR engine
unmark reflow "scan.pdf" --columns 1          # single-column works best
unmark reflow "scan.pdf" --pages 1-4          # limit to some pages

How it works

erase: PyMuPDF renders each page → numpy colour/pencil masking → repackaged as a compact greyscale PDF (or the annotation layer is simply deleted). reflow: colour-clean → split columns → RapidOCR → parse → re-typeset (Story API).

License

MIT.

Metadata

Release files for unmark 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for unmark 0.1.0
File Size Uploaded
unmark-0.1.0.tar.gz 11.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for unmark 0.1.0
File Interpreter ABI Platform
unmark-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 23.8 kB

Release files / unmark-0.1.0.tar.gz

Download URL unmark-0.1.0.tar.gz
Size 11.6 kB
Tags Source
SHA-256 checksum
How to use checksums
d007c8e511bd23a1f132662a99d5ed1a92c1b5c79e77897c5bc9e3b36b995c03
BLAKE2b-256 checksum
How to use checksums
e4dcf37b022aa8ece0524ebbdf8e0cc612a7edce76c8868f7e26023de9939960
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.5

Release files / unmark-0.1.0-py3-none-any.whl

Download URL unmark-0.1.0-py3-none-any.whl
Size 12.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
33bbbbdab49517ddf068b3613e7c75e853f32a109f445896f5076b74136c7226
BLAKE2b-256 checksum
How to use checksums
fa44186f10efa9aafaf852dcaaed35b0062b706a65d3c6b0f7f237444ea81bc2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.5

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page