{"id":11534,"library":"pdf-lib","title":"pdf-lib","description":"`pdf-lib` is a robust and actively maintained JavaScript library designed for creating and modifying PDF documents in any modern JavaScript environment, including Node.js, browsers, Deno, and React Native. Currently at version 1.17.1, it receives frequent minor and patch releases, with major versions introducing significant architectural changes. A key differentiator of `pdf-lib` from many other open-source PDF libraries is its comprehensive support for *modifying* existing PDF documents, not just creating new ones. Its features include drawing text, images, and vector graphics, embedding fonts (with UTF-8 and UTF-16 support), managing pages (add, insert, remove, copy), creating and filling forms, and setting/reading document metadata and viewer preferences. The library is written in TypeScript, providing excellent type support for its users.","status":"active","version":"1.17.1","language":"javascript","source_language":"en","source_url":"https://github.com/Hopding/pdf-lib","tags":["javascript","pdf-lib","pdf","document","create","modify","creation","modification","edit","typescript"],"install":[{"cmd":"npm install pdf-lib","lang":"bash","label":"npm"},{"cmd":"yarn add pdf-lib","lang":"bash","label":"yarn"},{"cmd":"pnpm add pdf-lib","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for embedding custom fonts. It is an optional dependency to keep the main bundle size smaller.","package":"@pdf-lib/fontkit","optional":true}],"imports":[{"note":"The primary class for creating and modifying PDFs. Asynchronous methods like `create()` and `load()` require `await` since v1.0.0.","wrong":"const PDFDocument = require('pdf-lib').PDFDocument","symbol":"PDFDocument","correct":"import { PDFDocument } from 'pdf-lib'"},{"note":"A utility function for defining RGB colors, commonly used for drawing operations.","wrong":"import rgb from 'pdf-lib/lib/api/colors/rgb'","symbol":"rgb","correct":"import { rgb } from 'pdf-lib'"},{"note":"An enum providing access to the 14 standard PDF fonts (e.g., `TimesRoman`, `Helvetica`).","wrong":"import { HELVETICA } from 'pdf-lib/lib/api/fonts/StandardFonts'","symbol":"StandardFonts","correct":"import { StandardFonts } from 'pdf-lib'"},{"note":"Needed for looking up dictionary entries with string keys, especially after v1.0.0's changes to `get()` methods.","wrong":"import { PDFName } from 'pdf-lib/es/core/objects/PDFName'","symbol":"PDFName","correct":"import { PDFName } from 'pdf-lib'"}],"quickstart":{"code":"import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';\n\nasync function createPdf() {\n  // Create a new PDFDocument\n  const pdfDoc = await PDFDocument.create();\n\n  // Embed the Times Roman font\n  const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman);\n\n  // Add a blank page to the document\n  const page = pdfDoc.addPage();\n\n  // Get the width and height of the page\n  const { width, height } = page.getSize();\n\n  // Draw a string of text toward the top of the page\n  const fontSize = 30;\n  page.drawText('Creating PDFs with pdf-lib is awesome!', {\n    x: 50,\n    y: height - 4 * fontSize,\n    size: fontSize,\n    font: timesRomanFont,\n    color: rgb(0, 0.53, 0.71),\n  });\n\n  // Serialize the PDFDocument to bytes (a Uint8Array)\n  const pdfBytes = await pdfDoc.save();\n\n  // In a Node.js environment, you could write this to a file:\n  // import { writeFileSync } from 'node:fs';\n  // writeFileSync('example.pdf', pdfBytes);\n\n  // In a browser, you might open it in a new tab:\n  // const blob = new Blob([pdfBytes], { type: 'application/pdf' });\n  // const url = URL.createObjectURL(blob);\n  // window.open(url, '_blank');\n\n  console.log('PDF created successfully (or bytes generated).');\n  return pdfBytes;\n}\n\ncreatePdf().catch(console.error);","lang":"typescript","description":"This example demonstrates creating a new PDF document, embedding a standard font, adding a page, drawing text, and serializing the document to bytes."},"warnings":[{"fix":"Ensure all calls to `create()`, `load()`, and `save()` are `await`ed. Update `PDFDocumentFactory` references to `PDFDocument`. Refactor drawing logic to use direct `page.draw...` methods. Replace `getMaybe` with `get` and use `PDFName.of()` for string keys.","message":"Version 1.0.0 introduced significant breaking changes. Key API methods such as `PDFDocument.create()`, `PDFDocument.load()`, and `pdfDoc.save()` became asynchronous and now return Promises. Additionally, `PDFDocumentFactory` was renamed to `PDFDocument`, and the page drawing API was simplified from content streams to direct methods (e.g., `page.drawText`). The `getMaybe` method was removed, and string-based dictionary lookups with `get` now require wrapping strings in `PDFName.of()`.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Install `@pdf-lib/fontkit` via npm (`npm install @pdf-lib/fontkit`) and register it before attempting to embed custom fonts: `import fontkit from '@pdf-lib/fontkit'; pdfDoc.registerFontkit(fontkit);`.","message":"Embedding custom fonts requires the separate `@pdf-lib/fontkit` package to be installed and registered with `pdfDoc.registerFontkit(fontkit)`.","severity":"gotcha","affected_versions":">=0.x"},{"fix":"If custom fonts are not needed, avoid installing `@pdf-lib/fontkit`. For browser environments, consider using CDN builds that don't include `fontkit` if feasible, or optimize your build process. Recent versions (post v0.5.1) have seen bundle size reductions.","message":"The `pdf-lib` bundle size, especially when including `@pdf-lib/fontkit` for custom font support, can be large. This is a consideration for browser-based applications where bundle size impacts load times.","severity":"gotcha","affected_versions":">=0.x"},{"fix":"Avoid using `pdf-lib` with encrypted documents. If encryption is a requirement, preprocess the PDF to remove encryption before using `pdf-lib` or consider alternative solutions designed for encrypted PDF handling.","message":"`pdf-lib` does not officially support modifying encrypted PDF documents. Attempting to load and save encrypted PDFs may result in unexpected behavior, errors, or corrupted output.","severity":"gotcha","affected_versions":">=0.x"},{"fix":"Update method calls from `embedJPG` to `embedJpg` and `embedPNG` to `embedPng`.","message":"Image embedding methods `pdfDoc.embedJPG()` and `pdfDoc.embedPNG()` were renamed to `pdfDoc.embedJpg()` and `pdfDoc.embedPng()` respectively (lowercase 'g' and 'n') for consistency.","severity":"breaking","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure `PDFDocument.create()` and `PDFDocument.load()` are awaited, as they return Promises since v1.0.0: `const pdfDoc = await PDFDocument.create();`","cause":"Attempting to use methods on the `pdfDoc` object immediately after `PDFDocument.create()` or `PDFDocument.load()` without awaiting the Promise.","error":"TypeError: Cannot read properties of undefined (reading 'addPage')"},{"fix":"Validate the original PDF with external tools (e.g., qpdf) if possible. Try simplifying the operations performed on the PDF. If re-saving an existing PDF, try `pdfDoc.save({ useObjectStreams: false })` as a workaround for some legacy viewer issues. Ensure embedded fonts are correctly registered and compatible.","cause":"Issues when processing complex or malformed PDFs, or specific font embedding problems leading to an invalid PDF structure after saving.","error":"The font '...' contains a bad /BBox. (Adobe Reader error)"},{"fix":"Rename `pdfDoc.embedJPG()` to `pdfDoc.embedJpg()` and `pdfDoc.embedPNG()` to `pdfDoc.embedPng()`.","cause":"Using the old casing for image embedding methods after upgrading to `pdf-lib` v1.0.0 or later.","error":"TypeError: pdfDoc.embedJPG is not a function"},{"fix":"For text containing characters outside WinAnsi (e.g., Unicode characters, emojis), embed a custom font that supports the required character set (e.g., `fontBytes = await fetch('/path/to/my-font.ttf').then(res => res.arrayBuffer()); const customFont = await pdfDoc.embedFont(fontBytes);`). Remember to install and register `@pdf-lib/fontkit` for custom fonts.","cause":"Attempting to draw text with characters not supported by the standard PDF fonts (e.g., `TimesRoman`, `Helvetica`), which primarily support the WinAnsi encoding.","error":"Standard fonts in pdf-lib cannot encode certain characters outside WinAnsi."},{"fix":"Replace `getMaybe` calls with `get`. If looking up a string-based dictionary key, wrap the string in `PDFName.of()`: `pdfDoc.catalog.get(PDFName.of('AcroForm'))`.","cause":"The `getMaybe` method was removed in `pdf-lib` v1.0.0.","error":"TypeError: pdfDoc.catalog.getMaybe is not a function"}],"ecosystem":"npm"}