1 September 2026
Two documents,
one object number 4
Both documents contain an object numbered 4, and they mean different things. Everything difficult about merging follows from that.
1 September 2026
Both documents contain an object numbered 4, and they mean different things. Everything difficult about merging follows from that.
Concatenating two PDFs produces a file that opens as the first document and ignores the second, or does not open at all. The reason is that a PDF is not a stream of pages. It is a set of numbered objects with a table at the end saying where each one begins, and both documents number their objects from one. Put them together and the reader finds two competing definitions of object 4, two catalogs, and two cross-reference tables, and it uses whichever it finds first.
You have to walk the page tree of each document to find the pages in order, then for every page copy not just the page object but everything it depends on: its content stream, its fonts, the descriptors those fonts point at, the embedded font programs, its images, the colour spaces those images use. That dependency graph can be dozens of objects deep for a single page. Each one gets a new number in a fresh space, and every reference inside every copied object has to be rewritten to match.
A page can leave its media box, its resources and its rotation unspecified and inherit them from a parent node in the page tree. Copy the page on its own and those attributes are simply gone: the page loses its size, or its fonts, and renders blank or wrong. So the tree has to be walked with the inherited values carried down, and anything the page did not specify for itself has to be written onto the copy explicitly before it is detached from its original parent.
Since PDF 1.5 a document can pack most of its objects into compressed object streams, and replace the cross-reference table with a compressed stream too. Simple merge scripts that scan for the text pattern “N 0 obj” find almost nothing in these files, because almost nothing is stored that way. Anything exported from Word, printed from a browser, or saved by most modern libraries looks like this. Handling it means decompressing those containers and unpacking the objects inside before the real work starts.
Because of what people merge. Scanned identity documents for an application. A signed contract with its annexes. Payslips assembled for a mortgage. Medical letters. These are the documents where uploading to an unknown company is least appropriate, and they are exactly the documents mainstream merge tools require you to upload. Doing the work on the device removes the question rather than answering it.