Library / SDK
yWorks/svg2pdf.js avatar
yWorks/svg2pdf.js

svg2pdf.js converts SVG to PDF in the browser and tells you not to feed it user input

A javascript-only SVG to PDF conversion utility that runs in the browser. Brought to you by yWorks - the diagramming experts

839 stars120 forksTypeScriptMIT

At a glance

What is it?
svg2pdf.js is a TypeScript library from yWorks that renders SVG into a PDF through jsPDF entirely client side, with no server round trip. It supports only part of the SVG specification, needs a real DOM so it will not run under JSDOM, and its own documentation insists you sanitise any SVG a user supplied before passing it in.
Who is it for?
svg2pdf.js fits a web application that already has an SVG on the page and wants to offer a download without a rendering service, such as a diagramming product exporting a diagram the user is looking at, since the conversion happens in the browser and the output goes straight to a 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 6 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

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

Editorial analysis

The conversion happens where the SVG already is

svg2pdf.js is a JavaScript-only utility for converting SVG to PDF in the browser using jsPDF, and the repository description calls it a diagramming utility brought to you by yWorks.

The architectural decision is the interesting one. There is no server component, no headless browser on the backend and no conversion service to run. The SVG is already in the document, the PDF library is already in the page, and the conversion happens where the user is looking at the diagram. For a product whose main artefact is a diagram, that removes an entire category of infrastructure: no rendering farm, no font installation on a server, no queue.

The package metadata reflects the modern packaging conventions. The type is module, the main entry is the UMD minified build at dist/svg2pdf.umd.min.js, the module and browser fields point at the ES build at dist/svg2pdf.es.min.js, and the types are in types.d.ts, which the README also points to for detailed documentation of the API. The published files are the dist directory, the type declarations, the README and the LICENSE.

The version is 2.8.1, with v2.8.0 and v2.8.1 both released in late August 2026 and v2.7.0 in January 2026. The last push to the repository was on 2026-10-18, so the work is current.

The API is a jsPDF method with an element and a box

The usage example is short enough to read in one go, and it shows the shape of the integration.

js
import { jsPDF } from 'jspdf'
import 'svg2pdf.js'

const doc = new jsPDF(width > height ? 'l' : 'p', 'pt', [width, height])

const element = document.getElementById('svg')
await doc.svg(element, {
  x,
  y,
  width,
  height
})

// save the created pdf
doc.save('myPDF.pdf')

The library is a side effect import that augments jsPDF with an svg method. The document is created in the orientation that matches the aspect ratio, in points, at the size of the drawing. The call is asynchronous, so it is awaited, and it takes the DOM element plus a box, which is how the SVG is placed on the page.

The save call then hands the file to the browser as a download.

That is the whole interface for the common case, and the fact that the method hangs off jsPDF rather than being a separate converter is what makes the composition work. A page with a title, a diagram and a footer is built with the same jsPDF calls you would use without svg2pdf.js, and the SVG is simply one more element to place.

The package also ships a playground for trying this out, and the repository contains a playground/ directory and an index.html at the root.

Fonts have to be registered before the conversion runs

There is a short section on custom fonts and non-ASCII characters, and it is the kind of thing that would otherwise cost an afternoon.

If you want to use fonts or characters beyond the basic set, you must add them before calling svg2pdf. The README defers to the jsPDF README for the instructions, which is a sensible division of responsibility, since the font machinery is jsPDF's and the SVG layer sits on top of it.

The order matters. A font added after the conversion has already run will not retroactively change the text in the document, so a pipeline that converts a diagram and then registers a font is a pipeline that produces PDFs with substituted glyphs.

This is also where the dependency list becomes relevant. The runtime dependencies are cssesc, font-family-papandreou, specificity and svgpath, alongside jsPDF itself. The font-family-papandreou package is the one that maps CSS font family names to actual font files, and specificity deals with the CSS cascade so that the computed style of an element is the style the renderer sees. svgpath is the path manipulation library that the SVG handling is built on.

In other words, the library does not just read the SVG markup. It computes styles, resolves fonts and transforms geometry, which is why it needs a real browser-like environment to do it.

The security section says more than the feature list

The Purpose and Security section is the most important paragraph in the README, and it is worth reading twice.

The library is intended to convert carefully curated SVG images to PDF. It supports only a limited part of the SVG specification and cannot convert arbitrary user-provided SVGs. It requires a fully functional DOM implementation and does not work with JSDOM. It is designed to run client-side in the user's browser.

The library can also run in a headless browser on the backend, but the README says plainly that it cannot guarantee security in that setting. The instruction is to always sanitise any user-provided SVG, including user-provided fragments, before passing it to the library, and to properly sandbox its execution.

That is an unusual thing to find in a README, and it is the correct thing to find. An SVG parser that reads a document, resolves styles and consults fonts is a parser, and parsers of untrusted markup are where the interesting failures live. The library is telling you that its own protections are not the thing standing between a hostile SVG and your server.

The second constraint, that it does not work with JSDOM, follows from the same design. A fully functional DOM implementation is needed, which in practice means a real browser, headless or not. If your server side pipeline is built on JSDOM, this library is not going to work there, and the README says so rather than leaving you to discover it.

Snapshot testing of generated PDFs, and the local machine problem

The testing section describes an approach that is unusual enough to be worth explaining.

