Preparing offline tools…

Lyonite
Measured results

PDF revision history: what five cleaners removed

A PDF can retain earlier drafts when an editor appends changes instead of rewriting the file. I built a fixture with five retained states and tested whether five cleaners removed its old values. The results describe this fixture and these tool versions.

Tested by .

Tested 6 September 2026, 11:14 PM EDT. Explanation corrected 21 September 2026; measurements unchanged.

Correction — 21 September 2026

The original wording treated save counts and raw end-of-file markers as proof of retained drafts. That was too broad. This report now distinguishes the synthetic fixture from other PDFs, describes the four string checks, and explains the limits of revision counts. The measurements below remain those recorded on 6 September.

What I planted

The fixture starts with a base PDF, then deliberately appends four incremental updates. That produces five file states. The updates set these properties:

  • Update 1 — Jane Doe, "Draft one"
  • Update 2 — "Draft two", marked Internal only
  • Update 3 — author changes to Priya Raman, "Draft three"
  • Update 4 — "Final", marked confidential, written on Reviewer Workstation 4

The current properties name Priya Raman and Final. The raw bytes also contain Jane Doe and the three earlier titles. The verifier searches for those four strings after cleaning; the table’s “4 of 4” refers to those checks, not four complete recovered documents.

This is a synthetic test of incremental saves. It does not establish how often ordinary PDFs retain earlier versions.

Why the old version is still in there

An incremental save appends changed objects and a cross-reference section to the file. Earlier bytes remain, and a reader follows the cross-reference information to assemble the current state.

Other save operations rewrite the PDF. Edits made before such a rewrite may leave no recoverable earlier state in the file you receive. Four edits do not necessarily mean four retained drafts.

Incremental updates can preserve the bytes covered by an existing digital signature. Whether later changes are permitted and whether the signer is trusted are separate checks.

Why a properties panel can miss earlier values

A normal properties panel reports the current document fields. That is useful, but it does not establish whether old values remain elsewhere in the file.

In this fixture the planted strings are uncompressed, so a raw-byte search finds them. Historical values in compressed or encoded objects may require decoding. A missing text match is not proof that a value is absent.

A revision-aware parser can follow earlier cross-reference sections and inspect retained states. The edit-history guide explains how to do that in Lyonite and how to interpret incomplete results.

What each cleaner did

Measured 6 September 2026, 11:14 PM EDT by scripts/compare-revisions.mjs, against a fixture built by scripts/make-revisions.mjs. Counts use the experiment’s marker-based diagnostic; the four planted-string checks determine whether historical values survived. These checks do not recover complete drafts. Tool versions are given because command-line tools change; any row can be rechecked with one command using the published test files.
ToolRevisions in the outputRevisionsHistorical strings still in the bytesStrings left
exiftool -all=13.556 — one more than it started with4 of 4 still presentAppended an incremental update. All four checked historical strings remained, even though the current properties no longer reported them.
mat20.15.02 — its own update over a rewritten basenoneNone of the four checked historical strings remained. This run rasterized the page; see the separate text-preservation measurement below. The extra state was appended over a rewritten base.
qpdf12.2.01noneRewrote the file and removed the four checked historical strings. Current document properties remained; this result does not establish complete metadata removal.
Ghostscript10.07.11noneRe-rendered the document into a new file. None of the four checked historical strings remained; current document properties were retained.
Lyonitebuild of 6 September 20261noneRewrote the file and removed the four checked historical strings. The cleaning report includes before-and-after revision information when available.

The one that removed everything, and what it cost

In this run, mat2 removed the checked historical strings by rasterizing the pages. That can discard information that a narrower metadata edit leaves behind, but it also changes what readers can do with the document.

The separate one-page text fixture shows the tradeoff:

One page of text, through both tools. Measured 6 September 2026, 11:14 PM EDT; text counted with pdftotext.
FileSize in bytesBytesSelectable textTextWhat the page reads asReads as
The original—2,152330 characters“Lyonite test page 1. The quick brown fox…”
After mat240.5× larger87,2545 charactersnothing — the page is now a picture
After Lyonite0.9× — slightly smaller1,968330 characters“Lyonite test page 1. The quick brown fox…”

