The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
How do you convert HTML to PDF? Choose a browser print flow when the page is already rendered for a person, Puppeteer or Playwright when you need an automated browser and JavaScript fidelity, WeasyPrint when a Python application needs a document-oriented renderer, and Prince when advanced paginated-media composition justifies a commercial engine. The best HTML-to-PDF library depends on rendering fidelity, print layout control, deployment language, security boundaries, and required PDF features—not on a universal performance winner.
Start with the output you actually need
HTML-to-PDF conversion has two different meanings. You may want a PDF that matches a live website after JavaScript, fonts, and client-side data have loaded. Or you may want a typeset document with deliberate page dimensions, running headers, footers, numbering, bookmarks, and repeatable page breaks. Browser automation is usually the safer choice for the first requirement; a paged-media renderer is often a better fit for the second.
| Method | Best fit | Important behavior |
|---|---|---|
| Browser print interface | A person prints an already rendered page | Uses the browser’s print preview and save-as-PDF workflow; little server-side integration |
| Puppeteer | JavaScript or TypeScript services that need Chromium automation | Page.pdf() uses print CSS by default; screen media must be selected explicitly |
| Playwright | Browser automation with Playwright’s multi-browser tooling and PDF options | page.pdf() returns a PDF buffer and uses print CSS by default |
| WeasyPrint | Python applications producing document-style PDFs | A Python HTML/CSS renderer, not a full WebKit or Gecko browser; supports links, bookmarks, attachments, and forms |
| Prince | Publishing systems needing extensive paged-media controls | Commercial HTML/XML-to-PDF engine with page dimensions, headers, footers, numbering, and page-break controls |
Browser print: the simplest manual method
When a person has opened the page, wait for the content to finish rendering, then use the browser’s Print command and select “Save as PDF.” This preserves the normal user workflow and avoids operating a server-side browser. It is appropriate for occasional exports, support instructions, and pages where a human must confirm the final state.
It is not a dependable batch conversion API. The result can depend on the browser, extensions, logged-in session, print settings, blocked resources, and the timing of client-side rendering. For repeatable jobs, move to an API-driven renderer and make the print assumptions explicit.
#1 Best Overall
Convert HTML with Puppeteer
Puppeteer documents a sequence of launching a browser, opening a page, navigating to the content, calling Page.pdf(), and closing the browser. Font loading is awaited by default in the documented PDF-generation flow. The API reference is at pptr.dev/api/puppeteer.page.pdf.
Minimal runnable Node.js example
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com/invoice/123', {
waitUntil: 'networkidle0'
});
await page.pdf({
path: 'invoice.pdf',
format: 'A4',
printBackground: true,
margin: { top: '18mm', right: '14mm', bottom: '18mm', left: '14mm' }
});
} finally {
await browser.close();
}
})();
Page.pdf() renders with print CSS by default. If the page was designed for screen media and you intentionally want that styling, select it before generating the PDF:
await page.emulateMediaType('screen');
await page.pdf({ path: 'screen-styled.pdf', printBackground: true });
Print color treatment can also change the visual result. Test backgrounds, gradients, and branded colors under the exact browser and PDF settings you will deploy. For a stable document, prefer print-specific rules such as @media print and @page rather than relying on a user’s preview settings.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteWhen Puppeteer is the right choice
- The source depends on client-side JavaScript, authenticated browser state, or a browser-only layout engine.
- You need the same DOM, fonts, and CSS behavior that a Chromium user sees.
- Your service is already JavaScript/TypeScript and can operate a browser process.
Convert HTML with Playwright
Playwright’s page.pdf() returns a PDF buffer. Its API documents an output path and options for page sizing and CSS behavior. Like Puppeteer, it uses print CSS by default, so screen styling requires an explicit media choice.
import { chromium } from 'playwright';
import { writeFile } from 'node:fs/promises';
const browser = await chromium.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com/report', { waitUntil: 'networkidle' });
const pdf = await page.pdf({
path: 'report.pdf',
format: 'A4',
printBackground: true,
preferCSSPageSize: true,
margin: { top: '16mm', right: '14mm', bottom: '16mm', left: '14mm' }
});
await writeFile('report-copy.pdf', pdf);
} finally {
await browser.close();
}
Use Playwright when its browser-context model, project tooling, or existing test infrastructure is already part of your stack. Do not assume that switching between Playwright and Puppeteer will produce byte-for-byte identical PDFs: browser versions, fonts, print settings, and page timing still matter.
Convert HTML with WeasyPrint
WeasyPrint 70.0 is documented as a Python 3.10+ HTML/CSS rendering engine under the BSD license. The project describes itself as “a visual rendering engine for HTML and CSS that can export to PDF.” It is not a wrapper around a complete WebKit or Gecko browser, so JavaScript-dependent pages may require a browser renderer instead.
Rank #2
Python API from a string
from weasyprint import HTML
html = '''
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
@page { size: A4; margin: 18mm 14mm; }
h1 { break-after: avoid; }
.invoice { page-break-inside: avoid; }
</style>
</head>
<body>
<h1>Invoice</h1>
<div class="invoice">Thank you.</div>
</body>
</html>
'''
HTML(string=html, base_url='https://example.com/').write_pdf('invoice.pdf')
Set base_url whenever the HTML contains relative images, stylesheets, fonts, or other resources. Without a meaningful base URL, those references cannot be resolved reliably. The API also exposes URL-fetching configuration, which lets an application control how external resources are retrieved.
Files, URLs, and the command line
The API accepts HTML strings, files, file objects, and URLs. The command-line interface is useful for batch jobs and container entrypoints; keep the input and output paths explicit and make sure the runtime has the system libraries and fonts required by your distribution.
WeasyPrint’s document features include hyperlinks, bookmarks, attachments, and forms. Its documentation says PDF/A and PDF/UA generation is supported but does not guarantee that every generated file will satisfy those standards. Validate a PDF against the specific conformance profile your regulator or archive requires.
Use Prince for advanced paged-media publishing
Prince is a commercial HTML/XML-to-PDF engine. Its user guide and styling documentation describe controls for page dimensions, headers, footers, numbering, and page breaks, making it a candidate for books, invoices, catalogs, and reports where pagination is part of the product rather than a side effect.
Prince documentation also describes HTML, Markdown, and XML input and server-side integration. Treat the renderer and its resource-fetching configuration as a security boundary, particularly when users can influence markup or URLs. The reviewed documentation does not establish a current price or affiliate program, so obtain commercial terms directly from YesLogic before budgeting.
Write CSS that survives PDF pagination
Define the paper and margins
@page {
size: A4 portrait;
margin: 18mm 14mm 20mm;
}
@page :first {
margin-top: 12mm;
}
@media print {
.screen-only { display: none; }
a { color: #000; text-decoration: none; }
}
Browser engines and document renderers share many CSS concepts but not identical feature sets. Keep critical layout rules simple, test the exact renderer version, and avoid assuming that a screen flex or grid layout will paginate exactly as it does in a viewport.
Control breaks and repeating content
- Use
break-before,break-after, andbreak-insidefor modern pagination rules, with legacypage-break-*declarations when your renderer requires them. - Keep headings with the following content using
break-after: avoid. - Protect signatures, table rows, and compact cards with
break-inside: avoid, while accepting that an oversized element may still need to split. - Use renderer-specific running-header features only after confirming support in the version you deploy.
Make assets deterministic
PDF jobs fail or vary when fonts, images, or API data are still loading. Host required assets where the renderer can reach them, use absolute URLs or a correct base URL, wait for the page state that means “ready,” and log failed resource requests. For authenticated resources, pass credentials through the renderer’s supported context or fetch the data server-side; never place long-lived secrets in public HTML.
How to choose the best HTML-to-PDF library
| Question | Prefer a browser API when… | Prefer WeasyPrint or Prince when… |
|---|---|---|
| Does the page need JavaScript? | Client-side rendering, charts, or browser APIs determine the final DOM. | The input is principally HTML/CSS and can be rendered without application JavaScript. |
| Must it match a live website? | Pixel and behavior fidelity to a Chromium page matter. | A controlled document layout is more important than browser parity. |
| How much page composition is needed? | Basic paper size, margins, and print CSS are enough. | Running furniture, numbering, sophisticated breaks, or publishing workflows are central. |
| What is the integration environment? | Your service already runs Node.js and can manage browser workers. | Your application is Python, or a dedicated renderer fits the deployment model. |
| Which PDF features matter? | You mainly need a visual PDF of a web page. | You need document features such as bookmarks, attachments, forms, or a paged-media workflow. |
There is no evidence here of a universal speed or visual-quality winner. Select a representative set of pages, render them in the versions you will ship, and inspect text selection, links, fonts, page breaks, images, and accessibility requirements before committing.
Security and reliability checklist
- Untrusted markup: isolate rendering of user-controlled HTML and CSS. WeasyPrint’s web-app guidance warns that user-modifiable content can create security problems.
- Network access: restrict outbound requests, allow-list hosts where possible, and prevent access to internal metadata endpoints.
- Resource limits: set job timeouts, maximum input sizes, browser-process limits, and temporary-directory quotas.
- Authentication: use short-lived cookies or tokens, redact credentials from logs, and ensure generated PDFs do not expose private URLs.
- Repeatability: pin browser or renderer versions, fonts, locale, timezone, and paper settings; record these with the job.
- Validation: open the produced file, check its page count and size, and run PDF/A, PDF/UA, or business-rule validation when required.
Troubleshooting common failures
The PDF is blank or missing late content
Cause: conversion started before client-side rendering completed, or a resource request failed. Wait for a meaningful selector or application-ready signal instead of relying only on a short sleep. In a browser API, inspect console and request failures and confirm that the page is not still showing a loading shell.
The layout looks like the screen version
Cause: print CSS is the default for Puppeteer and Playwright, or print rules intentionally hide or restyle elements. Decide which medium you want. For screen styling, select the screen media type before calling pdf(); for a print document, move essential rules into print styles and test color handling.
Images, fonts, or CSS are absent in WeasyPrint
Cause: relative URLs lack a base URL, the process cannot reach the host, or the resource is blocked by authentication or TLS policy. Supply base_url, use accessible absolute URLs, configure URL fetching deliberately, and log the failing resource.
Pages split invoices or cards awkwardly
Cause: the element is taller than the available page area or lacks break rules. Add appropriate break-inside: avoid and heading rules, but design a fallback for content that genuinely cannot fit on one page.
Rank #4
- Programming Language Lover Code Apparel. App or Web Design and Development Expert Funny Dress. Best Valentines Idea For Coding Lover. HTML Code or Meaning Costume
- Funny I Know HTML - How To Meet Ladies Computer Programmer Quotes
- Lightweight, Classic fit, Double-needle sleeve and bottom hem
The PDF passes visual inspection but fails a standard
Cause: visual similarity is not the same as PDF/A or PDF/UA conformance. Use a validator for the exact profile and treat WeasyPrint’s statement that conformance is not guaranteed as a reason to verify, not as a certification.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteBrowser jobs consume too many resources
Cause: launching a fresh browser for every request, leaking pages, or allowing unbounded concurrent jobs. Reuse a controlled browser process where safe, close pages and contexts in finally blocks, queue work, and enforce per-job timeouts. Measure your own workload rather than assuming a published benchmark.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server that can return a clean screenshot or PDF from one request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.
Use the API options for PDF output, paper size, margins, landscape mode, and page ranges. The same service also supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, custom CSS and JavaScript, clicks before capture, selector hiding, waits for selectors, delays or network idle, request and resource blocking, custom headers, cookies, user agents and Authorization, timezone and geolocation, transparent backgrounds, image resizing, configurable caching, signed public-image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.
One-call example
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for the PDF output option and the complete parameter list. Python and Node.js clients can use the same endpoint:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients, so an AI agent can request captures without you maintaining browser orchestration. 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.
Cost, performance, and operations
Browser automation carries the operational cost of browser binaries, memory, startup time, and concurrency management. A document renderer can be simpler to deploy for static HTML/CSS, while a commercial engine may reduce the engineering needed for sophisticated pagination. These are architecture trade-offs, not guarantees of speed.
Best Value
For any option, cache immutable source documents, avoid downloading the same fonts repeatedly, and separate conversion from request handling with a queue when jobs can run for seconds or minutes. Record input URL or document ID, renderer version, paper settings, duration, output size, page count, and failure reason. For browser APIs, keep navigation and PDF timeouts distinct so a slow origin is distinguishable from a PDF-generation failure.
FAQ
Is HTML-to-PDF a browser problem or a CSS problem?
It is both. A browser API reproduces runtime page behavior, while a document renderer emphasizes CSS paged media. Decide which behavior is authoritative before choosing a tool.
Recommended Free Tools
Can I use WeasyPrint for a JavaScript-heavy single-page app?
Not reliably when JavaScript is required to create the final content. Render the page in a browser first, or provide WeasyPrint with already-materialized HTML and assets.
Why do two browser libraries produce different PDFs?
Browser engine versions, installed fonts, print media rules, color settings, resource timing, and locale can differ even when the API calls look similar.
What should I test before shipping?
Test representative short and long documents, missing images, web fonts, tables crossing pages, right-to-left or localized text, authenticated assets, timeouts, and the PDF conformance profile your users require.
Frequently Asked Questions
Which tool should I start with for a JavaScript-rendered website?
Start with Puppeteer or Playwright, because both drive a browser and document print-CSS behavior explicitly. Choose based on the automation stack you already operate.
Free tools Windows power users keep installed
One-click scans. No signup required.
Do Puppeteer and Playwright use screen CSS automatically?
No. Their PDF methods use print CSS by default. Select screen media deliberately when that is the intended design.
When is a commercial renderer justified?
Prince is worth evaluating when precise paged-media composition—running headers, footers, numbering, and controlled breaks—is central to the product and licensing fits your budget.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

