DEV Community

PDFnoted
PDFnoted

Posted on Edited on

Three kinds of PDF watermarks, and why most removers only handle one

"Just remove the watermark" is one of those tasks that sounds trivial until you open the file. I've lost count of how many times someone has told me a tool "doesn't work", when the real issue was that they were dealing with a different kind of watermark than the tool was built for.

There are three, and they live in completely different places in the file.

Type 1: an annotation

This is the easy one. The watermark is an object in the page's /Annots array — the same mechanism as a sticky note or a highlight. It's drawn on top of the page, but it isn't part of the page content.

Anything that can edit annotations can delete it. On the command line:

# see what annotations exist
pdfinfo -meta file.pdf
qpdf --show-object=trailer file.pdf | head
Enter fullscreen mode Exit fullscreen mode

Most "PDF watermark remover" tools stop here. Which is fine, as long as that's what you actually have.

Type 2: a Form XObject

This is where it gets interesting. The watermark is a reusable content object referenced from the page's resource dictionary and painted via a Do operator in the content stream. It is page content now — there's no annotation to select and delete.

Removing it means:

  1. finding the XObject in /Resources /XObject
  2. following the mapping through /Form and the Matrix × Do CTM combination (a naive search misses nested forms)
  3. deleting the object and its reference
  4. writing the stream back and clearing the stale filter keys (Filter, DecodeParms, F, FFilter, FDecodeParms, DL)

Step 2 is why simple text-matching approaches fail. The content stream is compressed, the object may be nested several levels deep, and the positioning math is composed at draw time rather than stored as coordinates.

Type 3: baked into a scan

If the PDF is a scanned image, the watermark is pixels. No PDF-level tool will remove it — that's image editing, and results are usually ugly.

Worth checking before you try anything else:

pdftotext file.pdf - | wc -c
Enter fullscreen mode Exit fullscreen mode

If that returns almost nothing, you're looking at a scan. Stop trying PDF tools.

How to tell which one you have

Quick heuristic:

pdfinfo file.pdf | grep -i pages
pdftotext file.pdf - | head -20        # text present?
qpdf --qdf --object-streams=disable file.pdf out.pdf
grep -a -n "/Annots\|/XObject\|/Watermark" out.pdf | head
Enter fullscreen mode Exit fullscreen mode

If /Annots shows up with a /Subtype /Watermark entry, it's type 1. If you find /XObject forms that don't correspond to visible images, it's probably type 2.

The part that actually matters

Whatever you remove, verify afterwards. A lot of tools — including some well-known paid ones — "remove" content by drawing an opaque rectangle over it. The underlying text is untouched and trivially recoverable:

pdftotext cleaned.pdf - | grep -in "confidential\|salary\|身份证"
Enter fullscreen mode Exit fullscreen mode

If that prints anything, the file is not clean. I've seen contracts go out to counterparties with the "redacted" salary figure still in the text layer, because whoever prepared it trusted the visual preview.

For type 1 and 2, a proper removal should survive this check. For type 3, it won't — and that's the honest signal that you need a different approach.


Disclosure: I work on PDFnoted, which does object-level watermark removal and re-scans the file after cleaning. The three-type distinction here is tool-independent though — knowing which one you have will save you most of the time regardless of what you use.

Top comments (0)