Get started

How to split a PDF into individual pages (or custom ranges)

Split any PDF into individual pages or custom page ranges for free, in your browser, from the command line, or via API. No upload required.

benoitdedJanuary 7, 20266 min read

Sometimes you only need one chapter of a report. Or you need to send the last 3 pages of a contract without the rest. Whatever the reason, splitting a PDF is a routine task, and it should be simple.

Here's how to do it, from the fastest browser method to full programmatic control.

Method 1: Browser tool (no upload, instant)

The most private approach: everything runs in your browser, files never leave your device.

Using PDF4.dev Split PDF:

  1. Go to Split PDF
  2. Drop your PDF onto the upload area
  3. Enter a page range, for example 1-3 to extract pages 1 through 3, or 2,5,7 for specific pages
  4. Click "Split PDF"
  5. Download the result

Splitting every page into a separate file:

Toggle "Split all pages" to extract each page as its own PDF. You'll get a zip archive with one file per page.

Method 2: macOS Preview

Preview can extract pages without any extra software.

  1. Open your PDF in Preview
  2. Show the sidebar: View → Thumbnails
  3. Select the pages you want (hold Cmd for multiple, Shift for a range)
  4. Drag the selected thumbnails to your Desktop or a Finder window, this exports those pages as a new PDF

To delete specific pages instead (the reverse):

  1. Select the pages to remove
  2. Press Delete
  3. Save with File → Export as PDF

Method 3: Command line

Using pdftk (page range)

# Extract pages 3 to 7
pdftk input.pdf cat 3-7 output extracted.pdf
 
# Extract specific pages: 1, 5, 8
pdftk input.pdf cat 1 5 8 output extracted.pdf
 
# Split every page into its own file
pdftk input.pdf burst output page_%02d.pdf

Using qpdf

# Extract pages 3 to 7
qpdf input.pdf --pages . 3-7 -- output.pdf
 
# Every page to a separate file
for i in $(seq 1 $(qpdf --show-npages input.pdf)); do
  qpdf input.pdf --pages . $i -- page_$i.pdf
done

Using Ghostscript

# Extract pages 2 through 5
gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite \
  -dFirstPage=2 -dLastPage=5 \
  -sOutputFile=extracted.pdf input.pdf

Method 4: JavaScript with pdf-lib

For Node.js applications:

import { PDFDocument } from 'pdf-lib';
import fs from 'fs';
 
async function extractPages(inputPath, pages, outputPath) {
  const bytes = fs.readFileSync(inputPath);
  const original = await PDFDocument.load(bytes);
  const extracted = await PDFDocument.create();
 
  // pages is a 0-indexed array, e.g. [0, 2, 4] for pages 1, 3, 5
  const copied = await extracted.copyPages(original, pages);
  copied.forEach(page => extracted.addPage(page));
 
  const output = await extracted.save();
  fs.writeFileSync(outputPath, output);
  console.log(`Extracted ${pages.length} pages to ${outputPath}`);
}
 
// Extract pages 1–3 (0-indexed: 0, 1, 2)
await extractPages('report.pdf', [0, 1, 2], 'intro.pdf');

Splitting every page:

async function splitAllPages(inputPath) {
  const bytes = fs.readFileSync(inputPath);
  const original = await PDFDocument.load(bytes);
  const count = original.getPageCount();
 
  for (let i = 0; i < count; i++) {
    const single = await PDFDocument.create();
    const [page] = await single.copyPages(original, [i]);
    single.addPage(page);
    const output = await single.save();
    fs.writeFileSync(`page_${i + 1}.pdf`, output);
  }
 
  console.log(`Split into ${count} files`);
}

Method 5: Python with pypdf

from pypdf import PdfWriter, PdfReader
 
def extract_pages(input_path, page_range, output_path):
    reader = PdfReader(input_path)
    writer = PdfWriter()
 
    for page_num in page_range:
        writer.add_page(reader.pages[page_num])
 
    with open(output_path, "wb") as f:
        writer.write(f)
 
# Extract pages 1-3 (0-indexed)
extract_pages("report.pdf", range(0, 3), "intro.pdf")
 
# Split every page
def split_all_pages(input_path):
    reader = PdfReader(input_path)
    for i, page in enumerate(reader.pages):
        writer = PdfWriter()
        writer.add_page(page)
        with open(f"page_{i+1}.pdf", "wb") as f:
            writer.write(f)

Comparing Methods

MethodSetupBatchPrivacySpeed
Browser toolNoneManual100% localInstant
macOS PreviewNoneManualLocalFast
pdftk / qpdfInstallScriptableLocalFast
pdf-lib (Node.js)npm install pdf-libYesLocalFast
pypdf (Python)pip install pypdfYesLocalFast

Common use cases

Extracting an invoice from a statement

Bank statements often come as multi-page PDFs. Extract the single page you need to attach to an expense report:

pdftk statement.pdf cat 3 output invoice_march.pdf

Splitting a book into chapters

If you know the page ranges for each chapter, script it:

pdftk book.pdf cat 1-12 output ch1.pdf
pdftk book.pdf cat 13-28 output ch2.pdf
pdftk book.pdf cat 29-45 output ch3.pdf

Removing a cover page before sharing

Sometimes you want to strip the first page (a confidential cover sheet, or a page with personal info):

# Remove first page: start from page 2
pdftk document.pdf cat 2-end output without-cover.pdf

Splitting in a programmatic workflow

The methods above all operate on existing PDFs. If you're building an application that generates PDFs, there's often a smarter approach: instead of generating a large document and splitting it, generate targeted PDFs from the start.

Say you're generating monthly statements: 12 pages in one PDF, and your customers only need their own page. Instead of splitting a merged document, generate each statement individually:

async function generateStatement(customerId, month, data) {
  const response = await fetch('https://pdf4.dev/api/v1/render', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.PDF4_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      template_id: 'monthly-statement',
      data: { ...data, customer_id: customerId, month },
    }),
  });
  return Buffer.from(await response.arrayBuffer());
}
 
// Generate 100 individual statements without any splitting step
for (const customer of customers) {
  const pdf = await generateStatement(customer.id, 'March 2026', customer.data);
  await saveToStorage(pdf, `statement-${customer.id}-march.pdf`);
}

No merging, no splitting, no intermediate files. Each PDF is generated with exactly the content it needs. This is the approach that scales.

PDF4.dev has a free tier. Create a template and start generating targeted PDFs without post-processing.

FAQ

Will splitting reduce quality?

No. Pages are copied as-is using pdf-lib's copyPages() method, with no re-encoding or re-compression. All embedded fonts, images, and annotations are preserved at original quality. The output structure differs slightly (new cross-reference table, new file header) but the page content is functionally identical to the original.

Can I split password-protected PDFs?

You need to unlock the PDF first. Once unlocked, you can split normally.

What's the difference between "split" and "extract"?

They're the same operation. "Split" often implies separating into multiple files (e.g. one file per page), while "extract" implies pulling a specific range into a new file. Most tools support both.

Internal links that point to pages no longer included in the extracted range will break. Bookmarks may also be lost depending on the tool. If you need to preserve these, use a dedicated tool like pdftk's burst mode followed by manual bookmark management.

Can I split and then re-merge in a different order?

Yes, this is the standard workflow for reordering pages. Split → reorder externally → merge. Or use a reorder tool that handles it in one step.

Free tools mentioned:

Split PdfTry it free

Start generating PDFs

Build PDF templates with a visual editor. Render them via API from any language in ~300ms.