Library / SDK
parallax/jsPDF avatar
parallax/jsPDF

jsPDF: Client-Side PDF Generation Without a Server Round Trip

Client-side JavaScript PDF generation for everyone.

31,304 stars4,794 forksJavaScriptMIT

At a glance

What is it?
jsPDF builds PDFs in the browser or in Node from a small imperative API. It is a good fit for generated documents you fully control, and a poor fit for pixel-perfect rendering of arbitrary HTML.
Who is it for?
Adopt jsPDF when your PDF is a document you construct yourself from known data: invoices, tickets, labels, reports with fixed layout. Do not adopt it expecting a faithful renderer for arbitrary web pages, and do not adopt it if your content must be laid out by a full HTML/CSS engine.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 17 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What jsPDF solves, and who ends up using it

Generating a PDF on a server means a round trip: serialize the data, send it, render, stream a file back. jsPDF removes that step by shipping a PDF writer that runs in the same JavaScript context as your application. The README describes it plainly as "a library to generate PDFs in JavaScript", and the package main entry points at dist/jspdf.node.min.js while the browser field points at dist/jspdf.es.min.js, so the same import works in both places.

The audience is narrow but real. Front-end developers producing receipts, tickets, shipping labels, or export buttons that must work offline. Node developers writing batch jobs that emit thousands of small documents where the layout is already known. Teams that want the download to start without a backend service existing at all. It is not aimed at anyone who needs to convert an existing web page into a PDF with the same CSS, because that is a different problem and jsPDF only partially reaches toward it through optional dependencies.

The drawing model: an imperative canvas, not a layout engine

You create a document object, then issue drawing calls against a coordinate system. The default is A4, portrait, millimetres, and the README's first example places text at (10, 10) before calling save. There is no reflow. If a string is too long for the page width it does not wrap on its own; you either supply an explicit maxWidth argument to text or use splitTextToSize. This is the single most common source of surprise for people arriving from HTML tooling.

The document is assembled in memory and serialized on save. Under Node, save writes to the current working directory using file operations rather than browser APIs, which is why the package publishes a separate node build. Fonts are the other structural constraint: the base 14 PDF fonts cover Latin text, and anything else has to go through the font converter in the repository to produce an embeddable font file. The repository layout includes a fontconverter/ directory for exactly that.

For HTML, the html() method exists but the README is explicit that it depends on html2canvas and, when given a string document, dompurify. Those are optional dependencies loaded dynamically, so they are not pulled in unless you call html(). The result is a rasterized image of the DOM placed into the page, not selectable text with the original CSS preserved.

Installing jsPDF from npm and producing a first document

The README recommends npm and also documents yarn and a script tag pointing at unpkg. The npm route is the one to take for an application, because it lets the package exports field pick the right build for your target.

bash
npm install jspdf --save

After that, importing the named jsPDF export and drawing two pieces of text is enough to produce a file. The save call triggers the download in a browser and writes to disk under Node.

javascript
import { jsPDF } from "jspdf";

const doc = new jsPDF();
doc.text("Hello world!", 10, 10);
doc.save("a4.pdf");

The constructor takes an options object when the defaults are wrong. The README shows a landscape page measured in inches with a custom format array, which is the pattern for labels and tickets where the page is not a standard size.

javascript
const doc = new jsPDF({
  orientation: "landscape",
  unit: "in",
  format: [4, 2]
});

doc.text("Hello world!", 1, 1);
doc.save("two-by-four.pdf");

In Node the same code works through require, and save writes a4.pdf into the current working directory rather than prompting a download. If you load jsPDF from a script tag instead, the README shows the global form: read jsPDF off window.jspdf and construct from there.

The html() path, and why it is not an HTML to PDF renderer

People search for jsPDF HTML to PDF, and the method exists, but the mechanism matters. html() delegates the rendering to html2canvas, which paints the DOM onto a canvas, and that canvas is then embedded as an image in the PDF. The README also notes dompurify is loaded when the method receives a string HTML document. Two consequences follow directly.

The output is an image. Text inside it is not selectable and not searchable, and file size tracks the pixel dimensions of the raster rather than the amount of text. And the fidelity is only as good as html2canvas, which does not implement the whole CSS specification. If your requirement is a PDF that looks exactly like a styled page and remains indexable, this path will not satisfy it, and no amount of option tuning inside jsPDF changes that.

The optional dependency loading is also a bundler concern. Because these modules are imported dynamically, Webpack creates separate chunks for canvg, html2canvas and dompurify. The README gives a webpack externals snippet to suppress chunks you do not need, and notes the equivalents for Vue CLI, Angular custom webpack builders, and create-react-app via react-app-rewired or ejecting. If you never call html(), declaring those packages as externals is a reasonable build-time cleanup.

Limitations, failure modes, and the security default under Node

