Reversing a PDF — flipping the page order from last-to-first — sounds like something only desktop software handles. But with pdf-lib and three lines of iteration logic, you can build a fully browser-based reverse tool.
This post walks through the implementation, including index mapping, copyPages, and keeping the original metadata intact.
Why client-side?
Traditional reverse tools upload your file, process it on a server, and send the result back. For documents that might be confidential or contain sensitive information, this introduces an unnecessary privacy risk. A browser-based approach:
- Processes everything locally
- Keeps files on the user's device
- Works offline after loading
- Avoids server-side bandwidth costs
The stack
- Vue 3 + Composition API
- pdf-lib for PDF manipulation and page reversal
-
PDF.js (
pdfjs-dist) for preview rendering - Vite for bundling
Reversing page order
The core operation is deceptively simple: read each page in reverse order and append them to a new document.
<script setup lang="ts">
import { ref } from 'vue'
import { PDFDocument } from 'pdf-lib'
const file = ref<File | null>(null)
const reversing = ref(false)
async function reversePdf(bytes: ArrayBuffer) {
const sourcePdf = await PDFDocument.load(bytes, { updateMetadata: false })
const outputPdf = await PDFDocument.create()
// Build reversed indices: [N-1, N-2, ..., 1, 0]
const pageIndices = Array.from(
{ length: sourcePdf.getPageCount() },
(_, i) => sourcePdf.getPageCount() - 1 - i
)
// Copy pages at those indices into the new document
const copiedPages = await outputPdf.copyPages(sourcePdf, pageIndices)
copiedPages.forEach((page) => outputPdf.addPage(page))
return outputPdf.save({ useObjectStreams: true })
}
</script>
Key implementation details
Copying pages by index
pdf-lib's copyPages() method accepts an array of indices. To reverse, we compute totalPages - 1 - index for every page:
// source has 5 pages
const pageIndices = [4, 3, 2, 1, 0]
// These are copied in that order, so page 4 becomes the first page
// of the output document
Preserving metadata
By default, outputPdf.save() doesn't carry over metadata from the source. To keep the original title, author, and other fields, load the source PDF but copy pages into a new document. The newer version of pdf-lib (1.17+) preserves some metadata when using copyPages, but to be safe:
// Create output doc with source's metadata already embedded
const outputPdf = await PDFDocument.load(bytes, { updateMetadata: false })
// Now move pages around in-place
const pageCount = outputPdf.getPageCount()
const pageIndices = Array.from(
{ length: pageCount },
(_, i) => pageCount - 1 - i
)
const copiedPages = await outputPdf.copyPages(outputPdf, pageIndices)
// Remove all original pages first
for (let i = pageCount - 1; i >= 0; i--) {
outputPdf.removePage(i)
}
// Add them back in reversed order
copiedPages.forEach((page) => outputPdf.addPage(page))
return outputPdf.save({ useObjectStreams: true })
This approach keeps all metadata (title, author, subject, etc.) intact since we never create a fresh document — we just reorder pages in place.
Performance
For large PDFs (500+ pages), creating a new document and copying pages is efficient because pdf-lib uses internal page references rather than re-encoding content streams. Memory usage scales linearly with page count.
Testing shows that a 100-page PDF reverses in under 500ms on a typical laptop.
Preview with PDF.js
Before finalizing the reverse, show users a preview so they can verify:
<script setup lang="ts">
import { ref } from 'vue'
import { pdfToCanvases } from '@/utils/pdfPreview'
const reversedCanvases = ref<HTMLCanvasElement[]>([])
async function handleReverse() {
if (!file.value) return
reversedCanvases.value = await renderReversed(file.value)
}
async function renderReversed(file: File) {
const bytes = await file.arrayBuffer()
const reversedBytes = await reversePdf(bytes)
const blob = new Blob([reversedBytes], { type: 'application/pdf' })
return pdfToCanvases(blob.slice(0, 0), 5) // render first 5 pages as preview
}
</script>
Edge cases
Single-page PDFs
Reversing a 1-page PDF produces an identical file. The tool should still work without errors — pageIndices will be [0], which is valid.
Encrypted PDFs
Some PDFs have owner passwords that prevent structural changes. Using { updateMetadata: false } during load bypasses permission checks for reading, but the save operation may fail if the document has restrictive permissions.
Mixed page sizes
If the source PDF has pages of different sizes (e.g., some Letter, some A4), reversing still works correctly — the page content carries its own size metadata.
Summary
Building a browser-based PDF page reversal tool with pdf-lib involves:
- Load the PDF with
PDFDocument.load() - Compute reversed page indices:
[N-1, N-2, ..., 0] - Copy pages using
copyPages(sourcePdf, pageIndices) - Append them to a new (or in-place modified) document
- Save and download via
Blob+<a>element
Try it at en.sotool.top/reverse-pdf. It takes about 5 seconds and keeps your files completely private.
Top comments (0)