Convert HTML to PDF in Node.js
IronPDF's most powerful and most popular feature is the ability to create high-fidelity PDFs from raw HTML, CSS, and JavaScript. This tutorial walks Node.js developers through every practical method for turning HTML content into PDFs - from a one-liner string conversion all the way to dynamic template-driven document generation.
IronPDF is a high-level API library that helps developers implement powerful PDF processing capabilities into software applications quickly. IronPDF is available in multiple programming languages. For detailed coverage on creating PDFs in .NET, Java, and Python, consult the official documentation pages. This tutorial covers its usage as it applies to Node.js projects.
Quickstart: Convert HTML to PDF in Node.jsHow to Convert HTML to PDF in Node.js
- Install the IronPDF Node.js library via NPM:
npm install @ironsoftware/ironpdf - Import the PdfDocument class from the
@ironsoftware/ironpdfpackage. - Call
PdfDocument.fromHtml,PdfDocument.fromUrl, orPdfDocument.fromZipdepending on your HTML source. - Optionally configure rendering options: headers, footers, page size, orientation, and margins.
- Call
PdfDocument.saveAsto save the generated PDF to disk.
- How Do You Get Started with IronPDF for Node.js?
- How Do You Convert HTML to PDF in Node.js?
- What Advanced Rendering Options Does IronPDF Support?
- How Do You Generate PDFs from an HTML Template?
- What Are the Next Steps?
How Do You Get Started with IronPDF for Node.js?
Start using IronPDF in your project today with a free trial.
Install the IronPDF Library
Install the IronPDF Node.js package by running the NPM command below in your chosen Node.js project:
You can also download and install the IronPDF package manually.
How Do You Install the IronPDF Engine?
IronPDF for Node.js requires an IronPDF Engine binary to function.
@ironsoftware/ironpdf package automatically downloads and installs the appropriate binary for your operating system on first execution. Explicit installation is recommended in environments where internet access is restricted or unavailable.Install the IronPDF Engine binary by installing the appropriate package for your operating system.
How Do You Apply a License Key?
By default, IronPDF brands all documents it generates or modifies with a watermark. To remove the watermark, set the licenseKey property on the global IronPdfGlobalConfig object with a valid license key:
import { IronPdfGlobalConfig } from "@ironsoftware/ironpdf";
// Retrieve the global configuration object
var config = IronPdfGlobalConfig.getConfig();
// Set a valid license key to remove watermarks
config.licenseKey = "{YOUR-LICENSE-KEY-HERE}";
Obtain a free trial license key or purchase a license key from the licensing page.
The remaining code examples in this tutorial assume that a license key has been applied in a separate config.js file, which is imported at the top of each script:
import { PdfDocument } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
// ...

The image above shows the watermark IronPDF adds to PDFs generated without a license key - obtain a key at ironpdf.com/nodejs/licensing/ to remove it.
How Do You Convert HTML to PDF in Node.js?
The IronPDF Node.js library provides four approaches for creating PDF files from HTML content:
- From a string of HTML code
- From a local HTML file
- From an online URL
- From a compressed ZIP archive
Each approach uses the PdfDocument class as its foundation. A PdfDocument represents a PDF file produced from some source content and drives most of IronPDF's core creation and editing features.
How Do You Create a PDF from an HTML String?
PdfDocument.fromHtml generates PDFs from strings of raw HTML markup. This approach offers the most flexibility of the four methods because the HTML string can be sourced from virtually anywhere - text files, data streams, an HTML template engine, or dynamically constructed markup.
import { PdfDocument } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
// Create a PDF from an HTML string
const pdf = await PdfDocument.fromHtml("<h1>Hello from IronPDF!</h1>");
// Save the PDF document to the file system
await pdf.saveAs("html-string-to-pdf.pdf");
PdfDocument.fromHtml returns a Promise that resolves to an instance of the PdfDocument class. After obtaining the instance, call saveAs with a target file path to write the PDF to disk. The saved PDF file renders the HTML exactly as a standards-compliant browser would display it.

