DEV Community

Cover image for I deleted a page from a PDF and the file stayed the same size: merge, split and remove tested on five tools
Enlh NG
Enlh NG

Posted on Edited on

I deleted a page from a PDF and the file stayed the same size: merge, split and remove tested on five tools

"Remove page 5" sounds like the simplest PDF operation there is. So I tested it, along with split and merge, on five common tools. Several of them quietly did something other than what the name says: the deleted page's image stayed in the file, bookmarks vanished, a form field was overwritten.

None of these is exotic. They come from how a PDF is built, and they decide whether the "page tools" you use are safe for confidential or interactive documents.

Why page operations aren't just "cut and paste"

A PDF is a graph of numbered objects. A page is one object that points to its content, its fonts and images (often shared with other pages), its link annotations and its form widgets. Bookmarks and links point to pages by object reference.

So deleting "page 5" can mean two different things: remove the page from the list of pages, or also remove everything only that page used. Tools differ in whether they do the second part.

Test files

I generated these with reportlab (script at the end):

File Contents
P.pdf 10 pages. Page 5 holds one unique 900×900 image (2.9 MB file in total)
Q.pdf P.pdf rebuilt so the image sits in one resource dictionary shared by all pages (2.3 MB)
S.pdf 10 pages, 10 bookmarks ("Chapter 1…10"), a link on page 1 to page 8 and a link on page 10 to page 2
F1.pdf, F2.pdf One text field named name each, values "Alice" and "Bob"

Tools (versions as installed in my environment): pypdf 6.17, pikepdf 10.16, PyMuPDF, qpdf 11.9 and poppler's pdfunite/pdfseparate 24.02. KB and MB below use 1,024.

Results of each operation on each tool

Finding 1: "removed" doesn't always mean removed

I removed page 5 (the one with the big image) from P.pdf and looked at the output.

Method Pages Size after Image still in file?
pypdf: copy the other 9 pages into a new writer 9 4.4 KB No
pypdf: PdfWriter(clone_from=...) then remove_page(4) 9 2.9 MB Yes
pypdf: remove_page(4, clean=True) 9 2.9 MB Yes
pikepdf: del pdf.pages[4] 9 4.4 KB No
PyMuPDF: delete_page(4) then save() 9 2.9 MB Yes
PyMuPDF: select([...]) then save() 9 2.9 MB Yes
PyMuPDF: delete_page(4) then save(garbage=4) 9 4.5 KB No
qpdf: --pages . 1-4,6-10 9 4.4 KB No

In the three "Yes" rows the page was gone from the page list (9 pages), but the image object was still inside the file. I pulled it back out of the PyMuPDF output with a few lines of code and got the full 900×900 picture.

That matters if you remove a page because it's confidential. A PDF viewer won't show it. A script, or someone who knows PDF internals, can still get it. For the same reason, a file that doesn't get smaller after you delete its heaviest page is a warning sign.

How to check your own result:

import pymupdf
doc = pymupdf.open("after.pdf")
for xref in range(1, doc.xref_length()):
    if doc.xref_get_key(xref, "Subtype")[1] == "/Image":
        print(xref, doc.xref_get_key(xref, "Width")[1], doc.xref_get_key(xref, "Height")[1])
Enter fullscreen mode Exit fullscreen mode

If an image you removed is listed, it's still in the file. For sensitive pages, use a method from the table that dropped it (qpdf, pikepdf, or PyMuPDF with garbage=4), then run this check on the output. For high-stakes cases (legal, medical, redaction) the safest path is to produce a new file from the pages you keep, and verify it.

Finding 2: splitting can drag along data the page never uses

If every page shares one resource dictionary, a one-page extract may contain the whole thing. In Q.pdf, page 1 draws only text, yet the extracted page 1 was 2.3 MB with all five tools (pdfseparate for poppler). A page of text weighing as much as the whole file.

I tried two pruning options, qpdf --remove-unreferenced-resources=yes and pikepdf's remove_unreferenced_resources(), and neither reduced the size in this test (I didn't find out why). Deleting the unused entry from the page's resources by hand brought it to 700 bytes:

import pikepdf
src = pikepdf.open("Q.pdf")
out = pikepdf.new()
out.pages.append(src.pages[0])
del out.pages[0].obj.Resources["/XObject"]    # only safe if page 1 draws no images
out.save("page1.pdf")
Enter fullscreen mode Exit fullscreen mode

I built Q.pdf myself, so this tells you the pattern exists, not how common it is. Some producers do write one shared resource dictionary for the whole document. If split files come out as large as the original, this is the likely cause.

Finding 3: bookmarks survive only if you ask

I merged S.pdf (10 bookmarks) with P.pdf:

