pdf-lib.js.org Open in urlscan Pro
2606:50c0:8003::153  Public Scan

URL: https://pdf-lib.js.org/
Submission: On December 26 via manual from CL — Scanned from DE

Form analysis 0 forms found in the DOM

Text Content

PDF-LIB

 * API
 * Help
 * GitHub

 * 

import { PDFDocument } from 'pdf-lib'

// PDF Creation
const pdfDoc = await PDFDocument.create()
const page = pdfDoc.addPage()
page.drawText('You can create PDFs!')
const pdfBytes = await pdfDoc.save()

// PDF Modification
const pdfDoc = await PDFDocument.load(...)
const pages = pdfDoc.getPages()
pages[0].drawText('You can modify PDFs too!')
const pdfBytes = await pdfDoc.save()


import { PDFDocument } from 'pdf-lib'

// PDF Creation
const pdfDoc = await PDFDocument.create()
const page = pdfDoc.addPage()
page.drawText('You can create PDFs!')
const pdfBytes = await pdfDoc.save()

// PDF Modification
const pdfDoc = await PDFDocument.load(...)
const pages = pdfDoc.getPages()
pages[0].drawText('You can modify PDFs too!')
const pdfBytes = await pdfDoc.save()


Create and modify PDF documents in any JavaScript environment.
Examples
Install

CREATE AND MODIFY

Create PDF documents from scratch, or modify existing PDF documents. Draw text,
images, and vector graphics. Embed your own fonts. Even embed and draw pages
from other PDFs.

PURE JAVASCRIPT

Written in TypeScript and compiled to pure JavaScript with no native
dependencies. Works in any JavaScript runtime, including browsers, Node, Deno,
and even React Native.

SPLIT AND MERGE

Add, insert, and remove pages. Split a single PDF into separate ones. Or merge
multiple PDFs into a single document.

FILL FORMS

Create new forms or fill and read existing fields. Check boxes, buttons, radio
groups, dropdowns, option lists, and text fields are all supported.

> View the full feature set


QUICK START

<html>
  <head>
    <meta charset="utf-8" />
    <script src="https://unpkg.com/pdf-lib"></script>
  </head>

  <body>
    <iframe id="pdf" style="width: 100%; height: 100%;"></iframe>
  </body>

  <script>
    createPdf();
    async function createPdf() {
      const pdfDoc = await PDFLib.PDFDocument.create();
      const page = pdfDoc.addPage([350, 400]);
      page.moveTo(110, 200);
      page.drawText('Hello World!');
      const pdfDataUri = await pdfDoc.saveAsBase64({ dataUri: true });
      document.getElementById('pdf').src = pdfDataUri;
    }
  </script>
</html>


Save this snippet as an HTML file and load it in your browser to get up and
running with pdf-lib as quickly as possible.


DENO

$ deno run --allow-write https://pdf-lib.js.org/deno/quick_start.ts


If you are using Deno, then try running the above command in your terminal to
quickly create a PDF document! πŸ¦•


INSTALL


NPM MODULE

If you are using npm or yarn as your package manager:

# With npm
npm install --save pdf-lib

# With yarn
yarn add pdf-lib





UMD MODULE

If you aren't using a package manager, UMD modules are available on the unpkg
and jsDelivr CDNs:

 * https://unpkg.com/pdf-lib/dist/pdf-lib.js
 * https://unpkg.com/pdf-lib/dist/pdf-lib.min.js
 * https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.js
 * https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js



> NOTE: if you are using the CDN scripts in production, you should include a
> specific version number in the URL, for example:
>  * https://unpkg.com/pdf-lib@1.4.0/dist/pdf-lib.min.js
>  * https://cdn.jsdelivr.net/npm/pdf-lib@1.4.0/dist/pdf-lib.min.js


CREATE DOCUMENT

Try the JSFiddle demo

import { PDFDocument, StandardFonts, rgb } from 'pdf-lib'

async function createPdf() {
  const pdfDoc = await PDFDocument.create()
  const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman)

  const page = pdfDoc.addPage()
  const { width, height } = page.getSize()
  const fontSize = 30
  page.drawText('Creating PDFs in JavaScript is awesome!', {
    x: 50,
    y: height - 4 * fontSize,
    size: fontSize,
    font: timesRomanFont,
    color: rgb(0, 0.53, 0.71),
  })

  const pdfBytes = await pdfDoc.save()
}



MODIFY DOCUMENT

Try the JSFiddle demo

import { degrees, PDFDocument, rgb, StandardFonts } from 'pdf-lib';