Above is the PDF generated from the HTML string <h1>Hello from IronPDF!</h1> - PdfDocument.fromHtml output appears just as web page content would.
How Do You Create a PDF from an HTML File?
PdfDocument.fromHtml also accepts a path to a local HTML document. Instead of a string of markup, pass a valid file path as the first argument. This is the preferred approach when working with saved web pages that reference local CSS, JavaScript, and image assets.
The following example converts a sample web page into a PDF:
import { PdfDocument } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
// Render a PDF from a local HTML file
const pdf = await PdfDocument.fromHtml("./sample2.html");
// Save the PDF document to the project directory
await pdf.saveAs("html-file-to-pdf-1.pdf");

The image above shows the sample HTML page in Google Chrome before conversion. Download this and similar pages from https://filesamples.com/samples/code/html/sample2.html
IronPDF preserves the appearance of the original HTML document and retains the functionality of links, forms, and other interactive elements. This fidelity extends to complex pages that include paragraphs, lists, images, hyperlinks, and client-side scripting.

Above is the PDF generated from the sample HTML file - compare it with the previous image to see IronPDF preserve the layout with high fidelity.
IronPDF handles pages that go far beyond simple markup. The following example converts a feature-rich page that sources numerous external CSS files, images, and script assets:
import { PdfDocument } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
// Render a PDF from a complex HTML page with external assets
PdfDocument.fromHtml("./sample4.html").then(async (pdf) => {
return await pdf.saveAs("html-file-to-pdf-2.pdf");
});

The image above shows a PDF from a CSS-heavy, JavaScript-rendered page: if it looks good in Google Chrome, it looks good as a PDF.
How Do You Create a PDF from a URL?
PdfDocument.fromUrl fetches and renders a live web page as a PDF. Pass any publicly accessible URL as the argument. IronPDF's Chrome rendering engine retrieves the page, loads all assets, and produces a pixel-perfect PDF - no manual HTML download required.
import { PdfDocument } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
// Convert a live web page to a PDF
const pdf = await PdfDocument.fromUrl("https://en.wikipedia.org/wiki/PDF");
// Save the document
await pdf.saveAs("url-to-pdf.pdf");

The image above shows the Wikipedia article about the PDF format as it appears in a standards-compliant web browser.

Above is the PDF produced by calling PdfDocument.fromUrl on the Wikipedia article - note its close resemblance to the original web page.
ChromePdfRenderOptions.How Do You Create a PDF from a Zip Archive?
PdfDocument.fromZip converts a specific HTML file contained in a ZIP archive into a PDF. This is particularly useful when distributing self-contained HTML projects that bundle their HTML, CSS, and image assets together.
For this example, assume the project directory contains a ZIP file with the following structure:
html-zip.zip
├─ index.html
├─ style.css
├─ logo.png
The index.html file contains:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hello world!</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Hello from IronPDF!</h1>
<a href="https://ironpdf.com/nodejs/">
<img src="logo.png" alt="IronPDF for Node.js">
</a>
</body>
</html>
And style.css declares the page layout and font rules:
@font-face {
font-family: 'Gotham-Black';
src: url('gotham-black-webfont.eot?') format('embedded-opentype'),
url('gotham-black-webfont.woff2') format('woff2'),
url('gotham-black-webfont.woff') format('woff'),
url('gotham-black-webfont.ttf') format('truetype'),
url('gotham-black-webfont.svg') format('svg');
font-weight: normal;
font-style: normal;
font-display: swap;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
margin-left: auto;
margin-right: auto;
margin-top: 200px;
margin-bottom: auto;
color: white;
background-color: black;
text-align: center;
font-family: "Helvetica"
}
h1 {
font-family: "Gotham-Black";
margin-bottom: 70px;
font-size: 32pt;
}
img {
width: 400px;
height: auto;
}
p {
text-decoration: underline;
font-size: smaller;
}

The image above shows the sample logo.png contained inside the hypothetical HTML ZIP file.
When calling fromZip, specify the path to the ZIP file as the first argument and a configuration object as the second. Set the mainHtmlFile property to the name of the HTML file inside the archive that should be converted:
import { PdfDocument } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
// Convert an HTML file from a ZIP archive to PDF
PdfDocument.fromZip("./html-zip.zip", {
mainHtmlFile: "index.html"
}).then(async (pdf) => {
return await pdf.saveAs("html-zip-to-pdf.pdf");
});

