Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchespdf-lib uses a simple three-stage lifecycle: create or load a PDFDocument, change it with page, drawing, image, font, or form APIs, then call save() to obtain PDF bytes. In Node.js those bytes can be written to a file; in a browser they can be downloaded or displayed.
The project describes pdf-lib as usable in browsers, Node, Deno, and React Native. Confirm the API and runtime support for the package version you install, because surfaced documentation and package listings can lag current releases.
Install pdf-lib
Install the package in a Node project with npm or Yarn:
npm install --save pdf-lib
# or
yarn add pdf-lib
The package can also be loaded from a UMD build through a CDN. For production, use a specific version in the script URL rather than an unpinned “latest” address.
#1 Best Overall
- Scanner type: Document
- Connectivity technology: USB
- With Auto Scan Mode, the scanner automatically detects what you're scanning
- Digitize documents and images
Create a new PDF in Node.js
This complete example creates one page, draws text, serializes the document, and writes the resulting bytes to hello.pdf. PDFDocument.create() returns a promise, and save() returns a Uint8Array.
const { PDFDocument, StandardFonts, rgb } = require('pdf-lib');
const fs = require('node:fs/promises');
async function main() {
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage([612, 792]); // US Letter points
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
page.drawText('Hello from pdf-lib', {
x: 72,
y: 700,
size: 24,
font,
color: rgb(0.1, 0.2, 0.7),
});
const pdfBytes = await pdfDoc.save();
await fs.writeFile('hello.pdf', pdfBytes);
}
main().catch(console.error);
PDF coordinates start at the lower-left corner. A page size is expressed in points (72 points per inch), so the array above is 8.5 by 11 inches.
Use ES modules instead
import { PDFDocument, StandardFonts } from 'pdf-lib';
import { writeFile } from 'node:fs/promises';
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage();
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
page.drawText('Generated with ES modules', { x: 50, y: 750, font });
await writeFile('output.pdf', await pdfDoc.save());
Create a PDF in a browser
In a browser build, the bytes returned by save() can be placed in a Blob and downloaded. This example assumes pdf-lib is imported by your bundler.
import { PDFDocument, StandardFonts } from 'pdf-lib';
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage([595, 842]);
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
page.drawText('Browser PDF', { x: 50, y: 780, size: 20, font });
const bytes = await pdfDoc.save();
const blob = new Blob([bytes], { type: 'application/pdf' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'browser-pdf.pdf';
link.click();
URL.revokeObjectURL(link.href);
Load and edit an existing PDF
Editing starts with bytes, not a filename. Read a file, fetch an ArrayBuffer, or obtain bytes from another source, then pass them to PDFDocument.load(). The example below adds a notice to the first page and saves a new file.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11const { PDFDocument, StandardFonts, rgb } = require('pdf-lib');
const fs = require('node:fs/promises');
async function addNotice() {
const existingPdfBytes = await fs.readFile('input.pdf');
const pdfDoc = await PDFDocument.load(existingPdfBytes);
const pages = pdfDoc.getPages();
if (pages.length === 0) throw new Error('The PDF has no pages');
const firstPage = pages[0];
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
firstPage.drawText('Reviewed', {
x: 50,
y: 50,
size: 12,
font,
color: rgb(0.8, 0, 0),
});
const updatedBytes = await pdfDoc.save();
await fs.writeFile('reviewed.pdf', updatedBytes);
}
addNotice().catch(console.error);
This is a drawing operation layered onto a page. It is not unrestricted in-place editing of every existing text run, font, or layout object. Design the change around the operations pdf-lib documents and validate the output with representative PDFs.
Rank #2
- FAST SPEEDS - Scans color and black and white documents a blazing speed up to 16ppm (1). Color scanning won’t slow you down as the color scan speed is the same as the black and white scan speed.
- ULTRA COMPACT – At less than 1 foot in length and only about 1. 5lbs in weight you can fit this device virtually anywhere (a bag, a purse, even a pocket).
- READY WHENEVER YOU ARE – The DS-640 mobile scanner is powered via an included micro USB 3. 0 cable allowing you to use it even where there is no outlet available. Plug it into you PC or laptop and you are ready to scan.
- WORKS YOUR WAY – Use the Brother free iPrint&Scan desktop app for scanning to multiple “Scan-to” destinations like PC, Network, cloud services, Email and OCR. (2) Supports Windows, Mac and Linux and TWAIN/WIA for PC/ICA for Mac/SANE drivers. (3)
- OPTIMIZE IMAGES AND TEXT – Automatic color detection/adjustment, image rotation (PC only), bleed through prevention/background removal, text enhancement, color drop to enhance scans. Software suite includes document management and OCR software. (4)
Page operations: add, insert, remove, split, and merge
Add, insert, and remove pages
const pdfDoc = await PDFDocument.create();
const first = pdfDoc.addPage([612, 792]);
const inserted = pdfDoc.insertPage(0, [612, 792]);
pdfDoc.removePage(1);
addPage() appends a page. insertPage(index, size) inserts at a zero-based index, and removePage(index) removes one.
Copy pages between documents
const source = await PDFDocument.load(await fs.readFile('source.pdf'));
const target = await PDFDocument.load(await fs.readFile('target.pdf'));
const copiedPages = await target.copyPages(source, [0, 2]);
for (const page of copiedPages) target.addPage(page);
await fs.writeFile('merged.pdf', await target.save());
Copying selected pages is the basis for merging documents. To split a PDF, create a new document, copy the desired source pages into it, and save that new document. Preserve page order explicitly when building the index list.
Draw text, images, and vector graphics
Pages expose drawing methods for text, PNG and JPEG images, lines, rectangles, and other vector graphics. SVG paths are also listed among the project features. Embed an image once and draw it wherever needed.
Free tools Windows power users keep installed
One-click scans. No signup required.
const imageBytes = await fs.readFile('logo.png');
const image = await pdfDoc.embedPng(imageBytes);
const page = pdfDoc.getPages()[0];
page.drawImage(image, { x: 50, y: 600, width: 180, height: 60 });
page.drawRectangle({ x: 45, y: 595, width: 190, height: 70, borderWidth: 1 });
For a JPEG, use embedJpg(). Image dimensions are in PDF points; calculate the height yourself when preserving an image’s aspect ratio.
Fill, read, and flatten interactive forms
Use getForm() to access AcroForm fields. Documented field classes include text fields, checkboxes, radio groups, dropdowns, option lists, and buttons.
Rank #3
- Up to 255 customize favorite scan file setting with "Single Touch" , Support Windows 7/8/10
- Turn paper documents into searchable, editable files - save scans as searchable PDF files; OCR function included
- Info Barcode function - automatic categorization of complicate documentation and data with 1D or 2D Barcode page.
- Intelligent color and image adjustments — Auto Rotate, Crop, Deskew and blank page remove with Plustek Image Processing Technology
- Easy send scanned files to FTP server or personal NAS (FTP) with PDFs , Jpeg , TIFF or Png format. User can download scanner driver from Plustek website
const pdfDoc = await PDFDocument.load(await fs.readFile('form.pdf'));
const form = pdfDoc.getForm();
const name = form.getTextField('full_name');
name.setText('Ada Lovelace');
const country = form.getDropdown('country');
country.select('United Kingdom');
const terms = form.getCheckBox('terms');
terms.check();
// Make values non-editable in viewers, if that is your intended output.
form.flatten();
await fs.writeFile('completed-form.pdf', await pdfDoc.save());
Field names must match the names embedded in the source form. To inspect available fields, iterate over form.getFields() and read each field’s name. Flatten only after all values and appearance updates are complete; flattening removes the interactive editing step from the resulting form.
Form appearance and non-Latin text
The package README states that the default form appearance font is standard Helvetica and supports characters in the Latin alphabet. If a form value uses Arabic or another non-Latin script, embed a suitable custom font and update the field appearances with that font. This caveat concerns form appearances specifically; it should not be generalized to every text-drawing workflow.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Embed a custom font
Standard fonts such as Helvetica are available without another dependency. Custom font embedding requires the separate @pdf-lib/fontkit package.
npm install --save @pdf-lib/fontkit
const { PDFDocument } = require('pdf-lib');
const fontkit = require('@pdf-lib/fontkit');
const fs = require('node:fs/promises');
const pdfDoc = await PDFDocument.create();
pdfDoc.registerFontkit(fontkit);
const fontBytes = await fs.readFile('MyFont.ttf');
const font = await pdfDoc.embedFont(fontBytes);
const page = pdfDoc.addPage();
page.drawText('Custom-font text', { x: 50, y: 750, font, size: 18 });
await fs.writeFile('custom-font.pdf', await pdfDoc.save());
Choose a font that contains every glyph you need and test shaping, line breaks, and right-to-left output with your actual text. A font file being embedded does not by itself guarantee correct layout for every writing system.
Choose the right implementation path
| Requirement | Typical path | Important check |
|---|---|---|
| New document | PDFDocument.create(), add pages, draw, save |
Set page dimensions and coordinate positions |
| Existing document | PDFDocument.load(bytes), modify, save |
Validate the source PDF and preserve required content |
| Page rearrangement | getPages(), insertPage(), removePage(), copyPages() |
Use zero-based indexes and preserve intended order |
| Interactive form | getForm() and field-specific getters |
Use exact field names; choose whether to flatten |
| Non-Latin form values | Register fontkit, embed a custom font, update appearances | Test glyph coverage and viewer rendering |
| Browser output | Turn saved bytes into a Blob or data URL | Revoke object URLs after use |
Troubleshooting
“Cannot find module” or import errors
Install pdf-lib in the project that runs the code, and use the import style required by that project’s module configuration. For custom fonts, install @pdf-lib/fontkit separately and call registerFontkit() before embedding.
Rank #4
- Note: No software installation is required. You need 2 AA batteries ( not included) and a memory card ( included) to use it directly. Scan mode: Press and hold "Scan" for 2 seconds to turn on the device, and then press "Scan", the green light is on. The scanner moves to scan the file until the green light turns off automatically (or press the "Scan" key and the green light goes out). The number shown on the display increases by 1 to indicate that the scan is complete.
- Portable Scanner scans images or pictures quickly: Store JPEG/PDF files within seconds, scan images or pictures quickly, plug and play, no need any software preinstalled. Compatible with Windows XP/7/Vista/Mac OS 10.4 or above version.
- Lightweight and travel-friendly: Stored in Micro SD card directly, support read data on your computer or phone with USB connected. Powered by 2pcs AA batteries, Compact Design, it is convenient to carry outside.
- 3 Image Resolution: 3 modes of resolution for your options: 300dpi/600dpi/900dpi, you can save it at the clearest way, picture and document are showed clear as it is. Freely choose your favorite resolution.File Format: JPEG/PDF format is all available, Great storage capacity as it supports 32G Micro SD card(Included 16GB Card),total meet your need for business trip or daily use.
- Widely Used: It is applicable in bank, insurance business, real estate agency,home, office, library or outdoors. suitable for lawyer, businessmen, students, travelers and amateur archivists. Scan your important files and save them immediately, no struggling in finding a printing shop, keep it confidential.
The output is blank or text is off the page
Check the coordinate system: the origin is at the lower-left. Confirm the page dimensions, increase the y-coordinate from the bottom rather than from the top, and ensure the selected font is passed to drawText().
A field cannot be found
The string supplied to getTextField(), getDropdown(), or another getter must exactly match the PDF field name. Enumerate form.getFields() and log each name before writing values.
Characters show as boxes or disappear
Use a custom font containing the required glyphs. For form fields, update appearances with that font because the documented default Helvetica appearance is Latin-only.
The PDF fails after loading
Make sure the input is actually PDF bytes, not an HTML error page or a truncated download. Test a representative sample of source files; requirements involving scanned-document OCR, complex layout preservation, encryption, signatures, accessibility, or archival conformance need separate validation against the current API and your target viewers.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Performance, reliability, and validation
- Keep input and output as bytes until you need a file or browser Blob; unnecessary base64 conversions increase memory use.
- Embed a font or image once and reuse the returned object instead of embedding the same asset for every page.
- For large documents, measure memory in the runtime and process work in sensible batches where your application permits it.
- Save to a new file during development so an unsuccessful edit does not overwrite the source.
- Open generated PDFs in the viewers your users rely on, and test forms before and after flattening.
Documentation describes the supported environments and features, but it does not establish compatibility with every runtime release, bundler, mobile configuration, or unusual PDF producer. Pin and review the package version used by your application.
Best Value
- PORTABLE SCANNER FOR USE ON-THE-GO — The fastest and lightest mobile single-sheet-fed compact document scanner in its class¹
- QUICK DOCUMENT SCANNING ― This Epson ultra-fast scanner scans a single page as quickly as 5.5 seconds²; Windows and Mac compatible
- VERSATILE PAPER HANDLING ― Portable scanner scans documents up to 8.5 x 72 in; Also easily digitizes receipts and ID cards to make accounting, bookkeeping, and organizing simpler
- INTUITIVE, HIGH-SPEED SOFTWARE — Epson ScanSmart Software³ is a smart tool allowing you to easily scan, review, and save; Stay organized easily with the help of this Epson scanner
- EASY SETUP — USB-powered connect to your computer for quick and simple scanning; No batteries or external power supply required to operate portable document scanner; Standard Connectivity: USB 2.0
Or skip the browser setup
If your actual goal is to obtain a clean screenshot of a web page rather than generate a PDF document in JavaScript, ScreenshotNeo provides a one-request website screenshot API. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
See the parameter reference in the ScreenshotNeo documentation. cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
There is a free allowance of 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots, and every feature is included on every plan. Create a free ScreenshotNeo account.
FAQ
Does pdf-lib edit a PDF’s existing paragraphs like a word processor?
Its documented model focuses on drawing, page operations, forms, images, and related document features. Treat edits to existing layout objects as a specific API task, not as unrestricted word-processor-style editing.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Can I use pdf-lib without Node.js?
Yes. The project states support for browsers, Deno, and React Native as well as Node.js; verify your bundler and installed version.
When should I flatten a form?
Flatten after setting and appearance-updating all fields when the final PDF should display values without allowing viewers to edit them.
Frequently Asked Questions
Can pdf-lib create a PDF entirely in memory?
Yes. Create or load the document, make changes, and keep the Uint8Array returned by save() in memory until you send it, download it, or write it to storage.
Do I need fontkit for Helvetica or other standard fonts?
No. The built-in standard fonts do not require fontkit. Install and register @pdf-lib/fontkit when embedding a custom font.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

