Deleting a page from a PDF may not remove it

By Richard Bailey

When you delete a page from a PDF, the page disappears from view. Whether it disappears from the file is a separate question, and the answer depends entirely on how the software you used saves the result. I found this out while building this site’s PDF page remover, and the measurement was enough to change how the tool works.

The measurement

I made a ten page PDF, each page had a heading and twenty lines of text I deleted nine of its pages using the obvious method in pdf-lib, a widely used PDF library, then saved it. The original was 7769 bytes. The one page result was 7744 bytes.

Nine pages “deleted”, and the file shrank by 25 bytes. Rebuilding the same one page document from scratch produced a file of 1393 bytes. Nearly all of the 6351 byte difference is the nine deleted pages, still sitting in the first file.

Why it happens

A PDF is not a stack of pages. It is a collection of numbered objects: page descriptions, fonts, images, streams of drawing instructions. One of those objects is the page list, which says which page objects make up the document and in what order.

The cheap way to delete a page is to take it out of that list. Every viewer then shows one page fewer, but the page’s objects, its text, its images, are still in the file. Nothing points at them any more, and nothing deletes them either. Anyone who opens the file with a text editor or a PDF debugging tool, or who has a reason to look, can dig them out.

There is a second way to end up in the same place. The PDF format allows edits to be saved as an incremental update: the changes are appended to the end of the file and the original bytes are left exactly where they were. It is a deliberate part of the format (ISO 32000, section 7.5.6), designed so that large files save quickly and signatures stay valid. It also means the version before your edit can still be inside the version after it.

The difference, in code

For anyone working with PDFs programmatically, this is the whole problem in a few lines of pdf-lib:

import { PDFDocument } from 'pdf-lib';

const source = await PDFDocument.load(bytes);

// In place: page 2 leaves the page list, but its objects are still saved.
const edited = await PDFDocument.load(bytes);
edited.removePage(1);
const looksDeleted = await edited.save();

// Rebuilt: a new document that only ever contains the pages you keep.
const rebuilt = await PDFDocument.create();
const keep = source.getPageIndices().filter((i) => i !== 1);
for (const page of await rebuilt.copyPages(source, keep)) rebuilt.addPage(page);
const reallyDeleted = await rebuilt.save();

Both results show nine pages in any viewer. Search the bytes of looksDeleted for an image that was on page 2 and you will find it; search reallyDeleted and you will not.

How to check a file you have already sent

The file size is the quickest tell. If removing a substantial page, one with an image or a lot of text, barely changed the size, the content is probably still there.

Searching the file for a word you deleted is less useful than it sounds. Page content is usually compressed, so the absence of the word in a plain text search proves nothing either way.

How to delete pages for real

Use a tool that builds a new document from the pages you keep, rather than one that edits the page list. That is what this site’s page remover does, and it is why the file it gives you shrinks the way you would expect. The trade-off is that a rebuilt document loses bookmarks and fillable form fields, because those belong to the document as a whole rather than to its pages.

One caution applies whichever tool you use. Deleting a page removes that page. If its figures are quoted on another page, they are still quoted there. Removing pages is not the same as redacting a document, and when the stakes are high it is worth reading what is left before you send it.