HTML to PDF or image (jpeg, png, webp) converter via Chrome/Chromium.
npm install --save html-pdf-chrome
This library is NOT meant to accept untrusted user input. Doing so may have serious security risks such as Server-Side Request Forgery (SSRF).
If you run into CORS issues, try using the --disable-web-security
Chrome flag, either when you start Chrome externally, or in options.chromeFlags
. This option should only be used if you fully trust the code you are executing during a print job!
Note: It is strongly recommended that you keep Chrome running side-by-side with Node.js. There is significant overhead starting up Chrome for each PDF generation which can be easily avoided.
It's suggested to use pm2 to ensure Chrome continues to run. If it crashes, it will restart automatically.
As of this writing, headless Chrome uses about 65mb of RAM while idle.
# install pm2 globally
npm install -g pm2
# start Chrome and be sure to specify a port to use in the html-pdf-chrome options.
pm2 start google-chrome \
--interpreter none \
-- \
--headless \
--disable-gpu \
--disable-translate \
--disable-extensions \
--disable-background-networking \
--safebrowsing-disable-auto-update \
--disable-sync \
--metrics-recording-only \
--disable-default-apps \
--no-first-run \
--mute-audio \
--hide-scrollbars \
--remote-debugging-port=<port goes here>
# run your Node.js app.
TypeScript:
import * as htmlPdf from 'html-pdf-chrome';
const html = '<p>Hello, world!</p>';
const options: htmlPdf.CreateOptions = {
port: 9222, // port Chrome is listening on
};
// async
const pdf = await htmlPdf.create(html, options);
await pdf.toFile('test.pdf');
const base64 = pdf.toBase64();
const buffer = pdf.toBuffer();
const stream = pdf.toStream();
// Promise
htmlPdf.create(html, options).then((pdf) => pdf.toFile('test.pdf'));
htmlPdf.create(html, options).then((pdf) => pdf.toBase64());
htmlPdf.create(html, options).then((pdf) => pdf.toBuffer());
htmlPdf.create(html, options).then((pdf) => pdf.toStream());
JavaScript:
const htmlPdf = require('html-pdf-chrome');
const html = '<p>Hello, world!</p>';
const options = {
port: 9222, // port Chrome is listening on
};
htmlPdf.create(html, options).then((pdf) => pdf.toFile('test.pdf'));
htmlPdf.create(html, options).then((pdf) => pdf.toBase64());
htmlPdf.create(html, options).then((pdf) => pdf.toBuffer());
htmlPdf.create(html, options).then((pdf) => pdf.toStream());
View the full documentation in the source code.
By default, pages are saved as a PDF. To save as a screenshot instead, supply screenshotOptions
.
All supported options can be viewed here.
const htmlPdf = require('html-pdf-chrome');
const html = '<p>Hello, world!</p>';
const options = {
port: 9222, // port Chrome is listening on
screenshotOptions: {
format: 'png', // png, jpeg, or webp. Optional, defaults to png.
// quality: 100, // Optional, quality percent (jpeg only)
// optional, defaults to entire window
clip: {
x: 0,
y: 0,
width: 100,
height: 200,
scale: 1,
},
},
// Optional. Options here: https://chromedevtools.github.io/devtools-protocol/tot/Emulation/#method-setDeviceMetricsOverride
deviceMetrics: {
width: 1000,
height: 1000,
deviceScaleFactor: 0,
mobile: false,
},
};
htmlPdf.create(html, options).then((pdf) => pdf.toFile('test.png'));
import * as htmlPdf from 'html-pdf-chrome';
const options: htmlPdf.CreateOptions = {
port: 9222, // port Chrome is listening on
};
const url = 'https://github.com/westy92/html-pdf-chrome';
const pdf = await htmlPdf.create(url, options);
import * as htmlPdf from 'html-pdf-chrome';
import * as marked from 'marked';
const options: htmlPdf.CreateOptions = {
port: 9222, // port Chrome is listening on
};
const html = marked('# Hello [World](https://www.google.com/)!');
const pdf = await htmlPdf.create(html, options);
Pug (formerly known as Jade)
import * as htmlPdf from 'html-pdf-chrome';
import * as pug from 'pug';
const template = pug.compile('p Hello, #{noun}!');
const templateData = {
noun: 'world',
};
const options: htmlPdf.CreateOptions = {
port: 9222, // port Chrome is listening on
};
const html = template(templateData);
const pdf = await htmlPdf.create(html, options);
Specify additional headers you wish to send with your request via CreateOptions.extraHTTPHeaders
.
const options: HtmlPdf.CreateOptions = {
port: 9222, // port Chrome is listening on
extraHTTPHeaders: {
'Authorization': 'Bearer 123',
'X-Custom-Test-Header': 'This is great!',
},
};
const pdf = await HtmlPdf.create('https://httpbin.org/headers', options);
Note: Requires Chrome 65 or later.
You can optionally provide an HTML template for a custom header and/or footer.
A few classes can be used to inject printing values:
date
- formatted print datetitle
- document titleurl
- document locationpageNumber
- current page numbertotalPages
- total pages in the documentYou can tweak the margins with the printOptions
of marginTop
, marginBottom
, marginLeft
, and marginRight
.
At this time, you must inline any images using base64 encoding.
You can view how Chrome lays out the templates here.
const pdf = await htmlPdf.create(html, {
port,
printOptions: {
displayHeaderFooter: true,
headerTemplate: `
<div class="text center">
Page <span class="pageNumber"></span> of <span class="totalPages"></span>
</div>
`,
footerTemplate: '<div class="text center">Custom footer!</div>',
},
});
There are a few CompletionTrigger
types that wait for something to occur before triggering PDF printing.
true
htmlPdf.CompletionTrigger.CompletionTrigger
const options: htmlPdf.CreateOptions = {
port: 9222, // port Chrome is listening on
completionTrigger: new htmlPdf.CompletionTrigger.Timer(5000), // milliseconds
};
// Alternative completionTrigger options:
new htmlPdf.CompletionTrigger.Callback(
'cbName', // optional, name of the callback to define for the browser to call when finished rendering. Defaults to 'htmlPdfCb'.
5000 // optional, timeout (milliseconds)
),
new htmlPdf.CompletionTrigger.Element(
'div#myElement', // name of the DOM element to wait for
5000 // optional, timeout (milliseconds)
),
new htmlPdf.CompletionTrigger.Event(
'myEvent', // name of the event to listen for
'#myElement', // optional DOM element CSS selector to listen on, defaults to body
5000 // optional timeout (milliseconds)
),
new htmlPdf.CompletionTrigger.LifecycleEvent(
'networkIdle', // name of the Chrome lifecycle event to listen for. Defaults to 'firstMeaningfulPaint'.
5000 // optional timeout (milliseconds)
),
new htmlPdf.CompletionTrigger.Variable(
'myVarName', // optional, name of the variable to wait for. Defaults to 'htmlPdfDone'
5000 // optional, timeout (milliseconds)
),
html-pdf-chrome is released under the MIT License.