async function modifyPdf() {
  const url = 'https://pdf-lib.js.org/assets/with_update_sections.pdf'
  const existingPdfBytes = await fetch(url).then(res => res.arrayBuffer())

  const pdfDoc = await PDFDocument.load(existingPdfBytes)
  const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica)

  const pages = pdfDoc.getPages()
  const firstPage = pages[0]
  const { width, height } = firstPage.getSize()
  firstPage.drawText('This text was added with JavaScript!', {
    x: 5,
    y: height / 2 + 300,
    size: 50,
    font: helveticaFont,
    color: rgb(0.95, 0.1, 0.1),
    rotate: degrees(-45),
  })

  const pdfBytes = await pdfDoc.save()
}



CREATE FORM

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

async function createForm() {
  const pdfDoc = await PDFDocument.create()

  const page = pdfDoc.addPage([550, 750])

  const form = pdfDoc.getForm()

  page.drawText('Enter your favorite superhero:', { x: 50, y: 700, size: 20 })

  const superheroField = form.createTextField('favorite.superhero')
  superheroField.setText('One Punch Man')
  superheroField.addToPage(page, { x: 55, y: 640 })

  page.drawText('Select your favorite rocket:', { x: 50, y: 600, size: 20 })

  page.drawText('Falcon Heavy', { x: 120, y: 560, size: 18 })
  page.drawText('Saturn IV', { x: 120, y: 500, size: 18 })
  page.drawText('Delta IV Heavy', { x: 340, y: 560, size: 18 })
  page.drawText('Space Launch System', { x: 340, y: 500, size: 18 })

  const rocketField = form.createRadioGroup('favorite.rocket')
  rocketField.addOptionToPage('Falcon Heavy', page, { x: 55, y: 540 })
  rocketField.addOptionToPage('Saturn IV', page, { x: 55, y: 480 })
  rocketField.addOptionToPage('Delta IV Heavy', page, { x: 275, y: 540 })
  rocketField.addOptionToPage('Space Launch System', page, { x: 275, y: 480 })
  rocketField.select('Saturn IV')

  page.drawText('Select your favorite gundams:', { x: 50, y: 440, size: 20 })

  page.drawText('Exia', { x: 120, y: 400, size: 18 })
  page.drawText('Kyrios', { x: 120, y: 340, size: 18 })
  page.drawText('Virtue', { x: 340, y: 400, size: 18 })
  page.drawText('Dynames', { x: 340, y: 340, size: 18 })

  const exiaField = form.createCheckBox('gundam.exia')
  const kyriosField = form.createCheckBox('gundam.kyrios')
  const virtueField = form.createCheckBox('gundam.virtue')
  const dynamesField = form.createCheckBox('gundam.dynames')

  exiaField.addToPage(page, { x: 55, y: 380 })
  kyriosField.addToPage(page, { x: 55, y: 320 })
  virtueField.addToPage(page, { x: 275, y: 380 })
  dynamesField.addToPage(page, { x: 275, y: 320 })

  exiaField.check()
  dynamesField.check()

  page.drawText('Select your favorite planet*:', { x: 50, y: 280, size: 20 })

  const planetsField = form.createDropdown('favorite.planet')
  planetsField.addOptions(['Venus', 'Earth', 'Mars', 'Pluto'])
  planetsField.select('Pluto')
  planetsField.addToPage(page, { x: 55, y: 220 })

  page.drawText('Select your favorite person:', { x: 50, y: 180, size: 18 })

  const personField = form.createOptionList('favorite.person')
  personField.addOptions([
    'Julius Caesar',
    'Ada Lovelace',
    'Cleopatra',
    'Aaron Burr',
    'Mark Antony',
  ])
  personField.select('Ada Lovelace')
  personField.addToPage(page, { x: 55, y: 70 })

  page.drawText(`* Pluto should be a planet too!`, { x: 15, y: 15, size: 15 })

  const pdfBytes = await pdfDoc.save()
}



FILL FORM

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

