How it works
Every tool on this site processes your PDFs entirely inside your browser, using open-source JavaScript libraries. This page gives a transparent, step-by-step breakdown of exactly what happens to your file for each operation — so you never have to take our word for it.
No network calls
Your file bytes never touch a network socket. The only requests this site makes are for its own HTML, CSS, and JS assets.
Open source libraries
pdf-lib and pdf.js are audited, widely-deployed open-source libraries — not proprietary black boxes.
Runs in your browser
Processing uses the same JavaScript engine that powers the rest of the page. Close the tab and everything is gone.
Merge PDF
Open toolLibrary: pdf-lib
- 1Each selected file is read into an ArrayBuffer via the browser's FileReader API — entirely in memory, never on disk or network.
- 2pdf-lib's PDFDocument.load() parses each PDF's internal object tree.
- 3Pages are copied from each source document into a new empty PDFDocument using copyPages().
- 4The merged document is serialised to a Uint8Array via doc.save() and offered as a download using a temporary object URL.
Split PDF
Open toolLibrary: pdf-lib + JSZip
- 1The PDF is loaded into memory and parsed by pdf-lib.
- 2For a page range or specific pages, only the selected zero-indexed pages are copied into a new PDFDocument.
- 3When splitting every page, each page becomes its own document. All outputs are then bundled into a ZIP in memory using JSZip and offered as a single download.
- 4Nothing is written to a server, temp directory, or any storage mechanism.
Reorder Pages
Open toolLibrary: pdf-lib
- 1pdf-lib reads the PDF and exposes its page list.
- 2You drag page cards to produce a new ordering (an array of original page indices).
- 3copyPages() copies all pages in the new order into a fresh document.
- 4The reordered document is saved and offered for download.
Delete Pages
Open toolLibrary: pdf-lib
- 1The PDF is parsed and the full page index list retrieved.
- 2Your selected page numbers are parsed and validated against the actual page count.
- 3A new document is created containing only the pages not in the delete set.
- 4The result is serialised and downloaded.
Rotate Pages
Open toolLibrary: pdf-lib
- 1pdf-lib reads each page's current rotation angle from its page dictionary.
- 2The new rotation is set as (current + selected degrees) mod 360 using the PDF page's /Rotate key.
- 3If 'selected pages' mode is active, only those pages have their rotation updated.
- 4The modified document is saved and offered for download.
Fill PDF Form
Open toolLibrary: pdf-lib
- 1pdf-lib reads the document's AcroForm dictionary, which contains references to all interactive fields.
- 2Field names, types (text, checkbox, dropdown, radio), and current values are extracted and displayed in the UI.
- 3When you submit, pdf-lib writes your typed values back into the corresponding field objects.
- 4If 'flatten' is checked, form.flatten() is also called before saving.
Flatten Forms
Open toolLibrary: pdf-lib
- 1pdf-lib loads the form and calls form.flatten(), which renders each field's current visual appearance as a static content stream.
- 2The field widget annotations are removed from the page.
- 3The AcroForm dictionary is cleared from the document.
- 4The result is a standard PDF with no interactive elements.
Watermark PDF
Open toolLibrary: pdf-lib
- 1For text watermarks, pdf-lib embeds Helvetica Bold and draws the text onto each page's content stream at the specified coordinates.
- 2For image watermarks, the image is embedded once via embedPng() or embedJpg(), then stamped onto each page.
- 3Position, opacity, rotation, and size are calculated relative to each page's dimensions so the watermark scales correctly.
- 4All pages are processed in sequence and the resulting document is saved.
Page Numbers
Open toolLibrary: pdf-lib
- 1pdf-lib embeds Helvetica to draw text on each page.
- 2For each page, the label text is computed by substituting {n} and {total} in your format string.
- 3The text width is measured using the font's metrics to align it correctly at the chosen position.
- 4The label is drawn at the correct margin, then the document is saved.
Compress PDF
Open toolLibrary: pdf-lib
- 1The document is loaded and re-serialised with useObjectStreams: true, which compresses the cross-reference table using DEFLATE.
- 2Unused objects and redundant entries are dropped during the save pass.
- 3The resulting byte count is compared to the original to show the savings.
PDF to Images
Open toolLibrary: pdf.js (Mozilla)
- 1pdf.js loads the PDF using its own parser (identical to what Firefox uses to display PDFs).
- 2For each page, a viewport is calculated at your chosen scale (1x to 3x).
- 3The page is rendered onto an off-screen HTML5 Canvas element.
- 4The canvas is exported to your chosen format (PNG, JPEG, WebP) using canvas.toDataURL().
- 5All pages are collected and either downloaded individually or zipped together with JSZip.
Images to PDF
Open toolLibrary: pdf-lib
- 1Each image file is read into an ArrayBuffer via FileReader.
- 2PNG images are embedded with embedPng(); JPEGs with embedJpg().
- 3Other formats (WebP, BMP, GIF) are first drawn onto a canvas and re-exported as JPEG at 92% quality before embedding.
- 4A new PDF page sized to each image's native pixel dimensions is created, and the image is drawn to fill it.
- 5The completed document is serialised and downloaded.
Create PDF
Open toolLibrary: pdf-lib
- 1A new PDFDocument is created from scratch with no pages.
- 2Helvetica and Helvetica-Bold are embedded from pdf-lib's built-in standard font set.
- 3Text, lines, and layout elements are drawn using pdf-lib's coordinate-based drawing API.
- 4The document is serialised and downloaded.
View PDF
Open toolLibrary: pdf.js (Mozilla)
- 1pdf.js parses the PDF's page tree and renders each page on demand.
- 2At your chosen zoom level, a viewport is computed and the page is rendered onto a canvas.
- 3Navigation updates only re-render the requested page — not the whole document.
Extract Text
Open toolLibrary: pdf.js (Mozilla)
- 1pdf.js loads the PDF and accesses its text content layer.
- 2For each page, getTextContent() returns an array of text items, each with a string and position.
- 3The strings are joined with spaces and collected per-page into the text area.
- 4You can copy the text or download it as a .txt file — both operations happen entirely in the browser.