ScreenshotNeo

BlogHTML to image & PDF

HTML Text to PDF Converter Online

Convert HTML text to PDF online with browser printing, Puppeteer, wkhtmltopdf, hosted APIs, print CSS, troubleshooting, and automation examples.

By the ScreenshotNeo team1 October 20266 min read

Quick answer: For a one-off conversion, open the HTML in a browser, wait for it to finish loading, press Ctrl/Cmd + P, and choose Save as PDF. For repeatable jobs, use Puppeteer with Chromium, wkhtmltopdf, or a hosted HTML-to-PDF API. Add print CSS with @media print and @page so the PDF has the right paper size, margins, page breaks, and visible content.

Choose the right HTML-to-PDF method

Method Best for Trade-offs
Browser print Private, occasional conversions Manual; output depends on browser settings and loaded assets
Puppeteer CI, reports, invoices, JavaScript-heavy pages Requires Node.js and a browser runtime
wkhtmltopdf Self-hosted command-line batches Older Qt WebKit engine may lack modern CSS and JavaScript support
Hosted API Teams that do not want to operate browsers Review privacy, retention, pricing, and regional processing

1. Convert HTML text with your browser

Put the text in an HTML file, open it in a current browser, and select Print → Save as PDF. The browser waits for the document to finish loading before opening the print dialog when you call window.print() (MDN).

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Report</title>
  <style>
    @page { size: A4; margin: 18mm; }
    @media print {
      nav, button, .screen-only { display: none !important; }
      a { color: inherit; text-decoration: none; }
      h1, h2, h3 { break-after: avoid; }
      table, img, pre, blockquote { break-inside: avoid; }
    }
    body { font: 16px/1.5 system-ui, sans-serif; max-width: 760px; margin: 2rem auto; }
  </style>
</head>
<body>
  <nav class="screen-only">Site navigation</nav>
  <main>
    <h1>HTML text converted to PDF</h1>
    <p>Replace this paragraph with your content.</p>
  </main>
  <button class="screen-only" onclick="window.print()">Save as PDF</button>
</body>
</html>

@media print applies styles for paper and PDF output, while @page controls paper size, orientation, and margins (MDN print media; MDN @page). In the print dialog, enable background graphics when your design depends on colored backgrounds, and check the preview for clipped content and unexpected page breaks.

2. Generate PDFs with Puppeteer

Puppeteer automates a real Chromium browser. Its Page.pdf() method generates a PDF using print CSS by default and supports paper format, custom dimensions, margins, page ranges, headers and footers, background graphics, CSS page-size preference, and tagged output (Puppeteer API).

Install

npm install puppeteer

Complete Node.js example

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  try {
    const page = await browser.newPage();
    await page.setViewport({ width: 1280, height: 900, deviceScaleFactor: 1 });
    await page.goto('https://example.com', { waitUntil: 'networkidle2', timeout: 60000 });
    await page.evaluate(() => document.fonts.ready);
    await page.pdf({
      path: 'output.pdf',
      format: 'A4',
      printBackground: true,
      preferCSSPageSize: true,
      margin: { top: '18mm', right: '18mm', bottom: '18mm', left: '18mm' },
      displayHeaderFooter: false
    });
  } finally {
    await browser.close();
  }
})();

Use page.emulateMediaType('screen') before page.pdf() when the PDF should use screen styles instead of print styles. Wait for fonts and application data explicitly when a page renders after navigation:

await page.goto(url, { waitUntil: 'networkidle2' });
await page.waitForSelector('#report-ready', { timeout: 30000 });
await page.evaluate(() => document.fonts.ready);
await page.pdf({ path: 'report.pdf', printBackground: true, format: 'Letter' });

Useful Puppeteer options

  • format, or width/height, sets the paper dimensions.
  • margin sets top, right, bottom, and left margins.
  • printBackground: true preserves CSS backgrounds.
  • pageRanges: '1-3' exports selected pages.
  • displayHeaderFooter, headerTemplate, and footerTemplate add running content.
  • preferCSSPageSize: true honors CSS @page size when present.

