How to Turn an HTML File into a PDF
Convert an HTML file to PDF with Chrome, headless automation, WeasyPrint, or ScreenshotNeo. Includes commands, code, layout fixes, and troubleshooting.
The quickest way to turn an HTML file into a PDF is to open it in Chrome, choose File → Print (Ctrl+P on Windows/Linux or Command+P on Mac), select a PDF destination, review the preview, and save. For repeatable workflows, use Chrome Headless with --print-to-pdf or a renderer such as WeasyPrint.
This guide covers local files, scripted conversion, print CSS, JavaScript-heavy pages, missing assets, page breaks, security, and a hosted alternative.
1. Convert an HTML file to PDF in Chrome
- Keep the HTML file beside its CSS, images, fonts, and other asset folders.
- Open the
.htmlfile in Chrome. You can double-click it or useCtrl+O(Windows/Linux) orCommand+O(Mac). - Choose File → Print, or press
Ctrl+P/Command+P. Chrome documents this workflow and its PDF destination in the print instructions. - Choose Save as PDF or another PDF destination.
- Set paper size, orientation, scale, margins, and whether background graphics should print.
- Inspect every page in the preview, then save the file.
Preview before saving. Check for clipped columns, blank pages, missing images, unexpected headers and footers, and headings stranded at the bottom of a page.
Print settings that affect the result
| Setting | Use it when |
|---|---|
| Paper size | The document must match Letter, A4, or another paper standard. |
| Orientation | Use landscape for wide tables or diagrams. |
| Scale | Reduce scale when content is clipped; increase it only when the preview leaves excessive whitespace. |
| Margins | Adjust margins when content touches the edge or page breaks are awkward. |
| Background graphics | Enable this when colors, backgrounds, or CSS-generated visual panels are part of the document. |
| Headers and footers | Disable browser-generated URL, title, date, and page labels when they are not wanted. |
2. Make the HTML print-friendly with CSS
Screen CSS and print CSS have different goals. Add a print stylesheet or an @media print block:
<style>
@media print {
nav, .cookie-banner, .chat-widget, .screen-only { display: none !important; }
body { color: #000; background: #fff; }
a { color: inherit; text-decoration: none; }
.page-break { break-before: page; }
h1, h2, h3 { break-after: avoid; }
table, figure, pre { break-inside: avoid; }
}
@page {
size: A4;
margin: 18mm 15mm;
}
</style>
Use break-before, break-after, and break-inside for intentional pagination. Keep important content in normal document flow. A PDF is a rendered document, so hover states, open menus, video, and other interactive behavior are not preserved as live interactions.
3. Convert with Chrome Headless
For scripts, CI jobs, or batch work, Chrome’s headless mode can write a PDF without opening a window. The Chrome for Developers reference documents --print-to-pdf, --no-pdf-header-footer, --timeout, and --virtual-time-budget.
google-chrome --headless --disable-gpu \
--print-to-pdf="output.pdf" \
--no-pdf-header-footer \
"file:///absolute/path/document.html"
The --print-to-pdf flag writes a PDF named output.pdf in the working directory when no output path is supplied. Use an absolute file:// URL for local files.
Wait for scripts and remote resources
google-chrome --headless --disable-gpu \
--timeout=15000 \
--virtual-time-budget=5000 \
--print-to-pdf="output.pdf" \
--no-pdf-header-footer \
"https://example.com/report.html"
A timeout caps waiting; a virtual-time budget gives time-dependent page code an opportunity to run. These flags do not guarantee that every third-party request succeeds. Make assets local or ensure the renderer can reach them, then inspect the resulting PDF.
4. Convert with WeasyPrint
WeasyPrint is useful when you want a command-line or Python workflow for document generation. Its documentation covers both forms:
weasyprint document.html document.pdf
from weasyprint import HTML
HTML(filename="document.html").write_pdf("document.pdf")
You can also render a URL:
from weasyprint import HTML
HTML(url="https://example.com/report.html").write_pdf("report.pdf")
Check WeasyPrint’s documented CSS support before depending on browser-only features. Its documentation also warns that untrusted HTML or CSS can create security problems. Isolate the process, restrict network and file access, and avoid rendering arbitrary uploads with production privileges.
5. Existing wkhtmltopdf workflows
wkhtmltopdf is a command-line HTML-to-PDF converter based on Qt WebKit. A basic command is:
wkhtmltopdf document.html document.pdf
Its usage manual includes options such as local-file access. The project homepage and manual are older than current Chrome documentation, so verify maintenance, runtime compatibility, and security requirements before choosing it for a new system. Do not assume it renders modern CSS or JavaScript exactly like Chrome.
6. Choosing a conversion method
| Method | Best fit | Watch for |
|---|---|---|
| Chrome print preview | One-off conversion by a person | Dialog options vary by operating system and Chrome version. |
| Chrome Headless | Automated jobs that need browser rendering | Choose a wait strategy and verify scripts and assets loaded. |
| WeasyPrint | Python or CLI document generation | CSS support differs from a full browser; isolate untrusted input. |
| wkhtmltopdf | Existing deployments built around it | Check project status, compatibility, local-file exposure, and rendering limits. |
Compare tools by JavaScript dependence, print CSS requirements, volume, input trust, asset accessibility, and how much browser fidelity you need. The available documentation does not establish a universal speed, accuracy, or cost winner.
7. Troubleshooting HTML-to-PDF conversion
Images or fonts are missing
Cause: relative paths resolve from a different working directory, a file URL is blocked, or a remote request failed. Fix: keep companion folders beside the HTML, use correct relative paths, test absolute URLs, and verify the renderer can access remote resources.
The PDF contains a blank page
Cause: a forced page break, oversized element, or print margin pushed content onto a new sheet. Fix: inspect break-before/page-break-before, reduce oversized images, and review margins and scale.
Content is cut off
Cause: fixed widths, overflow rules, or a wide table exceed the paper width. Fix: use responsive print widths, allow wrapping, switch to landscape, or reduce scale.
JavaScript-generated content is absent
Cause: printing began before the page finished rendering. Fix: wait for the application state in your automation, use Chrome Headless timeout and virtual-time options, or generate the data into static HTML first.
Headers and footers appear unexpectedly
Cause: Chrome print metadata is enabled. Fix: disable headers and footers in the dialog or pass --no-pdf-header-footer to Chrome Headless.
Remote stylesheets work in Chrome but not in a server job
Cause: DNS, authentication, TLS, firewall, or network-policy differences. Fix: make dependencies available to the job, bundle critical CSS, and log failed requests.
The output differs between machines
Cause: different browser versions, fonts, viewport defaults, locale, or timezone. Fix: pin the renderer, install the required fonts, set locale/timezone explicitly where supported, and compare generated PDFs in CI.
8. Performance, reliability, and cost
- Reduce work: optimize large images, remove unnecessary third-party requests, and avoid repeatedly loading the same assets.
- Make failures visible: record the input URL or file, renderer version, exit status, elapsed time, and output size.
- Use bounded waits: a timeout prevents a page with a hanging request from occupying a worker forever.
- Retry carefully: retry transient network failures, but do not hide deterministic CSS or permission errors behind repeated attempts.
- Protect the worker: isolate untrusted HTML/CSS, limit file and network access, and enforce CPU, memory, and execution-time limits.
- Estimate cost: software conversion has no required physical equipment; your practical costs are compute, storage, bandwidth, and any hosted rendering service.
9. Or skip the browser setup
If your HTML is reachable by URL, ScreenshotNeo can return a PDF from one API request. See the ScreenshotNeo documentation for all options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/document.html -d format=pdf -o document.pdf
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={
"access_key": "YOUR_API_KEY",
"url": "https://example.com/document.html",
"format": "pdf",
},
timeout=90,
)
r.raise_for_status()
open("document.pdf", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com/document.html',
format: 'pdf'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('document.pdf', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. It also provides an MCP server for AI agents, including Claude and Cursor, with screenshot, page-info, and PDF tools. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.
Create a free ScreenshotNeo account and start with 1,000 screenshots each month at no cost.
10. FAQ
Can I convert HTML to PDF without installing a converter?
Yes. Open the file in Chrome and use Print → Save as PDF. This is the simplest one-off method.
Does PDF preserve JavaScript?
No. JavaScript may affect what is rendered before capture, but the saved PDF is a static representation.
Which method should I use for a batch job?
Use Chrome Headless when browser fidelity and JavaScript matter. Use WeasyPrint when its CSS model fits your templates and you want a focused Python or CLI pipeline.
How do I print an HTML file on Android?
In Chrome, open the file or page, choose More → Share → Print, select Save as PDF and a location, then tap Print. See Google’s mobile print guidance.
Can a local HTML file be sent directly to ScreenshotNeo?
The API captures a URL. Host the HTML and its required assets at a reachable address, then pass that URL to the API.