Layout is manual. Multi-page flow, table pagination, and automatic page breaks are not part of the core API, which is why jspdf-autotable exists as a separate package and why so many questions about jsPDF are really questions about tables. If your document is a long report with flowing paragraphs and a table of contents, you will be writing pagination logic yourself.

The README carries a blunt warning that user input should be sanitized before being passed to jsPDF. Treat that as a design constraint, not boilerplate. Any string from a form, a database, or a URL that reaches text() or html() is input to a PDF writer, and the library does not sanitize it for you.

Under Node, jsPDF restricts reading files from the local file system by default. The README's strongly recommended approach is Node's own permission flags, for example node --permission --allow-fs-read=... on your script, with the caveat that every imported JavaScript file, dependencies included, must be listed. The fallback is setting doc.allowFsRead to an array of paths, and the README states plainly that the Node flags are preferred because the runtime enforces them. If you are generating PDFs from untrusted content in a Node service, the flag approach is the one to use, and the allowlist maintenance is a real cost.

Finally, the browser build requires modern APIs. Internet Explorer and similarly old engines need the polyfills bundle, imported as jspdf/dist/polyfills.es.js or the self-contained UMD variant.

Where jsPDF sits against server-side PDF tooling

The alternative most teams weigh is a headless browser driving a print stylesheet, or a server-side library that lays out HTML and CSS. The difference in approach is fundamental. jsPDF gives you a coordinate-based drawing API and a small set of primitives; a headless browser gives you a real rendering engine and your existing CSS.

If the document already exists as a styled page, the headless browser route is less work and produces selectable text. If the document is data with a known shape, jsPDF avoids running a browser, avoids a service, and lets the file be produced on the client. That is the trade: control and no infrastructure against layout convenience. A team building a one-page invoice with fixed positions will find jsPDF shorter than standing up a rendering service. A team asked to export an arbitrary dashboard view will fight it.

There is also the question of where the code runs. jsPDF is the only one of these options that can produce the file entirely in the user's browser with no network call, which matters for offline use and for privacy-sensitive documents that should not leave the device.

Maintenance, licensing, and what upgrading costs

The repository is not archived and the last push was on 2026-09-10. Releases have continued through the 4.2 line, with v4.2.1 published on 2026-03-17, v4.2.0 on 2026-02-19 and v4.1.0 on 2026-02-02. The project is co-maintained by yWorks according to the README, and the README also points to a commercial consultancy run by the original author.

The licence is MIT, which is permissive and imposes no copyleft obligation on your application. The runtime dependencies are @babel/runtime, fflate and fast-png; canvg, core-js, dompurify and html2canvas are optional and only matter if you use the features that need them. For a licence review, the practical question is whether any optional dependency you actually rely on carries terms you have not already accepted, since those are the ones pulled into your bundle.

Upgrade cost is concentrated in the major versions. The package exports field, the separate node and browser builds, and the dynamic optional imports are the parts most likely to interact with a bundler configuration, so a major bump is a good moment to re-check that your build still resolves the intended dist file and that externals for unused optional dependencies are still accurate. There is no migration guide in the README, so the release notes are the place to look.

Editorial conclusion

Adopt jsPDF when your PDF is a document you construct yourself from known data: invoices, tickets, labels, reports with fixed layout. Do not adopt it expecting a faithful renderer for arbitrary web pages, and do not adopt it if your content must be laid out by a full HTML/CSS engine. Before committing, verify three things: that the fonts you need are embedded through the font converter, that your bundler resolves the dist variant you expect (node, es or umd), and that anything user-supplied reaching text() or html() is sanitized, since the README states this explicitly.

Frequently asked questions

What is jsPDF?

It is a JavaScript library for generating PDF documents, described in the README as "a library to generate PDFs in JavaScript". It runs in the browser and in Node, and the package publishes separate builds for each.

How do I install jsPDF?

The README recommends npm, running npm install jspdf --save, or yarn add jspdf. It also documents loading the UMD build from unpkg with a script tag.

How to use jsPDF to convert HTML to PDF?

Through the html() method, which the README says depends on html2canvas and, for a string HTML document, dompurify. Those are optional dependencies loaded dynamically, and the result is a rasterized image embedded in the page rather than selectable text.

How to use jsPDF in React?

The README states jsPDF can be imported like any other third party library and works with all major toolkits, offering a typings file for TypeScript. For create-react-app it notes that externals require react-app-rewired or ejecting.

How to use jsPDF in Angular?

The README says jsPDF imports like any other library and ships TypeScript typings. For Angular, externals for the optional dependencies can be defined using custom webpack builders.

What is jspdf-autotable?

It is not covered in the README, which documents jsPDF's own API only. Table generation is not part of the core drawing calls described there, so anything about jspdf-autotable has to come from that package's own documentation.

Official sources

  1. License: MIT
  2. parallax/jsPDF on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/parallax-jspdf.svg)](https://hysenlabs.com/projects/parallax-jspdf)