Top JavaScript libraries for converting HTML to PDF
This article was first published in March 2019 and was updated in November 2024.
Converting HTML to PDF is a common requirement for web developers, whether it’s for invoices, tickets, or reports. The versatility and reliability of the Portable Document Format (PDF) make it an essential tool for sharing documents while maintaining formatting across various devices. This post will explore the top three JavaScript libraries for HTML-to-PDF conversion: html2pdf, pdfmake, and Playwright. It’ll discuss their features, pros, and cons, and help you decide which library is the best fit for your needs.
1. Convert HTML to PDF using html2pdf
The html2pdf library converts HTML pages to PDFs in the browser. It uses html2canvas
and jsPDF
under the hood. html2canvas
renders an HTML page into a canvas element and turns it into a static image. jsPDF
then takes the image and converts it to a PDF file.
Check out How to Convert HTML to PDF Using React for a step-by-step guide on how to use jsPDF
in a React app.
Installation
To get started, install the html2pdf
library.
Using the CDN Link for html2pdf
The library provides a CDN link. If you prefer this method, add a script
tag to your HTML file:
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js" integrity="sha512-GsLlZN/3F2ErC5ifS5QtgpiJtWd43JWSuIgh7mbzZ8zBps+dvLusV+eNQATqgA/HdeKFVgA5v3S/cIrLF7QnIg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Installing via npm
Alternatively, download the package from npm:
npm install html2pdf.js
Downloading the library manually
You can also download the bundled html2pdf JavaScript library directly from the html2pdf.js GitHub repository.
After you’ve downloaded the library, add a script
tag to your HTML file:
<script src="html2pdf.bundle.min.js"></script>
Using html2pdf to generate PDFs
To begin, define a generatePDF()
function that will get the element you want to download as a PDF from your HTML files. Then, call html2pdf
with that element to download it directly on your users’ client. Next, call this function in a download button:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>HTML-to-PDF Example</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <!-- html2pdf CDN link --> <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js" integrity="sha512-GsLlZN/3F2ErC5ifS5QtgpiJtWd43JWSuIgh7mbzZ8zBps+dvLusV+eNQATqgA/HdeKFVgA5v3S/cIrLF7QnIg==" crossorigin="anonymous" referrerpolicy="no-referrer" ></script> </head> <body> <button id="download-button">Download as PDF</button> <div id="invoice"> <h1>Our Invoice</h1> </div> <script> const button = document.getElementById('download-button'); function generatePDF() { // Choose the element that your content will be rendered to. const element = document.getElementById('invoice'); // Choose the element and save the PDF for your user. html2pdf().from(element).save(); } button.addEventListener('click', generatePDF); </script> </body> </html>
In the example above, you only rendered the h1
title. However, you can render any HTML element, including images and tables. In the next example, you’ll use a more complex HTML structure.
Downloading an invoice as a PDF
We provided an invoice template to download as a PDF. You can download it by clicking this link. You can also generate the HTML for your own invoice on your backend if you prefer.
Similar to the example above, you’ll use the generatePDF()
function to download the invoice as a PDF. However, this time, you’ll render the invoice template to the div
element.
The end result will look like what’s shown below.
2. Convert HTML to PDF using pdfmake
The pdfmake library generates PDF documents directly in the browser. It uses a layout and style configuration defined in a JSON-like structure within JavaScript, leveraging pdfkit under the hood for PDF generation.
While html2pdf converts rendered HTML directly into a static image that’s later converted to a PDF file, retaining the layout and styles of the webpage, the text content becomes unselectable. Meanwhile, pdfmake requires explicitly defining the document’s structure and styles in JavaScript, offering more precise control over the PDF output. The biggest advantage of pdfmake is that the generated text content can be selected and copied, making it a better option when text selection is important.
Installation
To get started, install the pdfmake library.
Adding pdfmake via CDN
The library provides a CDN link. If you prefer this method, add a script
tag to your HTML file:
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.72/pdfmake.min.js" integrity="sha384-qwfyMhpwB4dOhtxItT9bxl/sd7WQ95MvXSyLUgVz3oNRlvK/Ea7uT4O3rf1ZriyH" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.72/vfs_fonts.js" integrity="sha384-vD7JPR0c5DJMoqHXO7lJKsK9k6XPlL4LMoGK1jHsGBWoDzW9BGfaP7UWKIXHdz7L" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Installing pdfmake via npm
Alternatively, download the package from npm:
npm install pdfmake
Generating PDFs with pdfmake
To begin, define a generatePDF()
function that will be used to specify the document configuration using a structured JavaScript object. Then, use pdfmake to generate and download the PDF based on this configuration. Next, associate this function with a download button in index.html
:
<!--index.html--> <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>HTML-to-PDF PDFMake Example</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <!-- pdfmake CDN link --> <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.72/pdfmake.min.js" crossorigin="anonymous" referrerpolicy="no-referrer" ></script> <!--vfs_fonts.js is essential for embedding fonts into PDF documents created with pdfmake--> <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.72/vfs_fonts.js" crossorigin="anonymous" referrerpolicy="no-referrer" ></script> </head> <body> <button onclick="generatePDF()">Generate Invoice PDF</button> <script> const button = document.getElementById('download-button'); function generatePDF() { const docDefinition = { content: [ { columns: [ { text: '&', style: 'logo', }, { stack: [ { text: 'Company', style: 'companyName' }, { text: '[COMPANY INFO]', style: 'companyInfo', }, ], alignment: 'right', }, ], margin: [0, 20, 0, 30], }, { canvas: [ { type: 'line', x1: 0, y1: 5, x2: 515, y2: 5, lineWidth: 2.5, lineColor: 'black', }, ], margin: [0, 10, 0, 20], }, { columns: [ { text: [ { text: 'Billed To:\n', style: 'billedToLabel', }, { text: 'Company Ltd.\n', style: 'billedTo', }, { text: 'Address\nCountry\nVAT ID: ATU12345678\n', style: 'billedTo', }, ], width: '60%', }, { text: [ { text: 'Invoice #\n', style: 'invoiceLabel', }, { text: '123456\n', style: 'invoiceNumber', }, { text: 'Payment Date:\n', style: 'invoiceLabel', }, { text: 'November 22nd 2021\n', style: 'invoiceDate', }, { text: 'Payment Method:\n', style: 'invoiceLabel', }, { text: 'Bank Transfer', style: 'paymentMethod', }, ], alignment: 'right', width: '40%', }, ], margin: [0, 10, 0, 20], }, { style: 'itemsTable', table: { widths: ['*', 75, 100, 100], headerRows: 1, body: [ [ { text: 'Description', style: 'tableHeader', }, { text: 'QTY', style: 'tableHeader' }, { text: 'Unit Price', style: 'tableHeader', }, { text: 'Total', style: 'tableHeader' }, ], ['Product 1', '2', '$10.00', '$20.00'], ['Product 2', '5', '$15.00', '$75.00'], ['Product 3', '1', '$25.00', '$25.00'], [ { text: 'Total', colSpan: 3, alignment: 'right', style: 'totalLabel', }, {}, {}, '$120.00', ], ], }, layout: 'lightHorizontalLines', }, ], styles: { logo: { fontSize: 30, bold: true, color: '#4736e7' }, companyName: { fontSize: 16, bold: true, color: '#333333', }, companyInfo: { fontSize: 10, color: '#555555' }, billedToLabel: { bold: true, fontSize: 12, color: '#333333', }, billedTo: { fontSize: 10, color: '#555555', lineHeight: 1.5, }, invoiceLabel: { fontSize: 10, bold: true, color: '#333333', }, invoiceNumber: { fontSize: 10, color: '#555555' }, invoiceDate: { fontSize: 10, color: '#555555' }, paymentMethod: { fontSize: 10, color: '#555555' }, tableHeader: { bold: true, fontSize: 10, color: 'black', }, totalLabel: { bold: true, fontSize: 10 }, }, defaultStyle: { columnGap: 20, }, }; pdfMake .createPdf(docDefinition) .download('styled-invoice.pdf'); } button.addEventListener('click', generatePDF); </script> </body> </html>
In the example above, the document configuration includes simple text and a line element. However, you can define a wide range of elements in your PDFs with pdfmake, including tables, lists, images, and styled text. In the next example, you’ll see how to configure a more complex document layout using pdfmake’s powerful styling and layout options.
You can test the example by running:
npx serve -l 4111 .
3. Convert HTML to PDF using Playwright
Playwright is a framework that provides an API to control headless Chrome, Firefox, and WebKit browsers with a single API, allowing you to convert web pages into PDFs. This allows you to automate nearly all tasks that can be done manually in a browser, including generating PDFs from web content. The difference between Playwright and html2pdf is that you need to run Playwright on your server and serve the PDF to your users.
Installing Playwright
For the Playwright example, you’ll build a small Node.js server and serve your user a PDF that gets downloaded.
-
Begin by creating a new Node project:
mkdir playwright-pdf-generation && cd playwright-pdf-generation npm init --yes
-
After initializing the Node project, you’ll have a
package.json
file in your directory. Now it’s time to add Playwright to your project as a dependency:
npm install playwright
-
Your
package.json
file will look similar to this:
{ "name": "playwright-pdf-generation", "version": "1.0.0", "description": "Example of how to generate a PDF with Playwright", "main": "index.js", "license": "MIT", "private": false, "dependencies": { "playwright": "^1.46.0" } }
Generating PDFs with Playwright
Before you start, make sure you have the latest version of Playwright installed. If you don’t, you can update it by running:
npx playwright install
You’ll now create an index.js
file where you’ll require Playwright, launch a new browser session, go to your invoice page, and save the PDF file:
// index.js // Require Playwright. const { chromium } = require('playwright'); (async function () { try { // Launch a new browser session. const browser = await chromium.launch(); // Open a new page. const page = await browser.newPage(); // Set the page content. await page.setContent('<h1>Our Invoice</h1>'); // Generate PDF and store in a file named `invoice.pdf`. await page.pdf({ path: 'invoice.pdf', format: 'A4' }); await browser.close(); } catch (e) { console.error(e); } })();
When you now run the script via node index.js
, you’ll see a nicely generated PDF with the name invoice.pdf
in your directory.
However, what you actually want is to serve your users a PDF when they click a download button. For this, you’ll use the http
module from Node and respond with the invoice PDF when a user goes to your page on localhost:3000
.
First, you need to integrate the http
module in your script. The server will listen for requests on the /generate-pdf
endpoint, and when accessed, it initializes Playwright’s Chromium to open a new page and set the content. Instead of writing to a file when creating the PDF, you’ll serve the buffer that’s returned from page.pdf
directly by omitting the path
option in the page.pdf()
method. The server then sets the HTTP headers to application/pdf
and sends the buffer directly to the client, ensuring the browser interprets it as a PDF file.
For non-PDF requests, provide a basic HTML page with instructions to navigate to the PDF generation endpoint:
// index.js const { chromium } = require('playwright'); const http = require('http'); // Create an instance of the HTTP server to handle the request. http .createServer(async (req, res) => { if (req.url === '/generate-pdf') { // Making sure to handle a specific endpoint. const browser = await chromium.launch(); const page = await browser.newPage(); // Set the content directly or navigate to an existing page. await page.setContent(` <!DOCTYPE html> <html> <head> <title>Invoice</title> </head> <body> <h1>Our Invoice</h1> <p>Details about the invoice...</p> </body> </html> `); // By removing the `path` option, you'll receive a `Buffer` from `page.pdf`. const buffer = await page.pdf({ format: 'A4' }); await browser.close(); // Set the content type so the browser knows how to handle the response. res.writeHead(200, { 'Content-Type': 'application/pdf' }); res.end(buffer); } else { // Respond with a simple instruction page. res.writeHead(200, { 'Content-Type': 'text/html' }); res.end( '<h1>Welcome</h1><p>To generate a PDF, go to <a href="/generate-pdf">/generate-pdf</a>.</p>', ); } }) .listen(3000, () => { console.log('Server is running on http://localhost:3000'); });
Open localhost:3000
in your browser, and you’ll see the instruction page. You can then navigate to /generate-pdf
to open the PDF with the invoice.
Advantages and disadvantages
html2pdf
-
Advantages:
-
Very easy to generate a PDF from HTML on the client-side, requiring no server.
-
-
Disadvantages:
-
Generates PDFs by taking screenshots of the webpage, resulting in blurry text when zoomed in or on high-resolution displays.
-
Using PNGs instead of JPEGs can significantly increase PDF size (e.g. 28 MB for PNG vs. 280 KB for JPEG).
-
To improve the quality, you can increase the resolution by adjusting the html2pdf
settings:
function generatePDF() { // Choose the element that your invoice is rendered in. const element = document.getElementById('invoice'); // Choose the element and save the PDF for your user. html2pdf() .set({ html2canvas: { scale: 4 } }) .from(element) .save(); }
pdfmake
-
Advantages:
-
Allows for creating PDFs programmatically with precise layout control.
-
Text within the PDF is selectable and searchable, enhancing usability for professional documents.
-
-
Disadvantages:
-
Requires manual customization for complex documents.
-
Playwright
-
Advantages:
-
Creates PDFs with actual text content, ensuring sharpness and selectable text, resulting in lower file sizes.
-
Supports server-side rendering for high-quality, complex PDFs.
-
-
Disadvantages:
-
Requires running a server instead of generating PDFs on the client.
-
Comparative analysis
To help you choose the best library for your needs, here’s a comparison table summarizing the key features, pros, and cons of each library:
Feature/criteria | html2pdf | pdfmake | Playwright |
---|---|---|---|
Ease of use | Very easy | Moderate | Moderate |
Installation | Simple (CDN, npm) | Simple (CDN, npm) | Simple (npm) |
Dependencies | html2canvas, jsPDF | pdfkit | Browser automation library |
PDF quality | Moderate | High | High |
Server-side rendering | No | No | Yes |
Customization | Limited | High | High |
Text selection | No | Yes | Yes |
Image handling | Good | Good | Excellent |
Performance | Good (client-side) | Good (client-side) | High (server-side) |
Use case examples | Certificates, invoices | Business reports, invoices | Invoices, automated testing |
Pros | Easy to use, No server needed | Highly customizable, No dependencies | Server-side rendering, High quality |
Cons | Blurry PDFs, non-selectable text | Requires manual customization | Requires server-side setup |
By comparing these features, you can better decide which library suits your specific project requirements:
-
Client-side applications — If you need a quick and easy solution without server-side setup, html2pdf is user-friendly and easy to implement quickly.
-
Customizable and high-quality PDFs — For greater customization and higher quality, pdfmake is a robust choice.
-
Server-side rendering and complex PDFs — For high performance and the ability to handle complex PDFs, Playwright is ideal, though it requires a server setup.
The information you provided about best practices for converting HTML to PDF is largely accurate and provides a solid foundation for ensuring high-quality PDF outputs. Here’s a refined version with some enhancements and additional context:
Best Practices for PDF Conversion
When converting HTML to PDF, adhering to best practices ensures that the resulting document is of high quality and meets specific needs. Here are some essential tips to consider:
-
Use a Clear and Concise Template:
-
Start with a well-structured HTML template that is easy to read and understand. A simple and organized design will translate better into PDF format. Avoid overly complex layouts or cramming too much content onto a single page, as this can lead to formatting issues and reduced readability.
-
Optimize Images and Fonts:
-
Ensure that all images and fonts used in your HTML document are optimized for the PDF format. Use high-resolution images to maintain visual quality and select fonts that are widely supported in PDF standards. Embedding fonts can prevent rendering issues and ensure text displays as intended across different devices.
-
Use a Consistent Layout:
-
Maintain a consistent layout throughout your HTML document. Consistency in design and formatting, including margins, font sizes, and color schemes, makes the resulting PDF document more professional and easier to read. Avoid switching layouts or styles between different sections or pages, which can create confusion for readers.
-
Test and Validate:
-
Before finalizing your PDF document, thoroughly test and validate it. Use tools like Adobe Acrobat or PDF validators to check for errors, ensure that links work correctly, and verify compatibility across different devices and platforms. This step is crucial for ensuring that your PDF documents are accessible and functional for all users.
-
Use JavaScript Libraries:
-
Leverage JavaScript libraries such as
jsPDF
,html2pdf
, orpdfmake
to streamline the PDF generation process. These libraries offer a range of features and customization options, making it easier to convert HTML to PDF efficiently. They support various elements like images, tables, and styled text, enhancing the overall quality of your PDFs. Ensure you choose a library that aligns with your specific requirements for features and ease of use.
-
Consider Accessibility:
-
Pay attention to accessibility standards when designing your HTML document. Use semantic HTML elements, provide alternative text for images, and ensure that text contrasts well with the background. Creating accessible PDFs is essential for reaching a wider audience, including individuals with disabilities.
-
Manage Page Breaks:
-
Be mindful of how page breaks will be handled during conversion. Use CSS properties like
page-break-before
andpage-break-after
to control content flow and avoid awkward splits in the middle of sentences or images.
By following these best practices, you can generate high-quality PDF documents that are professional, readable, and compatible with various devices and platforms. These steps will help ensure that your final product meets both aesthetic and functional expectations.
Conclusion
For quick client-side PDF generation, html2pdf is a suitable choice. However, due to potential issues with file size and image quality, Playwright is recommended for server-side implementations to produce high-quality PDFs.
And if you want to save time with an out-of-the-box solution, make sure to check out PDF Generation for Document Engine, which offers support for:
-
Forms — HTML forms and inputs will be converted to fillable PDF forms, which currently isn’t possible with Playwright.
-
An HTTP API — Document Engine can be controlled via an HTTP API with a flexible authentication/authorization mechanism, making it suitable for both backend and frontend use.
-
Extensible workflows — You can combine PDF generation with other operations. For example, you can generate a document, prepend a predefined introduction page, and watermark all pages in a single API request.
Document Engine combines PDF generation with powerful document operations that can streamline repetitive tasks such as merging and watermarking. Test it yourself with our free trial.
FAQ
Here are a few frequently asked questions about converting HTML to PDF in JavaScript.
What is the main advantage of using html2pdf?
html2pdf is user-friendly and allows you to generate PDFs directly on the client side without requiring a server.
What are the drawbacks of using html2pdf?
The primary drawback is that it generates PDFs as images, which can result in blurry text and larger file sizes, especially when using PNGs.
What makes pdfmake a strong option for generating PDFs?
pdfmake allows for highly customizable and high-quality PDFs with selectable and searchable text, making it suitable for professional documents.
Why should I consider using Playwright for PDF generation?
Playwright is ideal for server-side rendering, producing high-quality PDFs with selectable text and smaller file sizes. It is particularly useful for complex PDFs and automated testing.
Which library should I use for client-side applications?
For quick and easy client-side PDF generation, html2pdf is a suitable choice.