How to convert HTML to PDF in JavaScript

Nowadays, you have various options to generate PDFs from HTML or any given URL: generating PDF in the browser, on the server-side (Node.js), or even using a modern and friendly API to generate PDF.

4 min read

Written by

Dmytro Krasun

Published on

But only you who know your context and requirements can decide the best options for you. But let me guide you through existing solutions and describe their pros and cons.

Using html2canvas and jsPDF

You can use a combination of html2canvas and jsPDF libraries to generate PDF from HTML right away from the browser. Let’s do it first and then quickly discuss the pros and cons of generating PDFs in the browser.

Let’s install the necessary libraries first:

Terminal window
npm install jspdf dompurify html2canvas --save

And then generate a PDF document from simple HTML:

src/index.js
import { jsPDF } from "jspdf";
function generateAndDownload() {
const doc = new jsPDF();
doc.html("<h1>Hello, world</h1><h2>Peace and love to everybody.</h2>", {
callback: function (doc) {
doc.save();
}
});
}
window.addEventListener('DOMContentLoaded', () => {
document.getElementById('generate').addEventListener('click', () => {
generateAndDownload();
});
});

To make it work, use the following webpack.config.js:

const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
}
};

And UI:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<button id="generate">Generated and download a document</button>
<script src="dist/bundle.js"></script>
</body>
</html>

And the result is a PDF document.

Pros and cons:

  1. Rendering PDF in the browser saves computation resources for your servers. But it uses your users’ computational resources, and they might have unpleasant experiences after using your application.

  2. Each browser version is different, and the html2canvas library might produce various rendering artifacts. You don’t have control over what your potential users see. Hence, it would help if you considered this when rendering HTML on the client.

  3. It is not easy to render HTML from a URL. You can’t fetch any URL in the browser due to security reasons. So you need to prepare your HTML in advance or use some proxy.

But there is a solution to avoid the pitfalls of rendering PDFs on the client side.

Using Puppeteer

To ensure that PDFs are rendered as you expect for every user, you can use Puppeteer on the server side. Puppeteer is a browser automation library written for headless browsers that support Chrome DevTools Protocol.

Install Puppeteer:

Terminal window
npm i puppeteer

And then:

const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 1024 });
await page.goto('https://example.com/', { waitUntil: ['load', 'domcontentloaded', 'networkidle0'] });
await page.pdf({ type: 'png', path: 'example.pdf' });
} catch (e) {
console.log(e)
} finally {
await browser.close();
}
})();

And the result is a PDF document.

Pros and cons of using Puppeteer for rendering PDFs:

  1. I would love to repeat that, but the massive benefit of using Puppeteer is having fine-grained control over rendering results against rendering PDFs only in the browser.

  2. Managing headless browsers is a huge pain. The browsers might have memory leaks and suddenly restarts. You need to update them to the latest versions. And this is only a small list of problems that you will encounter.

  3. Puppeteer is imperfect, and the rendering PDF has different artifacts that must be addressed.

  4. It is a computation-heavy task for servers. And scaling it for running multiple browsers can be a problem in itself.

But there is a solution to address mentioned Puppeteer issues.

Using modern and scalable URL or HTML to PDF API

If you don’t want to deal with all the burdens of managing headless browsers, you can use ScreenshotOne API to render PDFs from HTML or any URL. It is a free PDF to HTML API for up to 100 requests. The PDF generation API from ScreenshotOne is easy to use. It is scalable, covers a variety of use cases, and solves all the issues related to rendering PDFs in headless browsers.

Let’s take a look at how easy it is to render a PDF with a straightforward call:

https://api.screenshotone.com/take?url=https://example.com&format=pdf&access_key=<your access key>

And the result is a PDF document.

Summary

If you do not want to make your backend more complex, render PDFs using html2canvas and jsPDF.

If you need scaling and want to ensure that PDFs are rendered the same way for any of your users, go with the Puppeteer library.

But if you don’t want to manage headless browsers and issues when rendering PDFs, feel free to use and sign up for ScreenshotOne HTML or URL to PDF API.

  1. A complete guide on how to take screenshots with Puppeteer.

  2. How to take website screenshots with JavaScript or TypeScript (Node.js).

Read more posts

Interviews, tips, guides, industry best practices, and news.

View all posts

Open Graph images

You can control the preview image rendered when your site is shared on social media, messengers, or apps that support the Open Graph protocol.

Read more

A friendly guide on how to render HTML or site screenshots in Google Sheets in less than 10 minutes

It is not the first time that one of the ScreenshotOne users asked how to render screenshots in Google Sheets. I wrote a simple but complete tutorial once and for all.

Read more

A Simple Website Screenshot Tool by ScreenshotOne

A few words about why to launch yet another website screenshotting tool.

Read more

Automate website screenshots

Exhaustive documentation, ready SDKs, no-code tools, and other automation to help you render website screenshots and outsource all the boring work related to that to us.