Tests are located in the tests folder, and most of them compare generated PDFs with snapshots. Updating the existing snapshots is done with npm run test:update, and the README asks you to carefully review the updated PDFs afterwards.

The awkward part is stated plainly. Some tests may fail on your local machine because of differences in text measurement. If you are contributing a pull request and need to update the snapshots, the recommended path is to download the relevant artifact from the CI build job on GitHub and commit it in a subsequent commit.

That is a sensible workflow, and it says something about the problem domain. Text measurement depends on the font files and the rendering environment, so a PDF produced on one machine is not byte identical to one produced on another. Snapshot testing a document format is therefore fragile by nature, and the project's answer is to treat the CI artifact as the source of truth rather than the developer's laptop.

The tooling around it is current. Tests run on vitest, with a browser mode, and playwright install is a separate script, so the browser used for the tests is pinned by the project rather than by whatever is on your machine. The package scripts also include a createreferences entry that runs a reference server script from the test folder, and the linting and formatting use oxlint and oxfmt with their own config files, rather than the eslint and prettier combination the older versions used.

The dist caveat that bites when you point npm at git

There is a warning in the installation section that is easy to skim past and expensive to debug.

If you want to use a development version from the repository, note that the files in dist may reflect the latest release rather than the current source. A simple package.json dependency pointing to a branch or revision may therefore fail, and the README points at issue 102 for details.

The cause is the release process. The version script runs the build and stages the dist directory into git, so the committed dist files are snapshots of the last release, not of the current working tree. A dependency that resolves to a branch gets those stale artefacts, and if the source in that branch has changed shape since the last release, the installed files no longer match what the source would build.

For a consumer, the practical rule is simple. Install the published version from npm, which is what the install command gives you.

bash
npm install svg2pdf.js jspdf

For a contributor, build before you test, which is what the build script is for.

bash
npm run build

The build is a rollup invocation with the config in rollup.config.mjs, and the rollup plugins in the devDependencies cover the commonjs and node-resolve resolution, terser for minification and the TypeScript plugin for the source itself. There is a separate typecheck script that runs tsc with no emit, so type errors are caught without producing files.

Where it fits, and where a different route does

The tool is at its best in a specific place. A web application that already draws an SVG in the page, for example a diagram editor, a chart or a generated report, and wants to offer a PDF download of exactly what the user sees, gets a client side implementation with no server component and no round trip. The diagram does not have to be re-rendered or re-laid-out on a server, so what lands in the PDF matches the screen.

That is also where its limits bite. The library supports only a limited part of the SVG specification, so an SVG using features outside that subset will convert partially or not at all, and the failure may be silent, which is a poor property for a download button. And because it needs a fully functional DOM, it cannot run in a JSDOM based server pipeline, so a Node service that wants to produce PDFs from stored SVG markup needs a real browser, whether headless or not.

The alternative route in that situation is a server side rendering pipeline. A headless browser loads the SVG and prints to PDF, or a dedicated SVG to PDF renderer handles the file. The difference in approach is that the server side route puts the conversion in a sandbox you control, it can handle the full specification, and it does not require the user to have a capable browser, at the cost of infrastructure and of a network round trip.

The security note is what decides between them for anyone dealing with other people's markup. If the SVG is curated and comes from your own code, the browser side library is the better fit. If it can be influenced by a user, the README's own instruction to sanitise and sandbox applies, and a server side pipeline you own is the more defensible design.

Editorial conclusion

svg2pdf.js fits a web application that already has an SVG on the page and wants to offer a download without a rendering service, such as a diagramming product exporting a diagram the user is looking at, since the conversion happens in the browser and the output goes straight to a file. It is the wrong choice for untrusted SVG, and the README says so directly, and it is the wrong choice in a server side JSDOM environment because it requires a fully functional DOM implementation. Before adopting it, read the Purpose and Security section, register any non standard fonts with jsPDF before calling svg, and verify the snapshot tests on your own machines, because text measurement differences are known to cause local failures.

Frequently asked questions

How do I install svg2pdf.js?

Run npm install svg2pdf.js jspdf, since the library works by augmenting jsPDF with an svg method. The README warns that pointing a dependency at a branch or revision of the repository may fail, because the committed files in dist can reflect the latest release rather than the current source.

Can svg2pdf.js convert any SVG file?

No. The README states that the library is intended to convert carefully curated SVG images, supports only a limited part of the SVG specification, and cannot convert arbitrary user-provided SVGs. If you need that, sanitise the SVG and sandbox its execution, as the README instructs.

Does svg2pdf.js work in Node.js with JSDOM?

No. The README says it requires a fully functional DOM implementation and does not work with JSDOM. It is designed to run client-side in the browser, although it can also run in a headless browser on the backend, where the README says it cannot guarantee security.

How do I use a custom font with svg2pdf.js?

Fonts and characters beyond the basic set must be added before calling svg2pdf, and the README points to the jsPDF README for the instructions. Adding a font after the conversion has run will not change the text already in the document.

How are the svg2pdf.js tests run and updated?

Run npm test, which uses vitest, and the tests live in the tests folder with most comparing generated PDFs against snapshots. Update snapshots with npm run test:update and review the changed PDFs, and note that some tests can fail locally because of differences in text measurement, in which case the CI artifact should be committed instead.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. yWorks/svg2pdf.js on GitHub
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/yworks-svg2pdf-js.svg)](https://hysenlabs.com/projects/yworks-svg2pdf-js)

Was this useful?