pdf-lib Merge and Reorder PDFs in the Browser — Free JavaScript Snippet

pdf-lib Merge and Reorder PDFs in the Browser · Tools · Plain HTML, CSS & JS · Live preview

What's included

Features

100% client-side
Files never leave the browser.
Drag and drop
Plus a standard multi-file picker.
Up-front validation
Invalid files reported with the reason.
Reorder and remove
Keyboard-accessible buttons.
copyPages merging
Fonts and images carried across files.
Page thumbnails
PDF.js renders the merged result.
Generated samples
Works with no files or network.
Metadata
Title and producer set on the output.

About this UI Snippet

Merge PDFs Client-Side With pdf-lib — Private, Fast, No Server

Screenshot of the pdf-lib Merge and Reorder PDFs in the Browser snippet rendered live

"Merge these PDFs" is one of the most common document tasks, and most online tools do it by uploading your files to a server. With pdf-lib the whole job can run in the browser: files are read locally, merged in memory, and downloaded without leaving the device. That matters for contracts, medical documents or anything else private.

Reading files

Files come from a file input or drag and drop. file.arrayBuffer() gives the raw bytes, which are loaded with PDFDocument.load. Loading up front validates the file — a corrupt or non-PDF file is reported instead of failing at merge time — and gives the page count for the list.

The merge is copyPages

A new empty document is created with PDFDocument.create(). For each source file, in the chosen order, out.copyPages(src, src.getPageIndices()) copies every page, then each is added with addPage. copyPages doesn't just copy drawing instructions: it brings along every resource a page references — fonts, images, colour spaces — which is what makes merging unrelated files work. Metadata such as the title is set on the output before save() returns the bytes.

Seeing the result

After merging, PDF.js renders a thumbnail of every page, so you can check the order before downloading. Because PDF.js detaches the buffer it's given, it receives a copy; the original bytes stay available for the download.

Sample files without network

"Add 3 sample PDFs" generates three small documents with pdf-lib itself — coloured headers and page numbers — so the demo is fully usable without your own files.

Limits

Everything is held in memory, which is fine for typical documents but not for gigabyte archives. Encrypted PDFs can't be loaded without their password. Links and form fields within pages are copied, but a document-level outline (bookmarks) isn't merged.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet into an AI assistant like Claude and ask it to explain why copyPages is needed instead of adding pages directly. Ask it to add per-file page ranges, drag-to-reorder with SortableJS, rotating individual pages, or merging the bookmarks outline. It can also help you process very large files by streaming them one at a time to keep memory low.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a browser-only PDF merge tool with pdf-lib and a PDF.js 3 preview (both from a CDN) in plain HTML, CSS and JavaScript.

Requirements:
- Add PDFs with a multi-file input or a drag-and-drop zone; read each with file.arrayBuffer(), validate it by loading it with pdf-lib, and show its name, page count and size, or an error message if it can't be read.
- A button that generates three sample PDFs with pdf-lib (coloured header, title, "Page X of N", placeholder lines) so the tool works with no files.
- A numbered list with move up, move down and remove buttons.
- Merge: create a new document and copy all pages from each file in list order with copyPages, set the title and producer, and save.
- Render every page of the merged document as a thumbnail with PDF.js (passing a copy of the bytes), and enable a download button that saves merged.pdf via a Blob URL, noting that sandboxed previews may block downloads.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

<div class="pm">
  <header class="pm-head">
    <div>
      <h2>Merge PDFs</h2>
      <p>Files never leave your browser. Add PDFs, put them in order, merge.</p>
    </div>
    <div class="pm-add">
      <label class="pm-file">Add PDFs<input type="file" id="pmFiles" accept="application/pdf" multiple></label>
      <button type="button" id="pmSamples" class="ghost">Add 3 sample PDFs</button>
    </div>
  </header>
  <div class="pm-drop" id="pmDrop">Drop PDF files here</div>
  <ol class="pm-list" id="pmList" aria-label="Files to merge"></ol>
  <div class="pm-bar">
    <button type="button" id="pmMerge" disabled>Merge</button>
    <button type="button" id="pmDownload" class="ghost" disabled>Download merged PDF</button>
    <span id="pmStatus" role="status"></span>
  </div>
  <div class="pm-pages" id="pmPages" aria-label="Pages of the merged PDF"></div>
</div>

Step by step

How to Use

  1. 1
    Add filesPick or drop PDFs, or press "Add 3 sample PDFs".
  2. 2
    Order themUse the arrow buttons; remove files with ✕.
  3. 3
    MergePages are copied into one new document in list order.
  4. 4
    Check the pagesThumbnails of every merged page appear below.
  5. 5
    DownloadSaves merged.pdf (open the demo in its own tab if the sandbox blocks it).

Real-world uses

Common Use Cases

Job applications
Cover letter, CV and portfolio in one file.
Contracts and HR
Combine signed pages privately.
Education
Merge lecture notes or submissions.
Internal tools
Batch documents without a backend.
Privacy-first apps
No uploads to third-party services.
Related: pdf-lib Watermark and Page Numbers
Stamp the merged file: pdf-lib Watermark and Page Numbers.
Related: File Dropzone
A styled drop target: File Dropzone Uploader.

Got questions?

Frequently Asked Questions

Create an empty document with PDFDocument.create(). For each source, load it with PDFDocument.load(bytes), copy its pages with out.copyPages(src, src.getPageIndices()), and add each copied page with out.addPage(page). Finally call out.save() to get the merged bytes.

No. Files are read with the File API and processed in memory by pdf-lib in the browser. Nothing is sent to a server.

Yes. Pass an array of page indexes to copyPages instead of getPageIndices(), for example [0, 2, 3] to copy the first, third and fourth pages.

A page belongs to its document and references objects such as fonts and images stored there. copyPages creates copies of the page and all its referenced objects in the target document.

pdf-lib cannot decrypt password-protected files. It will throw when loading them unless you pass ignoreEncryption, which only works for files that are encrypted but openable without a password, and the output may not be usable.