async function fillForm() {
  const formUrl = 'https://pdf-lib.js.org/assets/dod_character.pdf'
  const formPdfBytes = await fetch(formUrl).then(res => res.arrayBuffer())

  const marioUrl = 'https://pdf-lib.js.org/assets/small_mario.png'
  const marioImageBytes = await fetch(marioUrl).then(res => res.arrayBuffer())

  const emblemUrl = 'https://pdf-lib.js.org/assets/mario_emblem.png'
  const emblemImageBytes = await fetch(emblemUrl).then(res => res.arrayBuffer())

  const pdfDoc = await PDFDocument.load(formPdfBytes)

  const marioImage = await pdfDoc.embedPng(marioImageBytes)
  const emblemImage = await pdfDoc.embedPng(emblemImageBytes)

  const form = pdfDoc.getForm()

  const nameField = form.getTextField('CharacterName 2')
  const ageField = form.getTextField('Age')
  const heightField = form.getTextField('Height')
  const weightField = form.getTextField('Weight')
  const eyesField = form.getTextField('Eyes')
  const skinField = form.getTextField('Skin')
  const hairField = form.getTextField('Hair')

  const alliesField = form.getTextField('Allies')
  const factionField = form.getTextField('FactionName')
  const backstoryField = form.getTextField('Backstory')
  const traitsField = form.getTextField('Feat+Traits')
  const treasureField = form.getTextField('Treasure')

  const characterImageField = form.getButton('CHARACTER IMAGE')
  const factionImageField = form.getButton('Faction Symbol Image')

  nameField.setText('Mario')
  ageField.setText('24 years')
  heightField.setText(`5' 1"`)
  weightField.setText('196 lbs')
  eyesField.setText('blue')
  skinField.setText('white')
  hairField.setText('brown')

  characterImageField.setImage(marioImage)

  alliesField.setText(
    [
      `Allies:`,
      `  β€’ Princess Daisy`,
      `  β€’ Princess Peach`,
      `  β€’ Rosalina`,
      `  β€’ Geno`,
      `  β€’ Luigi`,
      `  β€’ Donkey Kong`,
      `  β€’ Yoshi`,
      `  β€’ Diddy Kong`,
      ``,
      `Organizations:`,
      `  β€’ Italian Plumbers Association`,
    ].join('\n'),
  )

  factionField.setText(`Mario's Emblem`)

  factionImageField.setImage(emblemImage)

  backstoryField.setText(
    [
      `Mario is a fictional character in the Mario video game franchise, `,
      `owned by Nintendo and created by Japanese video game designer Shigeru `,
      `Miyamoto. Serving as the company's mascot and the eponymous `,
      `protagonist of the series, Mario has appeared in over 200 video games `,
      `since his creation. Depicted as a short, pudgy, Italian plumber who `,
      `resides in the Mushroom Kingdom, his adventures generally center `,
      `upon rescuing Princess Peach from the Koopa villain Bowser. His `,
      `younger brother and sidekick is Luigi.`,
    ].join('\n'),
  )

  traitsField.setText(
    [
      `Mario can use three basic three power-ups:`,
      `  β€’ the Super Mushroom, which causes Mario to grow larger`,
      `  β€’ the Fire Flower, which allows Mario to throw fireballs`,
      `  β€’ the Starman, which gives Mario temporary invincibility`,
    ].join('\n'),
  )

  treasureField.setText(['β€’ Gold coins', 'β€’ Treasure chests'].join('\n'))

  const pdfBytes = await pdfDoc.save()
}



FLATTEN FORM

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

async function flattenForm() {
  const formUrl = 'https://pdf-lib.js.org/assets/form_to_flatten.pdf'
  const formPdfBytes = await fetch(formUrl).then(res => res.arrayBuffer())

  const pdfDoc = await PDFDocument.load(formPdfBytes)

  const form = pdfDoc.getForm()

  form.getTextField('Text1').setText('Some Text');
  form.getRadioGroup('Group2').select('Choice1');
  form.getRadioGroup('Group3').select('Choice3');
  form.getRadioGroup('Group4').select('Choice1');
  form.getCheckBox('Check Box3').check();
  form.getCheckBox('Check Box4').uncheck();
  form.getDropdown('Dropdown7').select('Infinity');
  form.getOptionList('List Box6').select('Honda');

  form.flatten();

  const pdfBytes = await pdfDoc.save()
}



COPY PAGES

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

async function copyPages() {
  const url1 = 'https://pdf-lib.js.org/assets/with_update_sections.pdf'
  const url2 = 'https://pdf-lib.js.org/assets/with_large_page_count.pdf'

  const firstDonorPdfBytes = await fetch(url1).then(res => res.arrayBuffer())
  const secondDonorPdfBytes = await fetch(url2).then(res => res.arrayBuffer())

  const firstDonorPdfDoc = await PDFDocument.load(firstDonorPdfBytes)
  const secondDonorPdfDoc = await PDFDocument.load(secondDonorPdfBytes)

  const pdfDoc = await PDFDocument.create();

  const [firstDonorPage] = await pdfDoc.copyPages(firstDonorPdfDoc, [0])
  const [secondDonorPage] = await pdfDoc.copyPages(secondDonorPdfDoc, [742])

  pdfDoc.addPage(firstDonorPage)
  pdfDoc.insertPage(0, secondDonorPage)

  const pdfBytes = await pdfDoc.save()
}