The measured mat2 output retained only 5 extractable characters from the original 330. The page’s original selectable text was lost, and the output was 40.5 times larger.

That tradeoff may be acceptable for some uses. It matters when a document needs searchable text or accessible reading. Check the settings and output of the version you use.

On this test, Lyonite removed the checked historical strings while retaining all 330 extractable characters. This is a result for these fixtures, not a guarantee about every document.

What to do about your own files

Appending a metadata change leaves the existing bytes in place. To discard earlier incremental file states, use a tool that rewrites the file, then inspect the result.

A rewrite alone does not remove identifying information that remains in current page text, images, comments or other retained objects. Review those separately and keep the original if you need to preserve evidence or signatures.

Use Saved versions in the viewer to inspect retained states. Read any incomplete-history notice and compare an earlier state with the current copy. A raw %%EOF count is only a clue: linearization, embedded data and malformed files can make it misleading.

What Lyonite does

Lyonite reads the current PDF objects, removes supported metadata and writes a new file. The original incremental save chain is not copied into that output. This is separate from removing values still present in current content or retained objects.

The tool reopens the result and reports the checks it completed, including available before-and-after revision information. Unsupported or incomplete checks need review; a clean report is not proof that a document is anonymous.

What this test does not tell you

  • It is a synthetic fixture. Four string checks stand in for earlier names and titles. They do not test recovery of complete drafts, every encoding or every PDF structure.
  • The counts are diagnostic. The experiment uses marker counts with a linearization adjustment. A count is not proof of a complete save history; the separate planted-string checks determine the table’s outcome.
  • Rewriting invalidates signatures over the original bytes. Keep the original signed file if its signature matters.
  • Tools and settings change. The table names the versions tested on 6 September 2026. The fixtures and scripts are published for reruns.
  • I maintain Lyonite. It is included in the comparison, so the test method and limitations should be checked independently.

Questions

How do I tell if my PDF has old versions in it?
Open Saved versions in the PDF Metadata Viewer and read any incomplete-history notice. If earlier states are found, inspect their properties or compare a downloaded version with the current copy. A raw count of %%EOF strings does not reliably count edits or recovered drafts.
Does exiftool -all= remove metadata from a PDF?
It changes supported metadata through an incremental update, so earlier bytes can remain recoverable. In this fixture it added a sixth state and left all four checked strings from earlier drafts. Check historical data separately from the current properties.
What about -pdf-update:all=?
It removes ExifTool’s own PDF update information to restore the file before those updates. It is an undo operation, not a general way to remove earlier revisions from other editors.
Should I just use mat2?
mat2 is another option, but inspect the output and its settings before choosing it. With the version and defaults in this test, it rasterized the page: 330 extractable characters became 5 and the file grew from 2,152 to 87,254 bytes. That tradeoff may be unsuitable for documents that need selectable text.
Will removing old versions change how my document looks?
It depends on the tool, settings and file. A rewrite can retain the current appearance while discarding earlier states, but some cleaners rasterize pages or alter document features. Review the output and keep the original. Rewriting invalidates existing signatures over the original bytes.
Is this a flaw in the PDF format?
No. Incremental updates are part of the PDF format and allow changes to be appended without replacing earlier bytes. Some editors use them and others rewrite the file. A current-properties check and an inspection of retained history answer different questions.
Corrections

Check this yourself. If I got it wrong, tell me.

Every number here came from files you can download and a checker you can run, so you do not have to take my word for any of it — clone the corpus and get your own result.

If it disagrees with mine, or if you build one of the tools named here and I measured it unfairly, out of date, or with a setting you would not have used, send it to hello@lyonite.com.

I reply within 48 hours. If you are right, the page is corrected with the date on it and your correction credited, and the old number stays visible so the change is legible. If a tool has since been fixed, that is the update I most want to publish. Nothing here is worth defending past the point it stops being true.

Keep reading

Technical references