Method Bookmarks in the result
pypdf writer.append(...) 10 of 10
pypdf loop with add_page 0
pikepdf pages.extend 0
PyMuPDF insert_pdf 0 (copy them with get_toc()/set_toc())
qpdf with the bookmarked file as primary input 10 of 10
qpdf --empty --pages ... 0
pdfunite 0

The tool didn't warn me in any of those cases. I only found out by counting.

Finding 4: links and bookmarks that point to removed pages

I removed page 8 from S.pdf; page 1 has a link to page 8, and "Chapter 8" is a bookmark for it.

  • pypdf (clone + remove_page), pikepdf and qpdf kept both. PyMuPDF reports the link and bookmark as now pointing at page 1, which is wrong: the real target was deleted. (I read these with PyMuPDF, so another reader may treat the dead reference differently.)
  • PyMuPDF's own delete_page removed the link, but left "Chapter 8" in the outline with no valid page (-1).
  • pypdf with the copy-pages approach lost all bookmarks (see Finding 3).

Nothing crashed, which is the problem: you get a file with a bookmark that either does nothing or jumps somewhere unexpected.

On merging, links between pages of the same file all survived in the libraries. pdfunite (poppler 24.02) was the exception: both links in my test pointed to page 1 after the merge. pikepdf prints its own warning that pages.extend() may not preserve forms or internal links (use add_pages_from() instead), although in my test the links still resolved.

Finding 5: merging two forms with the same field name

Forms store fields by name. I merged two one-field forms that both use the name name:

  • PyMuPDF insert_pdf and qpdf kept two fields and renamed the second (name [19], name+1).
  • pypdf append() and pdfunite ended up with one field called name, and the field-level value read "Bob". In real use that means editing one box can change the other, or "Alice" is lost, depending on the reader. I didn't test Acrobat.
  • pikepdf pages.extend and the pypdf add_page loop produced a file with no form fields registered in the document's form (the boxes were still drawn on the pages). pikepdf warned that widgets weren't reachable from /AcroForm.

If you merge fillable forms, fill each field and check that the values are independent in the result.

What online tools say about themselves (read from their pages, Nov 2026)

I tested libraries, not these sites. This is what each tool's own page states. "Not stated" means I didn't find it on that page, not that it doesn't exist.

Tool Limits stated Account Files / processing
Smallpdf No numeric limit stated ("Combine PDFs for free") Not stated on the tool page; login and trial buttons are in the header "Automatically deleted from our servers after one hour"; calls itself "cloud-based"
iLovePDF Not stated Not stated Retention not stated; processing location not stated
Adobe Acrobat online Up to 100 files, 1,500 pages merged, 500 pages per file Not required to merge or download; needed to save, organize pages or share "Deleted permanently unless you sign in and save"; no time given
PDFsam Basic None stated (desktop app, AGPL) No sign-up "Entirely on your computer… no file uploads"; Visual edition has a 14-day trial, per its page
Drawboard "No limits or size caps" beyond your device No sign-up "All processing happens directly in your browser"; "never uploaded to our servers"
The PDF Agent Not stated "No account or upload required" (meta description) Says "without uploading the document"; retention not stated

Syncfusion's PDF tools were on my list, but its site blocks automated readers, so I'm making no claims about it.

Two things to take from this. Pages that say "in your browser" are worth a quick DevTools → Network check before you trust them with confidential files (watch for a large request when you add a file). And none of these pages says how it treats bookmarks, links or form fields, so everything in the findings above is something to verify on your output, whatever tool you use.

I also run PDF merge, split and page tools at ToolTiny. Its merge page states up to 20 files of 20 MB each, no sign-up, and deletion from its servers within about 10 minutes. Treat it like the others: run the checklist below on the result.

Checklist after any page operation

  1. Page count and order. Scroll the whole file.
  2. File size. Removed a heavy page and the file didn't shrink? The page's data may still be in there.
  3. Sensitive page? Run the image check from Finding 1 (or try to extract text and images from the output) before sending.
  4. Bookmarks. Open the outline and click each entry.
  5. Links. Click the internal links, especially ones that pointed to removed pages.
  6. Forms. Fill fields on both source parts and check they stay independent.
  7. Keep the original. Work on a copy.

Limits of this post

  • Small synthetic files made with reportlab, not real-world documents. Tagged/accessible PDFs, layers, attachments, signatures and encrypted files are harder, and I didn't test them.
  • I tested libraries and command-line tools, not websites. Online tools may use other engines or settings.
  • Default settings and the calls named in the tables. Other flags or newer versions may behave differently.
  • Links and bookmarks were read with PyMuPDF; a different reader may interpret a dangling reference differently.

If a page operation broke one of your PDFs in a way not covered here, describe it in the comments (the structure, not the content). I'd like to add it to the test set.

Top comments (0)