jsPDF: four distribution builds, three runtime dependencies, and an html method that needs two more
Client-side JavaScript PDF generation for everyone.
At a glance
- What is it?
- jsPDF is an MIT licensed library that writes PDF files from JavaScript, with a Node build, an ES module build, a UMD build and a separate polyfill bundle in dist, with the package exports map choosing between the Node and ES builds. The cost of the design shows up in two places: the html method pulls in html2canvas at a release candidate, and Node file reads are denied by default so the recommended route is to hand the runtime a permission flag covering every dependency.
- Who is it for?
- jsPDF fits a browser application that needs to produce a PDF from data it already holds, on the client, without a server round trip, and it fits a Node script that writes a report file.
- 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 3 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 November 13, 2026, and from our analysis. They are not legal advice.
Star history
- parallax/jsPDF31,314 ★ · +18
| Repository | 2026-09-13 | 2026-11-13 |
|---|---|---|
| parallax/jsPDF | 31.3k | 31.3k |
18 Stars in the last 61 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The main field points at the Node build and the browser field at the ES one
One package serves a browser and a server, and the routing happens in package.json rather than in documentation prose. The main field is dist/jspdf.node.min.js, the module field is dist/jspdf.es.min.js, and the browser field points at that same ES build. An exports map repeats the decision with a types entry, a node entry, a browser entry and a default. The dist directory itself holds four kinds of file: the es variant in modern ES2015 module format, the node variant for running in Node which uses file operations for loading and saving instead of browser APIs, the umd variant for AMD or script tag loading, and the polyfills. The guidance is that you usually do not need to name the exact file, because build tools or Node figure out the right one and importing jspdf is enough. In practice that means require in Node silently loads the node build, and doc.save writes to the current working directory rather than to a browser download.
Three runtime dependencies, and a second tier that only loads on demand
The dependency list is short and each entry has an obvious job. The three runtime dependencies are the Babel runtime for its helpers, fflate, and fast-png. fflate is the compression layer, which matters because a PDF is largely streams of deflated data, and fast-png handles PNG encoding for images you embed. A second tier sits in optionalDependencies: canvg, core-js, dompurify and html2canvas. These are not linked into the main bundle, they are resolved at the moment a function needs them, using the respective module format and dynamic imports. The build itself is Rollup with two separate Babel configurations at the root, one plain and one for the ESM output, which is why the two module flavours can differ in more than just syntax. The practical consequence for a reader is that the size of the library you ship depends on which of the optional functions you call, and a bundler will not know that until it sees the call.
The html method needs html2canvas at a release candidate, plus dompurify for strings
HTML to PDF is the feature most people arrive for, and it is the one with the largest hidden cost. The html method depends on html2canvas and, when it is supplied with a string HTML document, on dompurify. Since these are optional dependencies loaded dynamically, build tools like Webpack create a separate chunk for each one. If your application uses none of them, you can stop Webpack generating the chunks by declaring them external, and the configuration example is a webpack externals block listing canvg, html2canvas and dompurify, with a comment that is really the important instruction: only define the dependencies you are NOT using as externals. Then the cost of that convenience lands on your framework. In Vue CLI you set it through configureWebpack or chainWebpack in a vue.config.js that has to be created first in a fresh project. In Angular it needs custom webpack builders. In React with create-react-app it needs react-app-rewired or ejecting. And html2canvas is pinned at a 1.0.0 release candidate, so the HTML path rests on a pre-final dependency.
Node file reads are denied by default, and the fix is a flag listing every import
This is the security design in the library, and it is stricter than most projects of this size. When running under Node.js, jsPDF restricts reading files from the local file system by default. The strongly recommended answer is not to loosen jsPDF but to let the Node runtime enforce the access.
node --permission --allow-fs-read=... ./scripts/generate.jsThe catch is stated immediately after: you need to include all imported JavaScript files, including all dependencies, in the allow-fs-read flag. So the permission list is transitive and has to be maintained as the dependency tree changes. The library's own fallback exists and is explicitly not recommended, which is setting jsPDF.allowFsRead in your script, an array of globs such as ./fonts/* alongside a single named file. The warning is explicit that the Node flags are preferred because they are enforced by the runtime and offer stronger security, which means the fallback is a convenience with a known weaker guarantee. Separately, the project strongly advises sanitising user input before passing it to jsPDF, and points to SECURITY.md for reporting a vulnerability.
The 14 standard PDF fonts stop at ASCII, so UTF-8 means embedding a TTF
The limitation that catches people in every language outside English is the font situation, and the cause is in the PDF format rather than in this library. The 14 standard fonts in PDF are limited to the ASCII codepage. If you want UTF-8 you have to integrate a custom font which provides the needed glyphs, and jsPDF supports ttf files. The failure mode is worth stating plainly because it does not look like an error. For Chinese text, for example, your font has to have the necessary Chinese glyphs, so you check whether the font supports the wanted glyphs, or else it will show garbled characters instead of the right text. The tool for the job is the project's own font converter, which lives in the fontconverter directory in this repository and is reachable as a page under the documentation site. The default page, for reference, is a4 in portrait using millimeters for units.
Polyfills are a separate import, and the prebundled file is discouraged
jsPDF requires modern browser APIs in order to function, which makes older browsers a configuration problem rather than a compatibility promise. For Internet Explorer and similar, polyfills are required, and they are loaded with their own import statement pointing at the ES polyfill file in dist. If you prefer the alternative, there is a prebundled polyfill file, and the project is direct about it: this is not recommended, since you might end up loading polyfills multiple times, though it might still be nifty for small applications or quick POCs. The difference between the two is the packaging. The es variant simply imports all required polyfills from core-js, so your bundler deduplicates them against anything else in your app that already depends on core-js, while the umd variant is self-contained and duplicates whatever is already in the page. The remaining install routes follow the same pattern of a supported path and a quick one, with a script tag pointing at the latest version on a CDN as the no-build option.
v4.2.1 is the newest release and the last push is six months behind it
The project is not archived and the last push landed on 2026-09-30, so jsPDF is actively maintained. The version picture is more interesting. The recent releases are v4.1.0 on 2026-02-02, v4.2.0 on 2026-02-19 and v4.2.1 on 2026-03-17, and package.json still reads 4.2.1. So the last commit is roughly six months newer than the last published version, and that gap is visible to anyone installing. A normal npm install gives you 4.2.1, and the script tag route that points at the latest version on a CDN gives you the same one, because latest means the newest published version rather than the tip of master. Maintenance is a shared arrangement rather than a foundation: the original author links his own account and consultancy site, and the project states that jsPDF is now co-maintained by yWorks. The root still carries bower.json alongside the modern tooling, a cli.js, and both RELEASE.md and a file named HOTFIX_README.md.
Editorial conclusion
jsPDF fits a browser application that needs to produce a PDF from data it already holds, on the client, without a server round trip, and it fits a Node script that writes a report file. It does not fit a team that needs arbitrary Unicode text without doing font work first, since the standard PDF fonts stop at ASCII, and it does not fit a build pipeline that refuses to be configured, because every optional dependency you do not use has to be declared external in whatever bundler you happen to have. Verify three things before you commit: that the html2canvas release candidate behind the html method meets your bar, that the Node permission flag you write lists every transitively imported file, and that the version you install from npm matches the 4.2.1 line, since master has moved on since that release.
Frequently asked questions
What is a jsPDF?
jsPDF is a library to generate PDFs in JavaScript, and the repository describes it as client side PDF generation. It is MIT licensed, is co-maintained by yWorks, and by default a new document is a4, portrait, with coordinates in millimeters. It ships separate ES module, Node, UMD and polyfill builds, and a typings file for TypeScript.
How do I install jsPDF?
The recommended route is npm, with npm install jspdf --save, or yarn add jspdf. For a page with no build step you can use a script tag pointing at the latest version on unpkg. On Meteor the project documents meteor add jspdf:core. Importing jspdf is enough in each case, because the package exports map selects the ES build for browsers and the Node build for Node.
How do I use jsPDF to convert HTML to PDF?
The html method is the route, and it depends on two optional dependencies: html2canvas always, and dompurify when you pass it a string HTML document. They are loaded dynamically, so a bundler such as Webpack will create a chunk for each, and you can declare the ones you do not use as externals. The project also strongly advises sanitising user input before passing it to jsPDF.
How do I use jsPDF in React?
jsPDF imports like any other third party library, so a plain import is enough, and a typings file is provided for TypeScript. The complication is build configuration for the optional dependencies. In React projects created with create-react-app, externals can be defined either by using react-app-rewired or by ejecting, since the default build gives you no way to declare them.
Official sources
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.
[](https://hysenlabs.com/projects/parallax-jspdf)Star history chart for your README
[](https://hysenlabs.com/projects/parallax-jspdf)Was this useful?