3. Convert from the command line with wkhtmltopdf

wkhtmltopdf is an open-source LGPLv3 command-line tool that renders HTML with Qt WebKit and can run headlessly (official project).

wkhtmltopdf --print-media-type --page-size A4 --margin-top 18mm --margin-right 18mm --margin-bottom 18mm --margin-left 18mm input.html output.pdf

Use it for controlled, self-hosted batches after checking your pages against its older rendering engine. If modern CSS, modules, or client-side applications are important, compare the result with current Chromium automation.

4. Use an online HTML-to-PDF service

A hosted converter can accept raw HTML or a public URL and return a PDF without your team managing browser processes. For example, HTMLPDF.dev documents a playground and an API based on headless Chromium with controls for paper size, margins, headers, footers, page numbers, backgrounds, scale, and print or screen media. Review its current privacy, retention, pricing, and processing terms before sending confidential HTML.

  • Set @page size and margins.
  • Hide navigation, buttons, ads, and other screen-only controls.
  • Wait for web fonts, images, charts, and client-side data.
  • Use break-before, break-after, and break-inside to control pagination.
  • Enable background graphics when required.
  • Test long tables, wide code blocks, links, and pages with missing images.
  • Choose print or screen media deliberately.

Edge cases and reliable automation

Fonts and images

Bundling fonts and images with the document avoids failures caused by blocked external resources. In Puppeteer, wait for document.fonts.ready and for a page-specific ready selector.

JavaScript applications

networkidle2 is a useful starting point, but single-page apps can keep connections open indefinitely. Prefer an explicit application-ready marker and a bounded timeout.

Page breaks

Use break-inside: avoid for cards, tables, and figures, but expect very large elements to split when they cannot fit on one page. Verify the generated PDF rather than relying only on CSS.

Security

For untrusted HTML, isolate the renderer, restrict outbound network access where possible, limit CPU and memory, and avoid exposing internal services through user-controlled URLs.

Or skip the browser setup

ScreenshotNeo provides a GET endpoint that can return a clean screenshot or PDF. It accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. It also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

See the ScreenshotNeo API documentation for PDF parameters and the complete option list.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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}`);

Every feature is included on every plan. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

Troubleshooting

Symptom Likely cause Fix
Blank or incomplete PDF Rendering started before app data loaded Wait for a ready selector, fonts, and required requests; use a bounded timeout
Missing backgrounds Print dialog or renderer disables backgrounds Enable background graphics or set printBackground: true
Wrong paper size Browser settings override CSS Set @page and Puppeteer preferCSSPageSize, then inspect preview
Clipped wide content Fixed-width elements exceed the page Add responsive print styles, reduce scale, or set a wider paper size
Fonts differ Font request failed or was not ready Bundle fonts or wait for document.fonts.ready
wkhtmltopdf layout differs Qt WebKit lacks modern browser features Adjust CSS for compatibility or move to Chromium
Print dialog does not appear Popup blocked or document still loading Call window.print() from a user action after load

Performance, reliability, and cost

Browser printing has no service charge but consumes a person’s time. Puppeteer and wkhtmltopdf make output repeatable, while hosted APIs remove browser fleet maintenance. Reuse browser processes for batches, cap concurrency, cache stable inputs, and record renderer version and options with each artifact. For hosted conversion, account for request limits, data retention, region, and per-document pricing. ScreenshotNeo only bills clean shots; failed loads, blank pages, bot checks, timeouts, and cache hits are free.

FAQ

Can I convert HTML to PDF without installing software?

Yes. Open the HTML in a browser and use Print → Save as PDF, or use a hosted converter.

Should I use print or screen CSS?

Use print CSS for paper-like documents. Use screen media when the PDF must preserve the on-screen layout.

Which method is best for invoices?

Puppeteer or a hosted Chromium API provides repeatable rendering and explicit page controls.

Why does my PDF have extra pages?

Check margins, fixed heights, oversized elements, and print-only content. Add deliberate page-break rules and inspect the print preview.