Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
World desk5 min

How to Generate PDFs in JavaScript in the Browser

Use pdf-lib to create, edit, preview, and download PDFs in browser JavaScript. Learn how it differs from PDF.js and how to handle remote files and common failures.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To create a PDF in the browser, use a PDF-authoring library such as pdf-lib: create a document, add a page, draw content, then save the bytes and offer them as a download. That is different from displaying an existing PDF, which is what Mozilla’s PDF.js is designed to do.

Create and download a PDF with pdf-lib

This example uses a JavaScript module environment, such as an app built with a bundler. Install pdf-lib with npm install pdf-lib, then create a document and turn its saved bytes into a browser download.

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

async function downloadPdf() {
  const pdfDoc = await PDFDocument.create();
  const page = pdfDoc.addPage([595.28, 841.89]); // A4-sized page in PDF points
  const font = await pdfDoc.embedFont(StandardFonts.Helvetica);

  page.drawText('Hello from the browser', {
    x: 50,
    y: 780,
    size: 18,
    font,
    color: rgb(0, 0, 0),
  });

  const pdfBytes = await pdfDoc.save();
  const blob = new Blob([pdfBytes], { type: 'application/pdf' });
  const objectUrl = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = objectUrl;
  link.download = 'example.pdf';
  document.body.append(link);
  link.click();
  link.remove();
  URL.revokeObjectURL(objectUrl);
}

document.querySelector('#download-pdf').addEventListener('click', downloadPdf);

Place a button with id="download-pdf" in the page to trigger the example. The download happens in response to a user click, which is a dependable pattern for browser downloads. The page dimensions above are expressed in PDF points; you can pass different width and height values to addPage when you need a different layout.

For a simple preview rather than a download, pdf-lib’s quick start demonstrates serializing to a data URI and assigning it to an iframe’s src:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const dataUri = await pdfDoc.saveAsBase64({ dataUri: true });
document.querySelector('#pdf-preview').src = dataUri;

Add an iframe with id="pdf-preview" for this version. A preview is useful when someone should inspect the generated document before deciding whether to save it.

Choose a library for the PDF task

Need Suitable direction What it does
Create a new PDF or modify one programmatically pdf-lib Creates and modifies PDFs, including drawing text, embedding images and fonts, filling forms, and copying or combining pages.
Render and inspect an existing PDF PDF.js Provides a display layer for rendering PDFs and retrieving document information; it is complementary to an authoring library, not the creation path shown here.

pdf-lib uses explicit page coordinates for drawing. Do not assume that applying ordinary webpage CSS to a document will reproduce the same layout in a PDF; the workflow here composes PDF content directly. If you need to import a remote PDF or image, fetch its bytes before loading or embedding it. Verify that the asset can be requested from your app’s origin and handle network failures before proceeding.

Load an existing PDF or remote asset

pdf-lib can load an existing PDF for changes, and its examples fetch remote documents and assets as bytes before loading or embedding them. A minimal pattern for a PDF is:

const response = await fetch('/documents/source.pdf');
if (!response.ok) {
  throw new Error(`Could not fetch PDF: ${response.status}`);
}
const existingPdfBytes = await response.arrayBuffer();
const pdfDoc = await PDFDocument.load(existingPdfBytes);

// Make changes to pdfDoc here.
const updatedPdfBytes = await pdfDoc.save();

The URL in this example is a same-origin example path; replace it with the actual resource URL. For remote origins, the server must permit the browser request under its cross-origin policy. Fetching the bytes successfully is a separate prerequisite from whether pdf-lib can parse or embed them.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Browser implementation details that affect reliability

  • Wait for asynchronous work. Creating, loading, embedding and saving documents are asynchronous steps. Await them before creating the download or preview.
  • Revoke download URLs after use. URL.createObjectURL allocates a temporary URL. The example revokes it after triggering the download; for a UI that may open it later, revoke it when it is no longer needed.
  • Use an explicit output type. Set the Blob MIME type to application/pdf so browser handling identifies the file as a PDF.
  • Check remote requests. A failed fetch, blocked cross-origin request, or invalid PDF input must be handled before loading or embedding bytes.
  • Test the actual target browsers and document sizes. The available project documentation does not establish a complete browser compatibility matrix or quantitative performance limits, so do not assume a particular size or speed ceiling without testing your app.
  • Pin CDN versions in production. If loading a UMD build from a CDN, pdf-lib recommends specifying a version in the URL. Check the current release and its documentation before choosing the pinned version.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If what you need is a capture of a webpage rather than a custom document assembled from application data, ScreenshotNeo can return a website screenshot or PDF from an API request. It is not a replacement for composing arbitrary PDF pages with pdf-lib. Its API also accepts or removes cookie banners, newsletter popups and chat widgets before capture; bot checks, blank pages and failed loads are not billed; and its MCP server lets AI agents take screenshots.

Here is the supplied one-call cURL example for a webpage capture. See the ScreenshotNeo documentation for PDF output options and other request parameters.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up for free.

Troubleshooting

  • The button does nothing: Check the button’s selector and ensure the event listener is registered after the relevant element exists. Look for rejected promises in the browser console.
  • The generated file is empty or incomplete: Confirm all content-building steps finish before save() runs, and check that any fetched source or image bytes were loaded successfully.
  • A remote PDF or image will not load: Inspect the network response and browser console. Confirm the URL is correct and the remote server permits the browser request; handle non-success HTTP responses before passing bytes to pdf-lib.
  • The preview does not appear: Ensure the iframe exists and the data URI is assigned after serialization completes. For larger outputs, consider an object URL backed by a Blob instead of embedding a data URI.
  • Text or images are positioned incorrectly: Recheck the PDF page dimensions and the coordinates passed to drawing methods. The authoring model is coordinate-based, not a direct transfer of HTML layout.

References

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.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Shenzhen desk3 min
    HONOR Expands Beyond Smartphones With Humanoid Robot RevealHONOR said it unveiled its first humanoid robot at MWC 2026 and named shopping assistance, workplace inspections, and supportive companionship as intended uses. Later Robotics D1 claims and a reported…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.