Concept · Page operations
Merge and Split PDFs Programmatically
Last updated: 2026-06-29
A merge appends all pages of one PDF after another into a single file. A split pulls any chosen set of pages into its own new PDF. Both run entirely in your process: no upload limits, no data leaving your server, and no re-rendering of any content.
The simplest analogy: binding and tearing booklets
Imagine you have printed three separate booklets for the three sections of an annual report. Merging them is like taking those booklets and binding them all between two covers, spine first, so all the pages appear in order as one volume. The pages themselves do not change; only the cover changes.
Splitting is the reverse: you take that bound volume and pull out one chapter, setting its pages aside as their own smaller booklet. You are not rewriting the words or reprinting anything; you are deciding which cover each page sits inside.
In code, rust-pdf works the same way. It never re-renders, re-encodes, or reflows any content. Pages are rearranged as-is. What you put in is what you get out, in a different arrangement.
The operations
Five page-level operations, all working on 0-based page indices.
Merge
Append all pages of a second PDF after all pages of the first. Every object in the second document is renumbered by an offset and its references are deep-remapped so the two documents never collide.
Split / Extract
Pull any subset of pages into a brand-new PDF by passing 0-based indices. A reachability pass carries only the objects those pages need; everything else is discarded.
Reorder
Provide a list of page indices in the desired output order. Ideal for fixing scanned books where odd and even pages were captured in separate passes.
Delete
Remove a single page by its 0-based index. All remaining pages shift down. Handy for stripping cover pages, blank separators, or accidental duplicates.
Rotate
Rotate any page by 90, 180, or 270 degrees. The rotation is stored in the page dictionary so every PDF viewer renders it correctly without any content re-encoding.
How it works: a flat page list
PDF files store pages in a tree structure: a root node that fans out into branches and leaf nodes. That tree is efficient for large documents but awkward to manipulate directly. To move a page you would need to detach it from one branch and reattach it to another, updating parent references and rebalancing the tree.
On load, rust-pdf flattens the page tree into a simple ordered list. Each entry in that list is just an object number pointing to a page dictionary. From that point on, merge, split, reorder, delete, and rotate are plain list operations: append, slice, permute, remove, or set a value on a list item.
Highlighted pages are selected by extract_pages([1, 2, 3]).
When you call save(), rust-pdf rebuilds the real /Pages
tree from the list and writes only the objects that are still referenced.
Nothing from discarded pages leaks into the output.
Common use cases
Page operations show up across many document workflows.
Assembling a report pack
Merge a cover page, individual section PDFs generated from templates, and a back-matter appendix into one document ready for distribution.
Bursting a batch
A print run produces one multi-page PDF. Split it into individual per-recipient files so each customer receives only their own statement or letter.
Removing blank or cover pages
Strip the leading cover or trailing blank pages that a scanner or template system inserts before archiving or sending a document.
Reordering scanned pages
A duplex scanner captured odd pages in one pass and even pages in another. Reorder the combined list to restore reading order without rescanning.
Rotating misoriented scans
Some pages land portrait when they should be landscape, or vice versa. Rotate individual pages by 90 or 270 degrees without touching the rest of the document.
Compliance packaging
Assemble signed terms, a signed quote, and supporting appendices into one auditable file that travels as a unit through a contract or approval workflow.
How to merge and split PDFs with rust-pdf
Load, combine or extract, save. Page indices are 0-based.
# pip install rustpdf
import rustpdf
# Merge: append b after a
a = rustpdf.EditableDoc.load(open("part-a.pdf", "rb").read())
b = rustpdf.EditableDoc.load(open("part-b.pdf", "rb").read())
a.merge(b)
a.save("merged.pdf")
# Split: pull pages 1-3 (0-based) into a new file
doc = rustpdf.EditableDoc.load(open("merged.pdf", "rb").read())
doc.extract_pages([0, 1, 2]).save("chapter1.pdf")
// dotnet add package RustPdf
using RustPdf;
using var a = EditableDoc.Load(File.ReadAllBytes("part-a.pdf"));
using var b = EditableDoc.Load(File.ReadAllBytes("part-b.pdf"));
a.Merge(b);
a.Save("merged.pdf");
using var doc = EditableDoc.Load(File.ReadAllBytes("merged.pdf"));
using var chapter = doc.ExtractPages(new[]{ 0, 1, 2 });
chapter.Save("chapter1.pdf");
// go get github.com/rustpdf/rustpdf-go@latest
a, _ := rustpdf.Load(mustRead("part-a.pdf"))
b, _ := rustpdf.Load(mustRead("part-b.pdf"))
a.Merge(b)
a.Save("merged.pdf")
a.Close(); b.Close()
doc, _ := rustpdf.Load(mustRead("merged.pdf"))
defer doc.Close()
chapter, _ := doc.ExtractPages([]int{0, 1, 2})
defer chapter.Close()
chapter.Save("chapter1.pdf")
// npm install rustpdf
const { EditableDoc } = require("rustpdf");
const fs = require("fs");
const a = EditableDoc.load(fs.readFileSync("part-a.pdf"));
a.merge(EditableDoc.load(fs.readFileSync("part-b.pdf")));
a.save("merged.pdf");
const doc = EditableDoc.load(fs.readFileSync("merged.pdf"));
doc.extractPages([0, 1, 2]).save("chapter1.pdf");
Eight language bindings share the same Rust core: Python, C#/.NET, Go, Node.js, PHP, Ruby, Delphi, and Swift. Full details in the documentation.
Merge and split PDF FAQ
How do I merge PDFs in code?
Load both files into EditableDoc objects, call merge() on the first with the second as argument, then save. rust-pdf renumbers the second document's objects by an offset and deep-remaps every cross-reference so nothing collides. The result is a single valid PDF containing all pages from both files.
How do I split a PDF?
Call extract_pages() with a list of 0-based page indices. rust-pdf performs a reachability pass to collect only the objects those pages need, then renumbers them compactly into a brand-new PDF. Pages not in the list are not carried over.
Can I reorder or delete pages?
reorder_pages() takes a list of page indices in the desired output order. delete_page() removes a single page by its 0-based index. Both are list operations on the flattened page list and take effect when you call save() or to_bytes().
Does merging break internal references?
No. rust-pdf renumbers every object in the second document by an offset before merging, then deep-remaps all object references recursively. Cross-references that were valid before remain valid in the merged file.
Can I rotate pages?
rotate_page(index, degrees) rotates a single page by 90, 180, or 270 degrees. The rotation is recorded in the page dictionary and respected by all PDF viewers.
Merge, split, and reorganize PDFs in your language
One Rust core, eight language bindings. Prototype for free; license the corporate features when you ship.