Above is a PDF created with PdfDocument.fromZip, which renders the HTML from the ZIP archive along with its bundled assets.
What Advanced Rendering Options Does IronPDF Support?
The ChromePdfRenderOptions interface exposes properties for granular customization of PDF rendering behavior. These settings apply before the PDF is generated and cover layout, visual appearance, and edge cases for dynamic content.
IronPDF applies default rendering settings to every conversion. Retrieve these default values with the defaultChromePdfRenderOptions function:
import { defaultChromePdfRenderOptions } from "@ironsoftware/ironpdf";
// Retrieve a ChromePdfRenderOptions object with default settings
var options = defaultChromePdfRenderOptions();
Modify the returned object's properties as needed and pass it to the renderOptions parameter of any conversion method.
How Do You Add Headers and Footers?
The textHeader and textFooter properties affix custom text-based content to every page of a newly rendered PDF. The following example creates a PDF from the Google search homepage with a custom header and footer, each using a different font:
import { PdfDocument, defaultChromePdfRenderOptions, AffixFonts } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
// Start from default render options
var options = defaultChromePdfRenderOptions();
// Configure a text-based header
options.textHeader = {
centerText: "https://www.adobe.com",
dividerLine: true,
font: AffixFonts.CourierNew,
fontSize: 12,
leftText: "URL to PDF"
};
// Configure a text-based footer
options.textFooter = {
centerText: "IronPDF for Node.js",
dividerLine: true,
fontSize: 14,
font: AffixFonts.Helvetica,
rightText: "HTML to PDF in Node.js"
};
// Render the page with custom headers and footers applied
PdfDocument.fromUrl("https://www.google.com/", { renderOptions: options }).then(async (pdf) => {
return await pdf.saveAs("add-custom-headers-footers-1.pdf");
});

The image above shows a PDF of the Google home page with a custom text header and footer applied using textHeader and textFooter.
For richer header and footer layouts, use the htmlHeader and htmlFooter properties instead. These accept raw HTML fragments, giving full control over typography, images, and alignment. The example below centers the page URL in bold in the header and embeds a logo image in the footer:
import { PdfDocument, defaultChromePdfRenderOptions } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
// Start from default render options
var options = defaultChromePdfRenderOptions();
// Define a rich HTML header
options.htmlHeader = {
htmlFragment: "<strong>https://www.google.com/</strong>",
dividerLine: true,
dividerLineColor: "blue",
loadStylesAndCSSFromMainHtmlDocument: true,
};
// Define a rich HTML footer with a logo
options.htmlFooter = {
htmlFragment: "<img src='logo.png' alt='IronPDF for Node.js' style='display: block; width: 150px; height: auto; margin-left: auto; margin-right: auto;'>",
dividerLine: true,
loadStylesAndCSSFromMainHtmlDocument: true
};
// Apply custom HTML headers and footers during rendering
await PdfDocument.fromUrl("https://www.google.com/", { renderOptions: options }).then(async (pdf) => {
return await pdf.saveAs("add-html-headers-footers.pdf");
});

