Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
The most reliable programmatic method is to load the HTML in a real browser with Puppeteer or Playwright, wait until the page is ready, call page.pdf(), and save the returned PDF bytes (or specify an output path). Both libraries use print CSS by default; switch to screen media only when that is what you intend to reproduce.
Choose the conversion method
Your best method depends on where the HTML lives and how much control you need.
| Situation | Recommended approach | Output handling |
|---|---|---|
| A Node.js script or service already uses Chromium | Puppeteer | Write directly with path or receive a Uint8Array |
| A project already uses Playwright | Playwright page.pdf() |
Write with path or receive a buffer |
| You need a repeatable API call without maintaining a browser | ScreenshotNeo PDF endpoint | Save the HTTP response as a PDF file |
The official references do not establish that Puppeteer is faster, more accurate, or more reliable than Playwright for every page. If those qualities matter, test your actual HTML, fonts, images, and deployment environment.
Recommended Free Tools
Generate a PDF with Puppeteer
Install and create a minimal script
Install Puppeteer in a Node.js project:
npm install puppeteer
Create html-to-pdf.mjs:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('file:///absolute/path/to/document.html', {
waitUntil: 'networkidle0'
});
await page.pdf({
path: 'output.pdf',
format: 'A4',
printBackground: true,
margin: {
top: '20mm',
right: '15mm',
bottom: '20mm',
left: '15mm'
}
});
await browser.close();
Run it with node html-to-pdf.mjs. Puppeteer’s documented flow is to launch a browser, navigate to the document, call page.pdf(), and close the browser. The guide also states that Page.pdf() waits for fonts by default (Puppeteer PDF generation guide).
#1 Best Overall
- INNOVATIVE CARTRIDGE-FREE PRINTING — No more dealing with lots of tiny ink cartridges; With this wireless document and photo printer each ink bottle set is equivalent to about 90 individual cartridges²
- LESS FREQUENT INK REPLACEMENT — Replacement ink bottles don't have to be changed nearly as often as ink cartridges¹; When you choose this combination printer, scanner and copier you can print up to 4,500 pages black/7,500 color³
- COLOR PRINTING — Up to 2 years of ink in the box4 (and with every replacement ink set) for fewer out-of-ink frustrations
- ZERO CARTRIDGE WASTE — By using an Epson EcoTank printer you can help reduce the amount of cartridge waste ending up in landfills
- HOME PRINTER DESIGNED FOR RELIABILITY — The Epson EcoTank ET-2800 All-in-One Supertank Color Printer creates vivid, detailed prints and documents thanks to Micro Piezo Heat-Free Technology; Fire off 10 ISO pages per minute1 to easily finish large jobs
Use a URL or inline HTML
For a web page, replace the file:// URL with an HTTPS URL. For an HTML string, use page.setContent():
await page.setContent(`
<h1>Invoice</h1>
<p>Generated from an HTML string.</p>
`, { waitUntil: 'networkidle0' });
const pdfBytes = await page.pdf({
printBackground: true,
preferCSSPageSize: true
});
await import('node:fs/promises').then(fs => fs.writeFile('invoice.pdf', pdfBytes));
When no path is supplied, Puppeteer returns PDF bytes. This lets you upload the result to object storage, attach it to an email, or send it as an HTTP response instead of writing a local file (Page.pdf() API).
Control paper size, layout and appearance
The defaults are convenient, but explicit options prevent surprises when a document moves between environments. Puppeteer documents these PDF options (PDFOptions reference):
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →- Paper:
format: 'A4','Letter', or another supported format. Ifformatis set, it takes precedence overwidthandheight. - Custom dimensions: set
widthandheightwith CSS units such asmm,in, orpx. - Orientation: use
landscape: truefor wide tables or slides. - Margins: set
top,right,bottom, andleftexplicitly. - CSS page size:
preferCSSPageSize: truegives an@pagerule priority over the generated paper size. - Backgrounds:
printBackgrounddefaults to false. Set it totruewhen background colors, charts, or images are part of the design. - Headers and footers: they are not displayed by default. Enable the relevant display option and provide templates when you need page numbers or a title.
- Scale: adjust the PDF scale when content is slightly too large or too small, rather than shrinking the browser viewport arbitrarily.
- Tagged output: the API describes tagged PDF generation as experimental; verify accessibility requirements with the exact version you deploy.
Print CSS versus screen CSS
page.pdf() uses the print CSS media type by default and adjusts colors for printing. Add print rules for page breaks, hidden navigation, and readable margins:
@media print {
nav, .cookie-banner, .screen-only { display: none; }
.break-before { break-before: page; }
a { color: #000; text-decoration: none; }
}
If the PDF should look like the on-screen version, call await page.emulateMediaType('screen') immediately before generating it. This behavior is documented in the Page.pdf() API.
Rank #2
- CARTRIDGE-FREE PRINTING — Print lab-quality photos, graphics and creative projects; Get vibrant colors and sharp text with Epson's high-accuracy printhead and Claria ET Premium 6-color inks
- INK BOTTLES — Save on photos1 and creative projects with affordable in-house printing; All-in-one printer allows you to print 4" x 6" photos for about 4 cents each vs. 40 cents with traditional ink cartridges1
- LESS FREQUENT INK REPLACEMENT — Replacement ink bottles don't have to be changed nearly as often as ink cartridges¹; Printer, scanner and copier lets you print up to 6,200 color pages³
- PRINT FOR LONGER — Up to 2 years of ink in the box² (and with every replacement ink set) for fewer out-of-ink frustrations with this wireless printer
- ZERO CARTRIDGE WASTE — Epson EcoTank printer helps reduce the amount of cartridge waste ending up in landfills; Cartridge-free printer uses high-yield ink bottles; Each replacement ink bottle set is equivalent to about 100 individual ink cartridges⁴
Generate a PDF with Playwright
Playwright exposes a comparable API. Install it and its browser binaries:
npm install playwright
npx playwright install chromium
Then create playwright-pdf.mjs:
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('file:///absolute/path/to/document.html', {
waitUntil: 'networkidle'
});
await page.pdf({
path: 'output.pdf',
format: 'A4',
printBackground: true,
margin: { top: '20mm', right: '15mm', bottom: '20mm', left: '15mm' }
});
await browser.close();
Playwright returns a PDF buffer when you omit path, and its API documents the path option for writing directly to disk. It also uses print media by default; call await page.emulateMedia({ media: 'screen' }) before page.pdf() when screen styling is required (Playwright Page API).
Free tools Windows power users keep installed
One-click scans. No signup required.
Wait for application-rendered content
Navigation completion does not guarantee that a single-page application has finished rendering its report. Wait for a meaningful selector or application state before exporting:
await page.goto('https://example.com/report', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('#report-ready');
await page.pdf({ path: 'report.pdf', printBackground: true });
Choose the readiness condition your application can actually prove. A fixed delay can help with an unavoidable animation, but a selector or explicit “ready” state is less brittle.
Make the file downloadable from a Node.js server
If a user clicks a button in your application, generate the bytes and return them with download headers:
Rank #3
- SET IT UP ONCE AND PRINT WITH CONFIDENCE. No complicated maintenance. Just easy, reliable printing you can count on.
- INK FOR YEARS. NOT MONTHS. Up to 2 years of ink included. Get thousands of pages of cartridge-free printing. More pages, less hassle
- KEEPS PRINTING WELL AFTER COMPETITORS HAVE QUIT. No complex maintenance. Sharper text, richer colors.[2] Only with HP Smart Tank
- PREMIUM SUPPORT - Strong technical expertise to solve issues faster
- THE LAST PRINTER YOU'LL EVER NEED. Enjoy years of refillable, cartridge-free printing.
import express from 'express';
import puppeteer from 'puppeteer';
const app = express();
const browser = await puppeteer.launch();
app.get('/download.pdf', async (req, res) => {
const page = await browser.newPage();
try {
await page.goto('https://example.com/report', { waitUntil: 'networkidle0' });
const pdf = await page.pdf({ format: 'A4', printBackground: true });
res.type('application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename="report.pdf"');
res.send(Buffer.from(pdf));
} finally {
await page.close();
}
});
app.listen(3000);
Keep the browser process alive for multiple requests, create a fresh page per request, and close each page in a finally block. Close the browser during graceful application shutdown.
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 & 11Or skip the browser setup
ScreenshotNeo provides a website screenshot and PDF API when you prefer one HTTP request over installing and operating Chromium. Its PDF-capable endpoint is https://api.screenshotneo.com/v1/shot. The service accepts the page URL and returns the file response; consult the ScreenshotNeo documentation for current PDF parameters such as paper size, margins, orientation, and page ranges.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
For a PDF request, add the documented PDF output parameter while keeping the same endpoint and save the response with a .pdf filename. The equivalent request forms are:
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`ScreenshotNeo failed: ${res.status}`);
const bytes = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));
ScreenshotNeo removes cookie-consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server includes take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan. Create a free ScreenshotNeo account to get started.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesTroubleshooting and quality checks
The PDF is blank or missing content
- Verify that the URL is reachable from the machine running the browser, not only from your laptop.
- Wait for the selector that proves your application rendered its content.
- Check that client-side errors are not preventing the page from mounting.
- For a local file, use an absolute
file://URL and confirm relative assets resolve from that directory.
Fonts or images are wrong
- Wait for the page’s real ready state; Puppeteer waits for fonts by default, but your image or data request may still be pending.
- Use absolute, accessible asset URLs and confirm the server returns the correct content type.
- Set
printBackground: truewhen the missing element is a background graphic.
Pages break in awkward places
- Add print rules such as
break-before,break-after, andbreak-inside: avoidto the relevant blocks. - Set an explicit paper format, margins, and orientation.
- Use
preferCSSPageSize: truewhen your@pagedefinition is authoritative.
The PDF looks different from the browser
That is usually a media-type difference. PDF generation uses print CSS; either add print-specific rules or emulate screen media before calling page.pdf(). Also remember that print color adjustment and disabled backgrounds can change appearance.
Rank #4
- Wireless Bluetooth Printer: Portable thermal printer compatible with iPhone, Android phones, iPad and tablet computers via Bluetooth. For smartphones, please download the "Nada Print" App. You can also connect to laptops and computers for printing using a USB-C cable. (Note: Laptops and computers can only be connected via USB and require the installation of a driver first. Bluetooth connection is not supported.)
- No-ink printing: Only supports US Letter and A4 size thermal paper.(Doesn't support regular paper) The no-ink portable thermal printer uses direct thermal technology, requiring no ink, toner or ribbons, making it environmentally friendly, cost-effective and time-saving. The thermal printer package comes with a roll of US Letter thermal printing paper. Note: When installing the paper, remember to switch the paper size switch on APP
- Clear Print: NDYIN N80 portable thermal printer adopts high-definition printing technology, with a 203DPI resolution to provide you with clear printing results. This mobile printer is compatible with roll paper, folded paper and tattoo transfer paper, supporting printing from your mobile phone PDF, Word, pictures and web pages anytime and anywhere. It is recommended to use our NDYIN thermal paper to achieve good printing quality
- Portable wireless printer for travel: The thermal printer is equipped with a built-in 1500mAh rechargeable battery, which can print 160 sheets of 8.5" x 11" thermal paper after being fully charged. It weighs only 1.5 pounds and is compact in size. This ink-free portable printer can be easily carried in a backpack or briefcase! It is perfect for business travel, cars, small offices, construction sites, schools and homes. You can print documents, contracts, invoices and boarding passes anytime and anywhere
- The N80 thermal printer has a wide range of uses. The package includes the N80 printer, a roll of US Letter paper(7m/roll), a user manual, a guide card, a type-C soft cable and a type C adapter. Note: The charging adapter is not included. Special thermal paper is required for use; ordinary paper cannot be used. This ink-free portable thermal printer is suitable for various scenarios such as home, school, travel, office, and outdoor, meeting the printing needs of different groups of people. This tattoo template printer is also compatible with tattoo transfer paper, making it an ideal choice for tattoo art
The process hangs or consumes too much memory
- Set a navigation timeout appropriate for your site and investigate requests that never finish.
- Reuse one browser process but close pages after each job.
- Limit concurrent PDF jobs and avoid creating a new browser for every request.
- Capture only the page state and assets required for the document.
Playwright cannot find Chromium
Run npx playwright install chromium in the same environment where the script executes, including your container or CI image.
A production checklist
- Define the exact URL or HTML string and the intended paper size.
- Add print CSS for navigation, page breaks, links, and colors.
- Choose a deterministic readiness signal for asynchronous content.
- Set margins, orientation, backgrounds, and CSS page-size precedence explicitly.
- Test local fonts, remote images, charts, and long tables.
- Save bytes to a controlled destination or return them with
application/pdfandContent-Disposition. - Log failures and validate the generated file before presenting it as a download.
Frequently Asked Questions
Can I convert HTML to PDF without JavaScript?
This workflow uses browser automation because it renders the same HTML, CSS, fonts, and client-side content a user sees. A non-browser converter may require different CSS and JavaScript support; choose it only after checking compatibility with your document.
Should I use Puppeteer or Playwright?
Use the library already established in your project. Both document a page PDF API with print-media defaults, screen-media emulation, and file output. The cited documentation does not establish a universal speed or fidelity winner.
Can the generated PDF be returned from an API instead of saved?
Yes. Omit the Puppeteer path option, receive the returned bytes, set the response type to application/pdf, and send them with an attachment filename.
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.

