LibPDF

PDF

The main document class for loading, creating, modifying, and saving PDFs.

PDF

The PDF class is the primary entry point for working with PDF documents. It provides methods for loading existing PDFs, creating new ones, and saving modifications.

import { PDF } from "@libpdf/core";

const pdf = await PDF.load(bytes);
console.log(`${pdf.getPageCount()} pages`);

Static Methods

PDF.load(bytes, options?)

Load a PDF from bytes.

ParamTypeDefaultDescription
bytesUint8ArrayrequiredPDF file bytes
[options]LoadOptions
[options.credentials]stringUser or owner password
[options.lenient]booleantrueEnable lenient parsing for malformed PDFs

Returns: Promise<PDF>

Throws:

  • Error - Document has no catalog (missing /Root in trailer)
  • Error - Parsing fails and lenient mode is disabled
// Basic load
const pdf = await PDF.load(bytes);

// With password
const encrypted = await PDF.load(bytes, { credentials: "secret" });

// Strict parsing (throws on malformed PDFs)
const strict = await PDF.load(bytes, { lenient: false });

PDF.create()

Create a new empty PDF document.

Returns: PDF

const pdf = PDF.create();
pdf.addPage({ size: "letter" });
const bytes = await pdf.save();

PDF.merge(sources, options?)

Merge multiple PDF documents into one.

ParamTypeDefaultDescription
sourcesUint8Array[]requiredArray of PDF bytes to merge
[options]MergeOptions
[options.credentials]stringPassword for encrypted sources
[options.includeAnnotations]booleantrueInclude annotations from sources

Returns: Promise<PDF>

const merged = await PDF.merge([pdf1Bytes, pdf2Bytes, pdf3Bytes]);
const bytes = await merged.save();

Instance Properties

version

PDF version string (e.g., "1.7", "2.0").

Type: string (readonly)


isEncrypted

Whether the document is encrypted.

Type: boolean (readonly)


isAuthenticated

Whether authentication succeeded (for encrypted documents).

Type: boolean (readonly)


recoveredViaBruteForce

Whether this document was recovered via brute-force parsing.

Type: boolean (readonly)


isLinearized

Whether this document is linearized (optimized for web viewing).

Type: boolean (readonly)


usesXRefStreams

Whether the original document uses XRef streams (PDF 1.5+).

Type: boolean (readonly)


warnings

Warnings accumulated during parsing and operations.

Type: string[] (readonly)


Page Methods

getPageCount()

Get the number of pages in the document.

Returns: number

const count = pdf.getPageCount();

getPage(index)

Get a single page by index (0-based).

ParamTypeDescription
indexnumberPage index (0-based)

Returns: Promise<PDFPage | null>

const page = await pdf.getPage(0);
if (page) {
  console.log(`Size: ${page.width} x ${page.height}`);
}

getPages()

Get all pages in document order.

Returns: Promise<PDFPage[]>

const pages = await pdf.getPages();
for (const page of pages) {
  console.log(`Page ${page.index}: ${page.width} x ${page.height}`);
}

addPage(options?)

Add a new blank page.

ParamTypeDefaultDescription
[options]AddPageOptions
[options.width]number612Page width in points
[options.height]number792Page height in points
[options.size]"letter" | "a4" | "legal""letter"Preset size
[options.orientation]"portrait" | "landscape""portrait"Page orientation
[options.rotate]number0Rotation (0, 90, 180, 270)
[options.insertAt]numberendInsert position

Returns: PDFPage

Throws: RangeError - If insertAt index is out of bounds

// Append US Letter page
const page = pdf.addPage();

// Insert A4 page at beginning
const firstPage = pdf.addPage({ size: "a4", insertAt: 0 });

// Custom size landscape
const wide = pdf.addPage({ width: 1000, height: 500 });

removePage(index)

Remove a page at the given index.

ParamTypeDescription
indexnumberPage index to remove

Returns: PdfRef - The removed page reference

Throws: RangeError - If index is out of bounds

pdf.removePage(0); // Remove first page

movePage(fromIndex, toIndex)

Move a page from one position to another.

ParamTypeDescription
fromIndexnumberCurrent page index
toIndexnumberTarget page index

Throws: RangeError - If either index is out of bounds

pdf.movePage(5, 0); // Move page 5 to the beginning

copyPagesFrom(source, indices, options?)

Copy pages from another PDF document.

ParamTypeDefaultDescription
sourcePDFrequiredSource PDF document
indicesnumber[]requiredPage indices to copy (0-based)
[options]CopyPagesOptions
[options.insertAt]numberendInsert position
[options.includeAnnotations]booleantrueInclude annotations

Returns: Promise<PDFPage[]> - Array of copied pages

Throws:

  • RangeError - If any source page index is out of bounds
  • Error - If source page not found
