Why another PDF tool? Because privacy shouldn't be a premium feature.
We've all been there. You have a 40-page PDF report, your client needs pages 12–18, and the only tools you can find either slap a watermark on the output, cap your file size, or — most troublingly — upload your document to some server you've never heard of before "processing" it.
That last part should bother you more than it does.
I built iHatePDF's Split PDF tool to solve exactly this problem. It's fast, it's free, it has no file size limit, and — most importantly — your files never leave your device. Not a single byte.
Here's the full story.
The Problem with Most Online PDF Tools
Online PDF utilities are everywhere. But most of them share an uncomfortable architecture: you upload your file, it travels to a remote server, gets processed, and then gets sent back to you. Along the way, your document — which might contain contracts, medical records, financial data, or intellectual property — passes through infrastructure you don't control and likely don't understand.
Some tools are upfront about this. Many are not. And even the honest ones that promise to "delete your file after 1 hour" are asking you to take their word for it.
There's a better way.
The Core Idea: Keep Everything in the Browser
Modern browsers are incredibly capable. Thanks to APIs like the File API, Web Workers, and libraries like pdf-lib, you can do serious PDF manipulation entirely on the client side — no server required.
This is exactly what the Split PDF tool does. When you upload a PDF:
It's read into memory using the browser's FileReader API as an ArrayBuffer.
pdf-lib parses the document and counts the pages.
When you hit "Split PDF," the library creates new PDF documents, copies the relevant pages over, and generates downloadable byte arrays.
Those byte arrays are handed directly to your browser's download mechanism.
At no point does the file travel over a network. The "server" is your own CPU.
javascriptconst buffer = await readFileAsArrayBuffer(file);
const { PDFDocument } = window.PDFLib;
const sourcePdf = await PDFDocument.load(buffer);
Three lines. That's the entire "upload" step — and it never left your machine.
Two Ways to Split
The tool offers two splitting modes, designed to cover the most common real-world scenarios.
- By Page Ranges This is the power-user mode. You type something like 1-5, 10-15, 20 and the tool produces three separate PDF files — one for each range. It's perfect for:
Breaking a book into chapters
Extracting a specific section of a report to share with stakeholders
Separating a combined invoice document into individual invoices
The range parser handles both ranges (1-5) and single pages (20) in the same input string, separated by commas. Clean and flexible.
javascriptconst parseRanges = (rangeStr) => {
const result = [];
for (const part of rangeStr.split(",").map((s) => s.trim())) {
if (part.includes("-")) {
const [start, end] = part.split("-").map((n) => parseInt(n.trim()));
if (!isNaN(start) && !isNaN(end) && start <= end)
result.push({ start: start - 1, end: end - 1 });
} else {
const num = parseInt(part);
if (!isNaN(num)) result.push({ start: num - 1, end: num - 1 });
}
}
return result;
};
Notice the - 1 offsets — PDF page indices are zero-based internally, but humans count from 1. Small detail, big UX impact.
- Individual Pages One click, and every page becomes its own PDF file. A 20-page document turns into 20 separate downloads. This is ideal for distributing slides, archiving scanned documents page by page, or just giving someone exactly the one page they asked for. To avoid overwhelming the browser's download manager, individual page downloads are staggered with a 100ms delay between each one — a tiny but important UX consideration.
Handling Downloads Across Every Browser
Cross-browser file downloads sound trivial until you try to support Safari on iOS. The tool uses a layered download helper that tries progressively more compatible approaches:
A custom window.download function if available
The legacy msSaveOrOpenBlob for old Edge/IE
A programmatically clicked tag (the standard modern approach)
As a last resort, window.open() with a blob URL, with a prompt to allow pop-ups
iOS Safari gets a special callout UI element that reminds users to check their Files app → Downloads folder, since the native Safari download behavior differs from desktop browsers.
javascriptconst isIOSSafari = () => {
const ua = window.navigator.userAgent;
return (
(!!ua.match(/iPad/i) || !!ua.match(/iPhone/i)) &&
!!ua.match(/WebKit/i) &&
!ua.match(/CriOS/i)
);
};
Small touches like this are what separate a tool people actually use from a tool people abandon in frustration.
Local History Without a Backend
The tool tracks your recent splits using a hybrid storage strategy:
Metadata (filename, tool used, timestamp, size) goes into localStorage — lightweight and fast.
The actual PDF bytes go into IndexedDB — the browser's structured data store, capable of handling large binary blobs.
This means you can revisit recent files without re-uploading anything, and it all works offline. No accounts. No sync. No data leaving your device.
javascriptconst addToHistory = async (pdfData) => {
const history = JSON.parse(localStorage.getItem(HISTORY_KEY) || "[]");
const newEntry = { id: Date.now(), name: pdfData.name, tool: pdfData.tool, ... };
if (pdfData.bytes) {
await dbSet(pdf_${newEntry.id}, pdfData.bytes); // IndexedDB
}
history.unshift(newEntry);
localStorage.setItem(HISTORY_KEY, JSON.stringify(history.slice(0, 50)));
};
The history is capped at 50 entries to keep storage usage reasonable. Pragmatic, not precious.
Quality Is Never Compromised
One concern people often have with PDF tools is quality degradation. This tool sidesteps the issue entirely — because there is no re-rendering happening.
pdf-lib doesn't rasterize your pages into images and repack them. It copies the raw PDF page objects from the source document into the new document. The text stays as text. The vector graphics stay as vectors. The embedded fonts stay embedded. You get a byte-perfect extraction, not a screenshot of a page.
The Bigger Picture
This tool is part of a broader philosophy: your files are yours. The browser has become powerful enough that the reflexive "upload to server → process → download" pipeline is often unnecessary, and increasingly, it's irresponsible.
Client-side PDF processing is just one example. The same principle applies to image compression, document conversion, data parsing, and dozens of other utility tasks that millions of people outsource to servers every day when they don't have to.
As developers, we have a responsibility to ask: does this actually need to leave the user's device? More often than the current ecosystem suggests, the answer is no.
Try It
If you've ever needed to split a PDF — and who hasn't — give it a try. Upload a file, split it, and notice what doesn't happen: no spinner while a server "processes" it, no email confirmation, no account wall, no watermark on the output.
Just your PDF, split the way you want it, in seconds, entirely on your machine.
That's what PDF tools should have been all along.
Built with React, pdf-lib, and a deep distrust of unnecessary server round-trips. All processing happens locally in your browser — always.
Top comments (0)