EMBED PNG AND JPEG IMAGES

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

async function embedImages() {
  const jpgUrl = 'https://pdf-lib.js.org/assets/cat_riding_unicorn.jpg'
  const pngUrl = 'https://pdf-lib.js.org/assets/minions_banana_alpha.png'

  const jpgImageBytes = await fetch(jpgUrl).then((res) => res.arrayBuffer())
  const pngImageBytes = await fetch(pngUrl).then((res) => res.arrayBuffer())

  const pdfDoc = await PDFDocument.create()

  const jpgImage = await pdfDoc.embedJpg(jpgImageBytes)
  const pngImage = await pdfDoc.embedPng(pngImageBytes)

  const jpgDims = jpgImage.scale(0.5)
  const pngDims = pngImage.scale(0.5)

  const page = pdfDoc.addPage()

  page.drawImage(jpgImage, {
    x: page.getWidth() / 2 - jpgDims.width / 2,
    y: page.getHeight() / 2 - jpgDims.height / 2 + 250,
    width: jpgDims.width,
    height: jpgDims.height,
  })
  page.drawImage(pngImage, {
    x: page.getWidth() / 2 - pngDims.width / 2 + 75,
    y: page.getHeight() / 2 - pngDims.height + 250,
    width: pngDims.width,
    height: pngDims.height,
  })

  const pdfBytes = await pdfDoc.save()
}



EMBED PDF PAGES

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

async function embedPdfPages() {
  const flagUrl = 'https://pdf-lib.js.org/assets/american_flag.pdf';
  const constitutionUrl = 'https://pdf-lib.js.org/assets/us_constitution.pdf';

  const flagPdfBytes = await fetch(flagUrl).then((res) => res.arrayBuffer());
  const constitutionPdfBytes = await fetch(constitutionUrl).then((res) =>
    res.arrayBuffer(),
  );

  const pdfDoc = await PDFDocument.create();

  const [americanFlag] = await pdfDoc.embedPdf(flagPdfBytes);

  const usConstitutionPdf = await PDFDocument.load(constitutionPdfBytes);
  const preamble = await pdfDoc.embedPage(usConstitutionPdf.getPages()[1], {
    left: 55,
    bottom: 485,
    right: 300,
    top: 575,
  });

  const americanFlagDims = americanFlag.scale(0.3);
  const preambleDims = preamble.scale(2.25);

  const page = pdfDoc.addPage();

  page.drawPage(americanFlag, {
    ...americanFlagDims,
    x: page.getWidth() / 2 - americanFlagDims.width / 2,
    y: page.getHeight() - americanFlagDims.height - 150,
  });
  page.drawPage(preamble, {
    ...preambleDims,
    x: page.getWidth() / 2 - preambleDims.width / 2,
    y: page.getHeight() / 2 - preambleDims.height / 2 - 50,
  });

  const pdfBytes = await pdfDoc.save();
}



EMBED FONT AND MEASURE TEXT

Try the JSFiddle demo

The@pdf-lib/fontkit module must be installed to embed custom fonts.

import { PDFDocument, rgb } from 'pdf-lib'
import fontkit from '@pdf-lib/fontkit'

async function embedFontAndMeasureText() {
  const url = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf'
  const fontBytes = await fetch(url).then(res => res.arrayBuffer())

  const pdfDoc = await PDFDocument.create()

  pdfDoc.registerFontkit(fontkit)
  const customFont = await pdfDoc.embedFont(fontBytes)

  const page = pdfDoc.addPage()

  const text = 'This is text in an embedded font!'
  const textSize = 35
  const textWidth = customFont.widthOfTextAtSize(text, textSize)
  const textHeight = customFont.heightAtSize(textSize)

  page.drawText(text, {
    x: 40,
    y: 450,
    size: textSize,
    font: customFont,
    color: rgb(0, 0.53, 0.71),
  })
  page.drawRectangle({
    x: 40,
    y: 450,
    width: textWidth,
    height: textHeight,
    borderColor: rgb(1, 0, 0),
    borderWidth: 1.5,
  })

  const pdfBytes = await pdfDoc.save()
}



ADD ATTACHMENTS

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