// Copy pages 0 and 2 from source
const copied = await dest.copyPagesFrom(source, [0, 2]);

// Insert at beginning
await dest.copyPagesFrom(source, [0], { insertAt: 0 });

// Duplicate a page in the same document
await pdf.copyPagesFrom(pdf, [0], { insertAt: 1 });

extractPages(indices, options?)

Extract pages into a new PDF document.

ParamTypeDefaultDescription
indicesnumber[]requiredPage indices to extract
[options]ExtractPagesOptions
[options.includeAnnotations]booleantrueInclude annotations

Returns: Promise<PDF> - New PDF containing extracted pages

Throws: RangeError - If any page index is out of bounds

// Extract first 3 pages
const first3 = await pdf.extractPages([0, 1, 2]);

// Extract odd pages
const oddPages = await pdf.extractPages([0, 2, 4, 6]);

const bytes = await first3.save();

embedPage(source, pageIndex)

Embed a page from another PDF as a reusable Form XObject.

ParamTypeDescription
sourcePDFSource PDF document
pageIndexnumberPage index to embed (0-based)

Returns: Promise<PDFEmbeddedPage>

Throws: RangeError - If page index is out of bounds

const watermark = await PDF.load(watermarkBytes);
const embedded = await pdf.embedPage(watermark, 0);

// Draw on all pages
for (const page of await pdf.getPages()) {
  page.drawPage(embedded, { opacity: 0.5 });
}

Form Methods

getForm()

Get the interactive form, if present.

Returns: Promise<PDFForm | null>

const form = await pdf.getForm();
if (form) {
  const fields = form.getFields();
  console.log(`${fields.length} fields found`);
}

Metadata Methods

getTitle() / setTitle(title, options?)

Get or set the document title.

const title = pdf.getTitle();

pdf.setTitle("Quarterly Report");

// Show in viewer's title bar
pdf.setTitle("My Document", { showInWindowTitleBar: true });

getAuthor() / setAuthor(author)

Get or set the document author.

pdf.setAuthor("Jane Smith");

getSubject() / setSubject(subject)

Get or set the document subject.

pdf.setSubject("Financial summary for Q4");

getKeywords() / setKeywords(keywords)

Get or set document keywords.

pdf.setKeywords(["finance", "quarterly", "2024"]);
const keywords = pdf.getKeywords(); // ["finance", "quarterly", "2024"]

getCreator() / setCreator(creator)

Get or set the creator application.

pdf.setCreator("Report Generator v2.0");

getProducer() / setProducer(producer)

Get or set the producer application.

pdf.setProducer("@libpdf/core");

getCreationDate() / setCreationDate(date)

Get or set the creation date.

pdf.setCreationDate(new Date());
const created = pdf.getCreationDate();

getModificationDate() / setModificationDate(date)

Get or set the modification date.

pdf.setModificationDate(new Date());

getLanguage() / setLanguage(language)

Get or set the document language (RFC 3066 tag).

pdf.setLanguage("en-US");

getMetadata() / setMetadata(metadata)

Get or set multiple metadata fields at once.

// Get all metadata
const metadata = pdf.getMetadata();

// Set multiple fields
pdf.setMetadata({
  title: "Quarterly Report",
  author: "Jane Smith",
  creationDate: new Date(),
});

Security Methods

getSecurity()

Get detailed security information.

Returns: SecurityInfo

const security = pdf.getSecurity();
console.log(`Encrypted: ${security.isEncrypted}`);
console.log(`Algorithm: ${security.algorithm}`);
console.log(`Can copy: ${security.permissions.copy}`);

getPermissions()

Get current permission flags.

Returns: Permissions

const perms = pdf.getPermissions();
if (!perms.copy) {
  console.log("Copy/paste is restricted");
}

Permission Flags:

FlagDescription
printPrint the document
printHighQualityHigh-resolution printing
modifyModify document contents
copyCopy text and graphics
annotateAdd or modify annotations
fillFormsFill form fields
assembleDocumentInsert, delete, rotate pages
extractForAccessibilityExtract for accessibility

hasOwnerAccess()

Check if authenticated with owner-level access.

Returns: boolean

if (pdf.hasOwnerAccess()) {
  pdf.removeProtection();
}

authenticate(password)

Attempt to authenticate with a password.

ParamTypeDescription
passwordstringPassword to try

Returns: AuthenticationResult

const result = pdf.authenticate("ownerPassword");
if (result.isOwner) {
  pdf.removeProtection();
}

setProtection(options)

Add or change document encryption.

ParamTypeDefaultDescription
optionsProtectionOptionsrequired
[options.userPassword]stringPassword to open
[options.ownerPassword]stringrandomPassword for full access
[options.permissions]PermissionOptionsall truePermission flags
[options.algorithm]EncryptionAlgorithmOption"AES-256"Encryption algorithm
[options.encryptMetadata]booleantrueEncrypt metadata

