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 minuteUse Playwright or Puppeteer when the page behaves like an application; use WeasyPrint, Paged.js, Vivliostyle CLI, or OpenHTMLtoPDF when it is a print-first document. Browser engines execute JavaScript and match modern CSS, while paged-media engines give you more deterministic pagination without shipping Chromium. Managed services such as Browserless or Doppio are sensible when maintaining browsers, scaling workers, and patching security issues is not part of your team’s operating model. Treat wkhtmltopdf as a migration target for new systems.
Choose by the document you actually have
HTML-to-PDF is not one problem. A server-rendered invoice, a React dashboard with charts, and a long compliance report need different rendering engines. Start with these questions:
- Does the page need client-side JavaScript, canvas charts, a single-page-app route, or data fetched after navigation?
- Do print rules, page breaks, running headers, footnotes, and repeatable pagination matter more than browser pixel fidelity?
- Can your deployment carry a Chromium binary and its memory, patching, and startup cost?
- Do you need a library inside your process, or an HTTP API with retries, queues, and operational support?
| Primary requirement | Best starting point | Why |
|---|---|---|
| JavaScript dashboards, SPAs, charts, web fonts, modern CSS | Playwright or Puppeteer | They drive a real browser and execute the page before printing. |
| Node service with a small abstraction layer | Puppeteer | page.pdf() provides a direct browser-to-PDF path. |
| Polyglot team that wants browser fidelity | Playwright or a managed Browserless-style API | Playwright offers bindings beyond Node; a service removes browser operations from application hosts. |
| Print-heavy, controlled templates with little JavaScript | WeasyPrint, Paged.js, Vivliostyle CLI, or OpenHTMLtoPDF | These are designed around paged media and predictable layout. |
| No browser operations team, bursty traffic, or high volume | Managed API such as Browserless or Doppio | The provider handles browser workers and exposes HTTP or asynchronous workflows; verify residency, quotas, SLA, and price first. |
| Existing wkhtmltopdf deployment | Plan a controlled migration | Current comparison sources describe it as archived or unmaintained, with no modern JavaScript/CSS support. |
Browser-based conversion: Playwright and Puppeteer
Why a real browser wins for dynamic pages
Headless Chromium evaluates scripts, lays out flexbox and grid, loads web fonts, paints canvas and SVG charts, and follows the same print pipeline users receive in a browser. That makes it the practical choice for SPAs and dashboards. The trade-off is operational: Chromium is a large dependency, consumes memory per worker, and must be patched and isolated like any other browser.
Playwright example (Node.js)
Install the library and its browser once in your build or image:
#1 Best Overall
- Create a mix using audio, music and voice tracks and recordings.
- Customize your tracks with amazing effects and helpful editing tools.
- Use tools like the Beat Maker and Midi Creator.
- Work efficiently by using Bookmarks and tools like Effect Chain, which allow you to apply multiple effects at a time
- Use one of the many other NCH multimedia applications that are integrated with MixPad.
npm install playwright
npx playwright install chromium
This script waits for the page to settle, selects print media, and writes a PDF:
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 1
});
await page.goto('https://example.com/report', { waitUntil: 'networkidle' });
await page.pdf({
path: 'report.pdf',
format: 'A4',
printBackground: true,
margin: { top: '18mm', right: '14mm', bottom: '18mm', left: '14mm' }
});
} finally {
await browser.close();
}
})();
Use a selector-based wait instead of relying only on network idle when your application renders after a websocket, timer, or client-side state change:
await page.goto('https://example.com/report', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('[data-report-ready]', { state: 'visible' });
await page.pdf({ path: 'report.pdf', format: 'A4', printBackground: true });
Puppeteer example (Node.js)
Install Puppeteer, which downloads a compatible browser for its normal setup:
npm install puppeteer
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: 'new' });
try {
const page = await browser.newPage();
await page.goto('https://example.com/report', { waitUntil: 'networkidle2' });
await page.pdf({
path: 'report.pdf',
format: 'A4',
printBackground: true,
margin: { top: '18mm', right: '14mm', bottom: '18mm', left: '14mm' }
});
} finally {
await browser.close();
}
})();
Puppeteer’s PDF method uses the print CSS media type by default and waits for fonts. If the design only looks correct under screen styles, call await page.emulateMediaType('screen') before generating the PDF. Browser print also modifies colors; add -webkit-print-color-adjust: exact in your print stylesheet when preserving authored colors is necessary.
Recommended Free Tools
CSS that prevents common surprises
@page {
size: A4;
margin: 18mm 14mm;
}
@media print {
.screen-only { display: none !important; }
.avoid-break { break-inside: avoid; }
h2 { break-after: avoid; }
body { -webkit-print-color-adjust: exact; }
}
For charts, wait for the chart library’s own “ready” signal or a DOM marker. For images loaded lazily, scroll or trigger the application’s image loader before printing. For authenticated pages, create a browser context with the required cookies or headers and never log those credentials.
Print-first engines without a browser binary
WeasyPrint (Python)
WeasyPrint is a strong fit for controlled, print-oriented HTML and CSS where client-side JavaScript is unnecessary. Install it according to your operating system’s documented native dependencies, then:
Rank #2
pip install weasyprint
from weasyprint import HTML
HTML('https://example.com/report').write_pdf('report.pdf')
You can also render a local template with an explicit base URL so relative stylesheets and images resolve:
from weasyprint import HTML
HTML(string=html, base_url='/srv/report-assets').write_pdf('report.pdf')
Choose WeasyPrint when deterministic pagination outweighs executing page JavaScript. A page that depends on React hydration or a canvas chart should be rendered by a browser first, or redesigned as server-generated markup and images.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Paged.js, Vivliostyle CLI, and OpenHTMLtoPDF
Paged.js and Vivliostyle CLI implement browser-oriented paged-media workflows and are useful when CSS page rules, generated content, and book-like layout are central. OpenHTMLtoPDF is a Java option for teams that want a library rather than a browser process. The comparison material also lists dompdf, mPDF, xhtml2pdf, and OpenHTMLtoPDF as options when avoiding a browser binary. Confirm each engine’s supported CSS, font handling, and JavaScript limitations against your templates; “HTML support” is not interchangeable across engines.
Managed PDF APIs and browser services
When an API is the better architecture
A managed service can remove browser image maintenance, worker autoscaling, queueing, and much of the patching responsibility from your application. This is attractive for bursty jobs or teams that cannot dedicate an operations path to Chromium. Doppio’s 2026 options guide presents managed APIs as a practical choice for many projects, especially those needing reliability, multiple languages, or high volume; that is a vendor opinion, not an independent market finding.
Browserless
Browserless documents exporting any webpage or HTML as PDF through a REST /pdf endpoint and browser connections for waiting on dynamic content. Its examples include A4 output, print backgrounds, headers, and footers, and show both Puppeteer and Playwright connections. Before committing, check current authentication, limits, data residency, retention, and contractual availability for your region.
Doppio
Doppio describes three approaches—legacy wkhtmltopdf, self-hosted Puppeteer/Playwright, and managed HTML-to-PDF APIs—and positions managed APIs as a way to avoid maintaining Chrome, scaling workers, and security controls yourself. Treat those statements as vendor claims and validate them with a representative document and your own compliance requirements.
Free tools Windows power users keep installed
One-click scans. No signup required.
Why wkhtmltopdf should usually be a migration target
Comparison sources describe wkhtmltopdf as archived in 2023, warn about unpatched CVEs, and note that it lacks modern JavaScript and CSS support. A legacy static template may still render acceptably, so migration should be controlled rather than a blind replacement.
- Capture PDFs from representative templates, including long tables, fonts, images, and failure cases.
- Implement the new renderer beside the old one and compare text extraction, page count, visual diffs, and links.
- Review sandboxing, outbound network access, secrets exposure, and patch cadence.
- Switch traffic gradually, retaining a rollback path until business owners accept the differences.
Performance, throughput, and cost
Browser startup dominates cold jobs. Keep a bounded pool of warm workers, reuse contexts when isolation permits, and cap concurrency so memory pressure does not turn into timeouts. Close pages and contexts, set navigation and PDF timeouts, and record document duration, browser version, page URL, and failure reason.
A PDF4.dev 2026 benchmark reports a complex document at 13 ms on a warm Playwright browser instance, 58 ms for Puppeteer, and 629 ms for WeasyPrint. Those are workload-specific figures from one publisher, not a universal ranking; your templates, fonts, network, hardware, and warm-up policy can reverse the result.
Self-hosting has no per-document vendor fee but carries engineering costs for browser images, security patches, scaling, observability, and retries. A managed API converts much of that into usage pricing and contractual limits. Compare total cost per successful PDF, not just the headline request price, and include failed-job behavior, storage, egress, and support.
Security and reliability checklist
- Run browser workers in a sandboxed, least-privilege environment with restricted outbound access.
- Do not expose internal metadata services or private network ranges to arbitrary user-supplied URLs.
- Keep authentication headers and cookies out of logs and error payloads.
- Pin and patch browser and system packages; rebuild images regularly.
- Set navigation, resource, and overall job timeouts. Retry only failures that are safe to retry.
- Record whether a job failed during navigation, asset loading, layout, or file upload.
- Use deterministic fonts and assets when legal or regulatory output must be reproducible.
- For a managed service, verify region, retention, encryption, quotas, SLA, webhook security, and deletion behavior.
Common failures and fixes
The PDF is blank or missing chart data
The capture happened before hydration or chart painting. Wait for a page-specific ready selector, network completion plus a short application-controlled signal, or an explicit chart-render event. Do not rely on a fixed delay as your only synchronization method.
Styles look different from the website
Print media is active by default in Puppeteer. Add print rules deliberately, or emulate screen media when that is the intended design. Check that every stylesheet, font, and image URL is reachable from the renderer.
Rank #4
- Transform audio playing via your speakers and headphones
- Improve sound quality by adjusting it with effects
- Take control over the sound playing through audio hardware
Fonts fall back or text reflows
Wait for document.fonts.ready when using custom browser code, verify font responses are successful, and package licensed fonts with the worker when external loading is unreliable. WeasyPrint and browser engines may support different font formats and CSS features, so test the actual files.
Long tables split badly
Use print CSS such as break-inside: avoid on rows or grouped blocks where supported, repeat table headers, and test rows that span multiple pages. If pagination rules are the central requirement, a paged-media engine may be a better fit than a browser.
Navigation times out
Find the blocking request in network logs. Permit required domains, block unnecessary trackers, and distinguish a slow origin from a page that never reaches the expected state. A retry should use a fresh page or context when the first navigation left corrupted state.
Self-hosted workers run out of memory
Lower concurrency, recycle workers after a bounded number of jobs, close every page, and avoid loading unbounded asset sets. Measure warm and cold memory separately before selecting worker limits.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If you need a hosted capture endpoint, ScreenshotNeo is the first alternative to try: it removes consent banners, newsletter popups, and chat widgets before capture, bills only clean shots, and has a $5 paid plan for 3,000 shots.
It can return PNG, JPEG, WebP, or PDF from one GET request. The same service supports full-page captures, lazy-image loading, CSS-selector element capture, device and viewport settings, retina scale, PDF paper size and margins, page ranges, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
Crashes, 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 minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the page verdict and billing status in headers. Every feature is on every plan: 1,000 shots per month are free with no card; paid plans start at $5 for 3,000. Yearly billing provides two months free.
Best Value
- Full-featured professional audio and music editor that lets you record and edit music, voice and other audio recordings
- Add effects like echo, amplification, noise reduction, normalize, equalizer, envelope, reverb, echo, reverse and more
- Supports all popular audio formats including, wav, mp3, vox, gsm, wma, real audio, au, aif, flac, ogg and more
- Sound editing functions include cut, copy, paste, delete, insert, silence, auto-trim and more
- Integrated VST plugin support gives professionals access to thousands of additional tools and effects
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/report -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com/report"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com/report' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo documentation for response and PDF options, then create a free account to use 1,000 screenshots each month with no card.
A practical selection process
- Render one representative document with your real fonts, charts, images, and authentication flow.
- Decide whether JavaScript execution is mandatory. If yes, start with Playwright or Puppeteer; if no, measure a paged-media engine.
- Measure cold start, warm throughput, peak memory, failure rate, and page-to-page visual differences under your expected concurrency.
- Choose self-hosting only if your team can own browser patching, isolation, observability, and capacity.
- Choose a managed API only after checking residency, retention, quotas, SLA, retries, webhook security, and total cost.
- Keep golden PDFs and automated visual or text checks so renderer upgrades do not silently change regulated or customer-facing documents.
Frequently Asked Questions
Does Puppeteer wait for web fonts before creating a PDF?
Its documented PDF method waits for fonts by default. You should still verify font responses and test your own custom-font files.
When is a paged-media engine preferable to Chromium?
Choose one when templates are mostly static and repeatable pagination, running content, and print rules matter more than executing client-side JavaScript.
Is the 2026 Playwright benchmark a guaranteed speed ranking?
No. The 13 ms, 58 ms, and 629 ms figures come from one PDF4.dev workload on warm instances and should not be generalized to every document or deployment.
What should I test before replacing wkhtmltopdf?
Use representative templates and compare page count, text, links, fonts, images, long-table breaks, security controls, and rollback behavior in a side-by-side rollout.
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.