async function addAttachments() {
  const jpgUrl = 'https://pdf-lib.js.org/assets/cat_riding_unicorn.jpg'
  const pdfUrl = 'https://pdf-lib.js.org/assets/us_constitution.pdf';

  const jpgAttachmentBytes = await fetch(jpgUrl).then(res => res.arrayBuffer())
  const pdfAttachmentBytes = await fetch(pdfUrl).then(res => res.arrayBuffer())
  
  const pdfDoc = await PDFDocument.create()
  
  await pdfDoc.attach(jpgAttachmentBytes, 'cat_riding_unicorn.jpg', {
    mimeType: 'image/jpeg',
    description: 'Cool cat riding a unicorn! πŸ¦„πŸˆπŸ•ΆοΈ',
    creationDate: new Date('2019/12/01'),
    modificationDate: new Date('2020/04/19'),
  })
  
  await pdfDoc.attach(pdfAttachmentBytes, 'us_constitution.pdf', {
    mimeType: 'application/pdf',
    description: 'Constitution of the United States πŸ‡ΊπŸ‡ΈπŸ¦…',
    creationDate: new Date('1787/09/17'),
    modificationDate: new Date('1992/05/07'),
  })
  
  const page = pdfDoc.addPage();
  page.drawText('This PDF has two attachments', { x: 135, y: 415 })
  
  const pdfBytes = await pdfDoc.save()
}


> Note that only some PDF readers can view attachments. This includes Adobe
> Reader, Foxit Reader, and Firefox.


SET DOCUMENT METADATA

Try the JSFiddle demo

import { PDFDocument, StandardFonts } from 'pdf-lib'

async function setDocumentMetadata() {
  const pdfDoc = await PDFDocument.create()
  const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman)
  
  const page = pdfDoc.addPage([500, 600])
  page.setFont(timesRomanFont)
  page.drawText('The Life of an Egg', { x: 60, y: 500, size: 50 })
  page.drawText('An Epic Tale of Woe', { x: 125, y: 460, size: 25 })
  
  // Note that these fields are visible in the "Document Properties" section of 
  // most PDF readers.
  pdfDoc.setTitle('πŸ₯š The Life of an Egg 🍳')
  pdfDoc.setAuthor('Humpty Dumpty')
  pdfDoc.setSubject('πŸ“˜ An Epic Tale of Woe πŸ“–')
  pdfDoc.setKeywords(['eggs', 'wall', 'fall', 'king', 'horses', 'men'])
  pdfDoc.setProducer('PDF App 9000 πŸ€–')
  pdfDoc.setCreator('pdf-lib (https://github.com/Hopding/pdf-lib)')
  pdfDoc.setCreationDate(new Date('2018-06-24T01:58:37.228Z'))
  pdfDoc.setModificationDate(new Date('2019-12-21T07:00:11.000Z'))
  
  const pdfBytes = await pdfDoc.save()
}



READ DOCUMENT METADATA

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

async function readDocumentMetadata() {
  const url = 'https://pdf-lib.js.org/assets/with_cropbox.pdf'
  const existingPdfBytes = await fetch(url).then(res => res.arrayBuffer())

  const pdfDoc = await PDFDocument.load(existingPdfBytes, { 
    updateMetadata: false 
  })
  
  console.log('Title:', pdfDoc.getTitle())
  console.log('Author:', pdfDoc.getAuthor())
  console.log('Subject:', pdfDoc.getSubject())
  console.log('Creator:', pdfDoc.getCreator())
  console.log('Keywords:', pdfDoc.getKeywords())
  console.log('Producer:', pdfDoc.getProducer())
  console.log('Creation Date:', pdfDoc.getCreationDate())
  console.log('Modification Date:', pdfDoc.getModificationDate())
}


This script outputs the following:

Title: Microsoft Word - Basic Curriculum Vitae example.doc
Author: Administrator
Subject: undefined
Creator: PScript5.dll Version 5.2
Keywords: undefined
Producer: Acrobat Distiller 8.1.0 (Windows)
Creation Date: 2010-07-29T14:26:00.000Z
Modification Date: 2010-07-29T14:26:00.000Z



DRAW SVG PATHS

Try the JSFiddle demo

import { PDFDocument, rgb } from 'pdf-lib'

async function drawSvgPaths() {
  const svgPath =
    'M 0,20 L 100,160 Q 130,200 150,120 C 190,-40 200,200 300,150 L 400,90'
  
  const pdfDoc = await PDFDocument.create()
  
  const page = pdfDoc.addPage()
  page.moveTo(100, page.getHeight() - 5)
  
  page.moveDown(25)
  page.drawSvgPath(svgPath)
  
  page.moveDown(200)
  page.drawSvgPath(svgPath, { borderColor: rgb(0, 1, 0), borderWidth: 5 })
  
  page.moveDown(200)
  page.drawSvgPath(svgPath, { color: rgb(1, 0, 0) })
  
  page.moveDown(200)
  page.drawSvgPath(svgPath, { scale: 0.5 })
  
  const pdfBytes = await pdfDoc.save()
}