IronPDF gives Python developers a direct path from HTML markup to production-ready PDF files — no intermediate design tools, no proprietary layout engines, no separate rendering pipeline. The library's ChromePdfRenderer class uses a Chromium-based engine under the hood, so any HTML that displays correctly in Chrome will convert accurately to PDF. This tutorial walks through every supported conversion method — HTML strings, local HTML files, and live URLs — and then covers the rendering options that let you control page size, margins, headers, footers, and more.
A companion tutorial is available for converting HTML to PDF in .NET applications if you need the C# or VB.NET workflow.
Quickstart: Convert HTML to PDF in Python
How to Convert HTML to PDF in Python

- Install IronPDF for Python via pip
- Import the library with
from ironpdf import * - Instantiate
ChromePdfRenderer - Call
RenderHtmlAsPdf,RenderUrlAsPdf, orRenderHtmlFileAsPdf - Save the result with
pdf.SaveAs("output.pdf")
Table of Contents
- How Do You Install IronPDF for Python?
- How Do You Configure IronPDF Before Converting?
- How Do You Convert an HTML String to PDF?
- How Do You Convert a URL to PDF?
- How Do You Convert an HTML File to PDF?
- How Do You Control PDF Rendering Options?
- How Do You Add Custom Headers and Footers?
- What Are the Next Steps?
Getting Started
How Do You Install IronPDF for Python?
IronPDF is distributed via pip, Python's standard package manager. Run the following command in a terminal to install the latest version:
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/install.sh
pip install ironpdf//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/install.sh
pip install ironpdfTo pin a specific release — useful in CI pipelines or containerized environments — append the version number:
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/install-versioned.sh
pip install ironpdf==2024.x.x//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/install-versioned.sh
pip install ironpdf==2024.x.xThe first time IronPDF initializes, it downloads a compatible Chromium binary. This download takes a moment on a fresh machine but only happens once per environment. Subsequent runs start up much faster because the binary is cached locally.
How-To Guide and Code Examples
How Do You Configure IronPDF Before Converting?
Two setup tasks are worth completing before the first conversion call: setting a license key and — optionally — configuring a log file location.
Importing the Package
Every Python file that uses IronPDF needs this single import line. Place it at the top of the file:
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/import.py
from ironpdf import *//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/import.py
from ironpdf import *All IronPDF classes — ChromePdfRenderer, PdfDocument, License, Logger, and the rest — become available through this wildcard import.
Setting a License Key
Without a license key, IronPDF adds a tiled watermark to every generated PDF. The watermark is suitable for development and testing, but production deployments require a valid key.
PDFs generated without a license key include a tiled watermark. Visit the licensing page to obtain a key.
Set the key before any other IronPDF calls:
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/set-license.py
from ironpdf import *
# Set the license key before any PDF operations
License.LicenseKey = "IRONPDF-MYLICENSE-KEY-1EF01"//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/set-license.py
from ironpdf import *
# Set the license key before any PDF operations
License.LicenseKey = "IRONPDF-MYLICENSE-KEY-1EF01"Start a free trial to receive a temporary key, or purchase a license for unrestricted production use.
Configuring Log Output
IronPDF writes diagnostic output to a file named Default.log in the script's working directory. To redirect logging to a different path or capture more detail for debugging, set the Logger properties before the first conversion:
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/configure-logging.py
from ironpdf import *
# Configure logging before running any conversions
Logger.EnableDebugging = True
Logger.LogFilePath = "ironpdf-debug.log"
Logger.LoggingMode = Logger.LoggingModes.All//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/configure-logging.py
from ironpdf import *
# Configure logging before running any conversions
Logger.EnableDebugging = True
Logger.LogFilePath = "ironpdf-debug.log"
Logger.LoggingMode = Logger.LoggingModes.AllLogger.LogFilePath must be set before the first PDF conversion call. Changes made afterward have no effect on the current session.Detailed logs are most useful when diagnosing why a particular HTML page doesn't render as expected — they capture network requests, CSS loading events, and JavaScript execution timing.
How Do You Convert an HTML String to PDF?
Converting an in-memory HTML string is the most direct approach and works well when the HTML is generated programmatically — for example, from a Jinja2 template or a database-driven report.
Basic HTML String Conversion
Instantiate ChromePdfRenderer, pass the HTML string to RenderHtmlAsPdf, and call SaveAs on the returned PdfDocument:
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/html-string-basic.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Convert an HTML string to a PDF document
pdf = renderer.RenderHtmlAsPdf("<h1>Hello from IronPDF!</h1><p>Generated in Python.</p>")
pdf.SaveAs("hello.pdf")//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/html-string-basic.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Convert an HTML string to a PDF document
pdf = renderer.RenderHtmlAsPdf("<h1>Hello from IronPDF!</h1><p>Generated in Python.</p>")
pdf.SaveAs("hello.pdf")The ChromePdfRenderer processes HTML, CSS, and JavaScript the same way a modern browser does. Any content that renders correctly in Chrome will produce an accurate PDF.
HTML String with External Assets
When the HTML string references local assets — stylesheets, images, scripts — pass the directory path as the second argument to RenderHtmlAsPdf. IronPDF uses this path as the base URL when resolving relative references:
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/html-string-assets.py
from ironpdf import *
html_content = """
<html>
<head>
<title>Styled Report</title>
<link rel='stylesheet' href='assets/style.css'>
</head>
<body>
<h1>Monthly Report</h1>
<img src='assets/logo.png' alt='Company logo'>
<p>Data as of Q1 2024.</p>
</body>
</html>
"""
renderer = ChromePdfRenderer()
# The second argument sets the base path for resolving relative asset URLs
pdf = renderer.RenderHtmlAsPdf(html_content, "./")
pdf.SaveAs("styled-report.pdf")//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/html-string-assets.py
from ironpdf import *
html_content = """
<html>
<head>
<title>Styled Report</title>
<link rel='stylesheet' href='assets/style.css'>
</head>
<body>
<h1>Monthly Report</h1>
<img src='assets/logo.png' alt='Company logo'>
<p>Data as of Q1 2024.</p>
</body>
</html>
"""
renderer = ChromePdfRenderer()
# The second argument sets the base path for resolving relative asset URLs
pdf = renderer.RenderHtmlAsPdf(html_content, "./")
pdf.SaveAs("styled-report.pdf")The base path can point to any local directory or a network share. Assets in subdirectories are resolved relative to it. For more patterns involving complex HTML strings, see the HTML string to PDF code example.
How Do You Convert a URL to PDF?
The RenderUrlAsPdf method fetches a live URL, waits for the page to fully load — including any JavaScript-driven content — and converts the rendered result to PDF. This makes it suitable for capturing dashboards, reports, or any page where the final visual state depends on JavaScript execution.
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/url-to-pdf.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Fetch and convert a live web page to PDF
pdf = renderer.RenderUrlAsPdf("https://en.wikipedia.org/wiki/Portable_Document_Format")
pdf.SaveAs("wikipedia-pdf.pdf")//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/url-to-pdf.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Fetch and convert a live web page to PDF
pdf = renderer.RenderUrlAsPdf("https://en.wikipedia.org/wiki/Portable_Document_Format")
pdf.SaveAs("wikipedia-pdf.pdf")ChromePdfRenderer instance before calling RenderUrlAsPdf. See the HTTP login credentials guide for details.When the target page loads asynchronous content, IronPDF waits for the Chromium rendering engine to signal that the document is fully painted. For pages with heavy JavaScript or delayed network requests, consider adjusting WaitFor properties on ChromePdfRenderOptions (covered in the rendering options section below). The URL to PDF code example shows additional configuration patterns.
How Do You Convert an HTML File to PDF?
RenderHtmlFileAsPdf accepts a path to a local HTML file and converts it directly. Relative paths inside the HTML — to CSS files, images, or JavaScript — are resolved against the HTML file's own directory automatically, so no base-path argument is needed.
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/html-file-to-pdf.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Convert a local HTML file (and its linked CSS/JS) to PDF
pdf = renderer.RenderHtmlFileAsPdf("invoices/TestInvoice1.html")
pdf.SaveAs("invoice.pdf")//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/html-file-to-pdf.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Convert a local HTML file (and its linked CSS/JS) to PDF
pdf = renderer.RenderHtmlFileAsPdf("invoices/TestInvoice1.html")
pdf.SaveAs("invoice.pdf")This method is particularly useful for server-side document generation where an HTML template has already been written to disk — a common pattern when using Django or Flask to render Jinja2 templates to files before converting them to PDF for download.
IronPDF resolves any <link>, <script>, and <img> tags relative to the HTML file location, so linked stylesheets, embedded fonts, and images appear in the PDF exactly as they do in a browser. The process mirrors how RenderHtmlAsPdf handles inline assets, with the difference that no explicit base path needs to be supplied.
How Do You Control PDF Rendering Options?
ChromePdfRenderOptions is the configuration object passed to ChromePdfRenderer (or directly to any of the render methods) to control page layout, margins, paper size, and other output characteristics. Setting options before conversion is the standard way to tailor the PDF output.
Paper Size and Orientation
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/render-options-paper.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Configure page layout before rendering
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20
renderer.RenderingOptions.MarginLeft = 15
renderer.RenderingOptions.MarginRight = 15
pdf = renderer.RenderHtmlAsPdf("<h1>Landscape Report</h1><p>Content here.</p>")
pdf.SaveAs("landscape-a4.pdf")//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/render-options-paper.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Configure page layout before rendering
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20
renderer.RenderingOptions.MarginLeft = 15
renderer.RenderingOptions.MarginRight = 15
pdf = renderer.RenderHtmlAsPdf("<h1>Landscape Report</h1><p>Content here.</p>")
pdf.SaveAs("landscape-a4.pdf")Margins are expressed in millimeters. PdfPaperSize supports all standard ISO sizes — A0 through A10, Letter, Legal, Tabloid — as well as Custom for arbitrary dimensions defined by CustomPaperWidth and CustomPaperHeight.
Custom Paper Dimensions
When standard paper sizes don't match the output requirement — for example, a receipt or label printer format — define width and height explicitly:
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/render-options-custom-size.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Set a custom paper size (in millimetres)
renderer.RenderingOptions.PaperSize = PdfPaperSize.Custom
renderer.RenderingOptions.CustomPaperWidth = 80 # 80 mm receipt roll width
renderer.RenderingOptions.CustomPaperHeight = 200
pdf = renderer.RenderHtmlAsPdf("<h2>Receipt</h2><p>Total: $12.50</p>")
pdf.SaveAs("receipt.pdf")//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/render-options-custom-size.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Set a custom paper size (in millimetres)
renderer.RenderingOptions.PaperSize = PdfPaperSize.Custom
renderer.RenderingOptions.CustomPaperWidth = 80 # 80 mm receipt roll width
renderer.RenderingOptions.CustomPaperHeight = 200
pdf = renderer.RenderHtmlAsPdf("<h2>Receipt</h2><p>Total: $12.50</p>")
pdf.SaveAs("receipt.pdf")Enabling JavaScript Execution
By default, IronPDF executes JavaScript during rendering. If a page relies on JavaScript to generate visible content — charts, data tables, dynamic form values — this behavior means the rendered PDF reflects the final DOM state. To disable JavaScript for pages where it is unnecessary:
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/render-options-javascript.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Disable JavaScript for static HTML pages
renderer.RenderingOptions.EnableJavaScript = False
pdf = renderer.RenderHtmlAsPdf("<p>Static content only.</p>")
pdf.SaveAs("static.pdf")//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/render-options-javascript.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Disable JavaScript for static HTML pages
renderer.RenderingOptions.EnableJavaScript = False
pdf = renderer.RenderHtmlAsPdf("<p>Static content only.</p>")
pdf.SaveAs("static.pdf")Disabling JavaScript reduces rendering time for simple, static HTML documents.
For more rendering configuration details, see PDF generation settings and the custom paper size example.
How Do You Add Custom Headers and Footers?
Headers and footers in IronPDF are applied through HtmlHeaderFooter or TextHeaderFooter objects attached to the renderer's RenderingOptions. HtmlHeaderFooter gives you full HTML and CSS control — ideal for branded letterheads with logos. TextHeaderFooter is simpler and covers most text-based requirements including dynamic page numbers.
Text-Based Header and Footer
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/headers-footers-text.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Add a text header with the document title
renderer.RenderingOptions.TextHeader = TextHeaderFooter()
renderer.RenderingOptions.TextHeader.CenterText = "Quarterly Report — Q1 2024"
renderer.RenderingOptions.TextHeader.DrawDividerLine = True
renderer.RenderingOptions.TextHeader.FontSize = 10
# Add a footer with page numbers
renderer.RenderingOptions.TextFooter = TextHeaderFooter()
renderer.RenderingOptions.TextFooter.RightText = "Page {page} of {total-pages}"
renderer.RenderingOptions.TextFooter.FontSize = 9
renderer.RenderingOptions.TextFooter.DrawDividerLine = True
html = "<h1>Executive Summary</h1><p>Revenue increased 12% year-over-year.</p>"
pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("report-with-footer.pdf")//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/headers-footers-text.py
from ironpdf import *
renderer = ChromePdfRenderer()
# Add a text header with the document title
renderer.RenderingOptions.TextHeader = TextHeaderFooter()
renderer.RenderingOptions.TextHeader.CenterText = "Quarterly Report — Q1 2024"
renderer.RenderingOptions.TextHeader.DrawDividerLine = True
renderer.RenderingOptions.TextHeader.FontSize = 10
# Add a footer with page numbers
renderer.RenderingOptions.TextFooter = TextHeaderFooter()
renderer.RenderingOptions.TextFooter.RightText = "Page {page} of {total-pages}"
renderer.RenderingOptions.TextFooter.FontSize = 9
renderer.RenderingOptions.TextFooter.DrawDividerLine = True
html = "<h1>Executive Summary</h1><p>Revenue increased 12% year-over-year.</p>"
pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("report-with-footer.pdf")The {page} and {total-pages} placeholders are replaced at render time with the correct values. Other available placeholders include {date}, {time}, and {url}.
HTML-Based Header with Logo
When a branded header is required — a company logo, a color band, or a formatted address block — use HtmlHeaderFooter instead:
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/headers-footers-html.py
from ironpdf import *
renderer = ChromePdfRenderer()
header_html = """
<div style="font-family: Arial, sans-serif; border-bottom: 2px solid #003366; padding: 8px 0;">
<img src='assets/logo.png' style='height: 40px; float: left;' alt='Company logo'>
<span style='float: right; font-size: 11px; color: #666;'>Confidential</span>
<div style='clear:both;'></div>
</div>
"""
renderer.RenderingOptions.HtmlHeader = HtmlHeaderFooter()
renderer.RenderingOptions.HtmlHeader.HtmlFragment = header_html
renderer.RenderingOptions.HtmlHeader.BaseUrl = "./"
html_body = "<h1>Project Status Update</h1><p>All milestones on track.</p>"
pdf = renderer.RenderHtmlAsPdf(html_body, "./")
pdf.SaveAs("branded-report.pdf")//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/headers-footers-html.py
from ironpdf import *
renderer = ChromePdfRenderer()
header_html = """
<div style="font-family: Arial, sans-serif; border-bottom: 2px solid #003366; padding: 8px 0;">
<img src='assets/logo.png' style='height: 40px; float: left;' alt='Company logo'>
<span style='float: right; font-size: 11px; color: #666;'>Confidential</span>
<div style='clear:both;'></div>
</div>
"""
renderer.RenderingOptions.HtmlHeader = HtmlHeaderFooter()
renderer.RenderingOptions.HtmlHeader.HtmlFragment = header_html
renderer.RenderingOptions.HtmlHeader.BaseUrl = "./"
html_body = "<h1>Project Status Update</h1><p>All milestones on track.</p>"
pdf = renderer.RenderHtmlAsPdf(html_body, "./")
pdf.SaveAs("branded-report.pdf")BaseUrl on HtmlHeaderFooter to the same base path used for the document body. This ensures images and stylesheets referenced inside the header HTML resolve correctly.The header and footer appear on every page of the generated PDF, including multi-page documents. For a working example with page-level metadata in the footer, see the HTML headers and footers code example.
Margin Adjustments for Headers and Footers
When adding a header or footer, increase the corresponding margin so the content doesn't overlap the page body:
//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/headers-footers-margins.py
from ironpdf import *
renderer = ChromePdfRenderer()
renderer.RenderingOptions.MarginTop = 30 # Make room for header
renderer.RenderingOptions.MarginBottom = 20 # Make room for footer
renderer.RenderingOptions.TextHeader = TextHeaderFooter()
renderer.RenderingOptions.TextHeader.CenterText = "Internal Use Only"
renderer.RenderingOptions.TextFooter = TextHeaderFooter()
renderer.RenderingOptions.TextFooter.CenterText = "Page {page} of {total-pages}"
pdf = renderer.RenderHtmlAsPdf("<h1>Internal Document</h1><p>Body content.</p>")
pdf.SaveAs("margined-report.pdf")//:path=/static-assets/pdf/content-code-examples/tutorials/html-to-pdf/headers-footers-margins.py
from ironpdf import *
renderer = ChromePdfRenderer()
renderer.RenderingOptions.MarginTop = 30 # Make room for header
renderer.RenderingOptions.MarginBottom = 20 # Make room for footer
renderer.RenderingOptions.TextHeader = TextHeaderFooter()
renderer.RenderingOptions.TextHeader.CenterText = "Internal Use Only"
renderer.RenderingOptions.TextFooter = TextHeaderFooter()
renderer.RenderingOptions.TextFooter.CenterText = "Page {page} of {total-pages}"
pdf = renderer.RenderHtmlAsPdf("<h1>Internal Document</h1><p>Body content.</p>")
pdf.SaveAs("margined-report.pdf")For layout-critical documents, combine margin adjustments with PaperSize settings to match the output exactly to a print specification. Additional layout controls — such as IronSoftwareSystemDrawingColor background fills and CSS @page rules — are detailed in the custom margins example.
What Are the Next Steps?
This tutorial covered the three core HTML-to-PDF conversion methods and the rendering options that control their output. The following guides build on this foundation and cover more specialized tasks:
- PDF Generation Settings — Deep dive into
ChromePdfRenderOptions: DPI, background rendering, CSS media type, JavaScript wait strategies, and print vs. screen mode. - HTML Headers and Footers — Branded header and footer templates with logos, page numbers, dates, and multi-column layouts.
- Custom Margins and Paper Size — Fine-tune page geometry for print-ready output and non-standard formats.
- Add Watermarks to PDFs — Stamp text or image watermarks onto existing or newly generated PDFs.
- Extract Text from PDFs — Read text content from generated or existing PDFs programmatically.
Start a free 30-day trial to generate unlimited, watermark-free PDFs during evaluation. When ready for production, view licensing options for teams and enterprise deployments.
Frequently Asked Questions
How do I convert an HTML string to PDF in Python?
Instantiate ChromePdfRenderer, then call renderer.RenderHtmlAsPdf(html_string). The method accepts any valid HTML including inline CSS and JavaScript. Save the returned PdfDocument with pdf.SaveAs("output.pdf").
How do I install IronPDF for Python?
Run pip install ironpdf from a terminal. IronPDF for Python requires the .NET 6.0 SDK or later, which must be installed separately before the first use.
Can IronPDF convert a live URL to PDF in Python?
Yes. Use renderer.RenderUrlAsPdf("https://example.com"). IronPDF fetches the page using a Chromium engine, waits for JavaScript to finish executing, and then generates the PDF from the fully rendered DOM.
How do I convert a local HTML file to PDF?
Call renderer.RenderHtmlFileAsPdf("path/to/file.html"). IronPDF resolves all relative asset paths — stylesheets, images, scripts — relative to the HTML file's directory automatically.
How do I remove the watermark from IronPDF-generated PDFs?
Set a valid license key with License.LicenseKey = "YOUR-KEY" before any PDF operation. Without a key, IronPDF adds a tiled watermark suitable for development but not for production use.
What rendering options does IronPDF expose for Python?
Properties on renderer.RenderingOptions control paper size (PaperSize), orientation (PaperOrientation), margins (MarginTop, MarginLeft, etc.), custom dimensions (CustomPaperWidth, CustomPaperHeight), JavaScript execution (EnableJavaScript), and more.
How do I add page numbers to a PDF with IronPDF in Python?
Assign a TextHeaderFooter to renderer.RenderingOptions.TextFooter and include the placeholder {page} or {total-pages} in one of the text properties such as RightText or CenterText.
Can I add a branded logo header to every page of a generated PDF?
Yes. Use HtmlHeaderFooter with an HTML fragment that includes an <img> tag. Assign it to renderer.RenderingOptions.HtmlHeader and set BaseUrl so the image path resolves correctly.
Does IronPDF support custom paper sizes in Python?
Yes. Set renderer.RenderingOptions.PaperSize to PdfPaperSize.Custom, then assign CustomPaperWidth and CustomPaperHeight in millimetres to define any arbitrary page dimension.
What .NET version does IronPDF for Python require?
IronPDF for Python requires the .NET 6.0 SDK or later. The SDK is available at no cost from the Microsoft .NET download page and must be installed before pip-installing or running IronPDF.