The image above shows a PDF with an HTML-based header (the page URL in bold) and footer (the IronPDF logo) - full control over branding and layout on every page.
How Do You Control Page Size, Orientation, and Margins?
The margin, paperSize, fitToPaperMode, paperOrientation, and grayScale properties on ChromePdfRenderOptions control the physical layout of every rendered page. The following example converts the Google homepage with custom margins, A5 landscape orientation, and grayscale output:
import { PdfDocument, defaultChromePdfRenderOptions, PaperSize, FitToPaperModes, PdfPaperOrientation } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
// Start from default render options
var options = defaultChromePdfRenderOptions();
// Set page margins in millimeters
options.margin = {
top: 50,
bottom: 50,
left: 60,
right: 60
};
// Configure paper size, fit mode, orientation, and color mode
options.paperSize = PaperSize.A5;
options.fitToPaperMode = FitToPaperModes.FitToPage;
options.paperOrientation = PdfPaperOrientation.Landscape;
options.grayScale = true;
// Render with the customized layout settings
PdfDocument.fromUrl("https://www.google.com/", { renderOptions: options }).then(async (pdf) => {
return await pdf.saveAs("set-margins-and-page-size.pdf");
});
The PaperSize enumeration includes standard paper sizes such as A4, A5, Letter, and Legal. The PdfPaperOrientation enumeration supports Portrait and Landscape. These settings give precise control over output dimensions for print-ready documents.
How Do You Handle Dynamic Web Pages?
Pages that load content asynchronously - through JavaScript timers, lazy loading, or API calls - may not be fully rendered by the time IronPDF's engine captures them. The WaitFor mechanism, configured through the waitFor property on ChromePdfRenderOptions, instructs the Chrome renderer to pause until specified conditions are met before capturing the page.
The following code block sets IronPDF to wait 20 seconds before capturing the page content:
import { PdfDocument, defaultChromePdfRenderOptions, WaitForType } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
// Configure the renderer to wait 20 seconds before capturing
var options = defaultChromePdfRenderOptions();
options.waitFor = {
type: WaitForType.RenderDelay,
delay: 20000
};
PdfDocument.fromUrl("https://ironpdf.com/nodejs/", { renderOptions: options }).then(async (pdf) => {
return await pdf.saveAs("waitfor-renderdelay.pdf");
});
Alternatively, configure IronPDF to wait until a specific DOM element appears before rendering. This is useful for pages where content is injected after a JavaScript framework finishes mounting:
import { PdfDocument, defaultChromePdfRenderOptions, WaitForType } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
// Configure the renderer to wait for a specific DOM element (up to 20 seconds)
var options = defaultChromePdfRenderOptions();
options.waitFor = {
type: WaitForType.HtmlElement,
htmlQueryStr: "div.ProseMirror",
maxWaitTime: 20000,
};
PdfDocument.fromUrl("https://app.surferseo.com/drafts/s/V7VkcdfgFz-dpkldsfHDGFFYf4jjSvvjsdf", { renderOptions: options }).then(async (pdf) => {
return await pdf.saveAs("waitfor-htmlelement.pdf");
});
The WaitForType.HtmlElement strategy uses a standard CSS query selector. The renderer polls for the element's presence until maxWaitTime milliseconds elapse or the element is found - whichever comes first.
How Do You Generate PDFs from an HTML Template?
A common real-world automation pattern is generating a batch of PDFs from a shared HTML template, substituting placeholder values with data from a database, API, or spreadsheet. IronPDF's replaceText method on PdfDocument handles this directly.
The sample invoice template below (adapted from a publicly accessible CodePen invoice template) uses curly-brace placeholders such as {COMPANY-NAME}, {FULL-NAME}, and {INVOICE-NUMBER} for substitutable content:

The image above shows a sample invoice HTML template with placeholder tags; JavaScript replaces each tag with real data before the document is saved as a PDF.
The following code loads the template, replaces every placeholder with test data, and saves the result as a PDF:
import { PdfDocument } from "@ironsoftware/ironpdf";
import './config.js'; // Import the configuration script
/**
* Loads an HTML template from the file system as a PdfDocument.
*/
async function getTemplateHtml(fileLocation) {
return PdfDocument.fromHtml(fileLocation);
}
/**
* Saves a PdfDocument to the specified file path.
*/
async function generatePdf(pdf, location) {
return pdf.saveAs(location);
}
/**
* Replaces a named placeholder in the PdfDocument with a data value.
*/
async function addTemplateData(pdf, key, value) {
return pdf.replaceText(key, value);
}
// Path to the HTML invoice template
const template = "./sample-invoice.html";
// Load the template, fill in all placeholder values, then save the PDF
getTemplateHtml(template).then(async (doc) => {
await addTemplateData(doc, "{FULL-NAME}", "Lizbeth Presland");
await addTemplateData(doc, "{ADDRESS}", "678 Manitowish Alley, Portland, OG");
await addTemplateData(doc, "{PHONE-NUMBER}", "(763) 894-4345");
await addTemplateData(doc, "{INVOICE-NUMBER}", "787");
await addTemplateData(doc, "{INVOICE-DATE}", "August 28, 2023");
await addTemplateData(doc, "{AMOUNT-DUE}", "13,760.13");
await addTemplateData(doc, "{RECIPIENT}", "Celestyna Farmar");
await addTemplateData(doc, "{COMPANY-NAME}", "BrainBook");
await addTemplateData(doc, "{TOTAL}", "13,760.13");
await addTemplateData(doc, "{AMOUNT-PAID}", "0.00");
await addTemplateData(doc, "{BALANCE-DUE}", "13,760.13");
await addTemplateData(doc, "{ITEM}", "Training Sessions");
await addTemplateData(doc, "{DESCRIPTION}", "60 Minute instruction");
await addTemplateData(doc, "{RATE}", "3,440.03");
await addTemplateData(doc, "{QUANTITY}", "4");
await addTemplateData(doc, "{PRICE}", "13,760.13");
return doc;
}).then(async (doc) => await generatePdf(doc, "html-template-to-pdf.pdf"));
The code above defines three async helper functions:
getTemplateHtml: Loads an HTML file into aPdfDocumentobject usingPdfDocument.fromHtml.addTemplateData: CallsPdfDocument.replaceTextto substitute a placeholder key with its real data value.generatePdf: Writes the completedPdfDocumentto a target file path.
Each replaceText call operates directly on the in-memory PDF representation, so multiple replacements can be chained without reloading the document from disk. The resulting PDF retains all CSS styles, fonts, and layout from the original template.