Throws: PermissionDeniedError - If insufficient permissions

Algorithm Options:

AlgorithmKey LengthNotes
"RC4-40"40-bitLegacy, weak, avoid
"RC4-128"128-bitDeprecated
"AES-128"128-bitRecommended minimum
"AES-256"256-bitStrongest, default
pdf.setProtection({
  userPassword: "secret",
  ownerPassword: "admin",
  permissions: { copy: false, print: true },
  algorithm: "AES-256",
});

removeProtection()

Remove all encryption from the document.

Throws: PermissionDeniedError - If insufficient permissions

const pdf = await PDF.load(bytes, { credentials: "ownerPassword" });
pdf.removeProtection();
const unprotectedBytes = await pdf.save();

Font and Image Methods

embedFont(bytes, options?)

Embed a font for use in drawing operations.

ParamTypeDefaultDescription
bytesUint8ArrayrequiredTTF or OTF font file bytes
[options]EmbedFontOptions
[options.subset]booleantrueSubset font on save

Returns: EmbeddedFont

const font = pdf.embedFont(fontBytes);

page.drawText("Hello", {
  font,
  size: 24,
});

embedImage(bytes)

Embed an image for use in drawing operations.

ParamTypeDescription
bytesUint8ArrayJPEG or PNG image bytes

Returns: Promise<PDFImage>

const image = await pdf.embedImage(jpegBytes);

page.drawImage(image, {
  x: 50,
  y: 500,
  width: 200,
});

Digital Signatures

sign(options)

Sign the document with a digital signature.

ParamTypeDefaultDescription
optionsSignOptionsrequired
options.signerSignerrequiredP12Signer or CryptoKeySigner
[options.level]PAdESLevel"B-B"PAdES conformance level
[options.timestampServer]stringRFC 3161 timestamp URL
[options.fieldName]stringautoSignature field name

Returns: Promise<SignResult>

PAdES Levels:

LevelDescription
"B-B"Basic signature
"B-T"With timestamp
"B-LT"Long-term validation
"B-LTA"Long-term archival
import { P12Signer } from "@libpdf/core";

const signer = await P12Signer.create(p12Bytes, "password");

const result = await pdf.sign({
  signer,
  level: "B-LTA",
  timestampServer: "http://timestamp.example.com",
});

// result.bytes contains the signed PDF

Save Methods

save(options?)

Save the document to bytes.

ParamTypeDefaultDescription
[options]SaveOptions
[options.incremental]booleanfalseAppend-only save (preserves signatures)
[options.useXRefStream]booleanautoUse XRef stream format
[options.subsetFonts]booleanfalseSubset embedded fonts

Returns: Promise<Uint8Array>

// Full rewrite
const bytes = await pdf.save();

// Incremental (preserves signatures)
const bytes = await pdf.save({ incremental: true });

// With font subsetting
const bytes = await pdf.save({ subsetFonts: true });

reload(bytes)

Reload the PDF from new bytes after an incremental save.

ParamTypeDescription
bytesUint8ArrayNew PDF bytes

Throws: Error - If the document has no catalog

const signed = await pdf.sign({ signer });
await pdf.reload(signed.bytes);
// Continue using the same PDF instance

Types

LoadOptions

interface LoadOptions {
  credentials?: string;  // User or owner password
  lenient?: boolean;     // Enable lenient parsing (default: true)
}

SaveOptions

interface SaveOptions {
  incremental?: boolean;   // Append-only save
  useXRefStream?: boolean; // Use XRef stream format
  subsetFonts?: boolean;   // Subset embedded fonts
}

DocumentMetadata

interface DocumentMetadata {
  title?: string;
  author?: string;
  subject?: string;
  keywords?: string[];
  creator?: string;
  producer?: string;
  creationDate?: Date;
  modificationDate?: Date;
  trapped?: "True" | "False" | "Unknown";
  language?: string;
}

SecurityInfo

interface SecurityInfo {
  isEncrypted: boolean;
  algorithm?: "RC4-40" | "RC4-128" | "AES-128" | "AES-256";
  keyLength?: number;
  revision?: number;
  hasUserPassword?: boolean;
  hasOwnerPassword?: boolean;
  authenticatedAs?: "user" | "owner" | null;
  permissions: Permissions;
  encryptMetadata?: boolean;
}

Permissions

interface Permissions {
  print: boolean;
  printHighQuality: boolean;
  modify: boolean;
  copy: boolean;
  annotate: boolean;
  fillForms: boolean;
  assembleDocument: boolean;
  extractForAccessibility: boolean;
}

On this page