A few weeks ago I built a free online Merge PDF tool that runs 100% in the browser. Today I'm sharing its sibling: a Split PDF tool using the same library — pdf-lib — with zero file uploads, zero watermark, and zero server code.
You can try it live here: https://yourutilityhub.com/pdf/split-pdf
Why split PDFs in the browser?
Most online PDF tools upload your file to a server — which means your document is never truly private. Splitting pages locally means:
- No uploads — nothing leaves your device
- No watermark or signup
- Free — no per-page charges
- Works offline, fast, for files of any size (limited by your browser's memory)
The plan
We'll load the PDF, pick a page range (or specific pages), copy those pages into a fresh PDFDocument, and save the result — all with pdf-lib. Let's walk through the full working component.
1. Install and import
npm install pdf-lib
import { PDFDocument } from "pdf-lib";
2. Load the uploaded file
const arrayBuffer = await file.arrayBuffer();
const pdf = await PDFDocument.load(arrayBuffer);
const totalPages = pdf.getPageCount();
PDFDocument.load() accepts an ArrayBuffer. We read it straight from the File object — no server involved.
3. Split by page range (e.g. 1-5 or 3-)
const parts = pageRange.split("-");
const startRaw = parseInt(parts[0].trim(), 10);
const endRaw = parts[1].trim() === "" ? totalPages : parseInt(parts[1].trim(), 10);
// validate 1..totalPages
const startPage = Math.min(startRaw, endRaw) - 1; // 0-based
const endPage = Math.max(startRaw, endRaw) - 1;
const newPdf = await PDFDocument.create();
const pageIndices = [];
for (let i = startPage; i <= endPage; i++) {
pageIndices.push(i);
}
const copiedPages = await newPdf.copyPages(pdf, pageIndices);
copiedPages.forEach(page => newPdf.addPage(page));
The trick: copyPages() wants 0-based indices, but users type 1-based page numbers, so we subtract 1. "3-" with an empty end means "to the last page."
4. Or extract specific pages (e.g. 1,3,5)
const pages = extractPages
.split(",")
.map(s => parseInt(s.trim()))
.filter(n => !isNaN(n) && n > 0 && n <= totalPages);
const newPdf = await PDFDocument.create();
const copiedPages = await newPdf.copyPages(pdf, pages.map(p => p - 1));
copiedPages.forEach(page => newPdf.addPage(page));
We parse comma-separated numbers, filter out anything out of range, then map to 0-based before copying.
5. Save, download, and clean up
const pdfBytes = await newPdf.save();
const blob = new Blob([pdfBytes], { type: "application/pdf" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "split_" + file.name;
link.click();
Blob + URL.createObjectURL() lets the user download the split file without the bytes ever touching a server.
Full component
The complete, production-ready React component (mode toggle, validation, error handling, and download) is live here: https://yourutilityhub.com/pdf/split-pdf
The full source is also on GitHub: https://github.com/Jalal-khn/utilityhub-
Caveats worth knowing
-
copyPagesreuses the existing page content — it does not re-parse fonts/images per page, so quality is preserved. - Very large PDFs are limited by browser memory. For giant files, consider a server-side approach instead.
- The extracted pages keep their original dimensions and orientation.
Why combine this with Merge PDF?
Many users need both halves of the same workflow — split a big PDF apart, then merge specific pages back into one. Pairing them means users never have to send their documents to a third-party server for either task.
Try it free: https://yourutilityhub.com/pdf/split-pdf
Top comments (0)