Above is the completed PDF invoice with placeholders replaced by real data - the original template's CSS styles and layout are preserved exactly.
This approach scales well for batch document generation. Call getTemplateHtml once per record to create a fresh PdfDocument for each output file, then chain the addTemplateData calls for that record's data before calling generatePdf.
What Are the Next Steps?
This tutorial covers the core HTML-to-PDF conversion methods and the most frequently used rendering options in IronPDF for Node.js. The topics below extend what you have learned here into more specialized areas.
- Edit and Stamp PDFs in Node.js - Apply stamps, annotations, and text edits to existing PDF documents programmatically.
- Merge and Split PDFs in Node.js - Combine multiple PDFs into a single document or split one PDF into separate pages.
- Add Watermarks to PDFs in Node.js - Apply text or image watermarks across every page of a PDF with precise positioning control.
- IronPDF Node.js API Reference - Browse the full API for
PdfDocument,ChromePdfRenderOptions,WaitFor,AffixFonts, and all other exported classes and interfaces. - Get a Free Trial License Key - Generate production-quality PDFs without watermarks by activating a free 30-day trial license.
Frequently Asked Questions
How can I convert an HTML string to PDF using IronPDF in Node.js?
To convert an HTML string to PDF using IronPDF in Node.js, you can use the PdfDocument.fromHtml method. This function generates a PDF from a raw HTML markup string, allowing for dynamic HTML content creation.
What steps are needed to convert an HTML file to PDF with IronPDF?
To convert an HTML file to PDF with IronPDF, you first import the PdfDocument class, then use the PdfDocument.fromHtml method with a file path as the argument. Finally, save the PDF using the saveAs method.
How do you create a PDF from a URL in Node.js with IronPDF?
Use the PdfDocument.fromUrl method to create a PDF from a live web page URL. This feature fetches the webpage, loads all associated assets, and generates a browser-equivalent PDF file.
Can IronPDF convert HTML content from a ZIP archive to PDF?
Yes, IronPDF can convert HTML content from a ZIP archive to PDF using the PdfDocument.fromZip method. Specify the path to the ZIP file and designate the main HTML file within.
What advanced rendering options are available with IronPDF?
Advanced rendering options in IronPDF include setting custom headers and footers, controlling page size, orientation, and margins, and handling dynamic content with wait conditions through ChromePdfRenderOptions.
How can you add headers and footers to a PDF in IronPDF?
To add headers and footers to a PDF in IronPDF, configure the textHeader, textFooter, htmlHeader, or htmlFooter properties within ChromePdfRenderOptions to incorporate custom content and styling.
How do you handle dynamic web pages during PDF conversion with IronPDF?
For dynamic web pages, use the waitFor property in ChromePdfRenderOptions to define a render delay or wait for a specific DOM element before capturing the page content as a PDF.
What is the process for generating PDFs from an HTML template in IronPDF?
To generate PDFs from an HTML template, load the template with PdfDocument.fromHtml, replace placeholder text with real data using replaceText, and save the document with saveAs.
How do you ensure high fidelity in HTML to PDF conversion using IronPDF?
IronPDF ensures high fidelity in conversions by using a Chrome-based rendering engine that supports HTML5, CSS, and JavaScript, resulting in PDFs that mimic browser-rendered pages closely.
What are the licensing requirements to remove watermarks from PDFs created with IronPDF?
To remove watermarks from PDFs created with IronPDF, apply a valid license key using the licenseKey property on the global IronPdfGlobalConfig object. You can obtain keys from IronPDF's licensing page.
Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.