HTML to PDF Converter
Paste an HTML snippet or a full document, pick page size, orientation, and margin, then save it as a PDF — all in your browser. No signup, no upload, the file never leaves your device. Text stays selectable in the output, not flattened to an image.
How it works
A PDF made from HTML can be produced two ways: by rasterising the page to a canvas (the html2canvas + jsPDF approach) or by handing off to the browser's own print engine via window.print(). The first approach turns text into pixels, which prints fuzzily and breaks selection, accessibility, and search. The second uses the same Blink, Gecko, or WebKit code path that powers Print Preview in the browser's File menu — the output is a real, text-selectable PDF. This tool uses the second approach.
The pure-data module lives in lib/data/html-to-pdf.ts. It exposes a deterministic buildPrintableDocument(html, options) function that wraps the user's HTML and emits a self-contained document with a CSS @page rule (CSS Paged Media Module Level 3, §3). Two paths cover every input:
- Detect kind. A small heuristic scans the first 4 KB for an
<html>element. A match means the paste is a full document; otherwise it's a fragment. - Validate. Two independent tag counters — a regex matcher and a char-by-char scanner — must agree on the tag count, the input must be non-empty, and the UTF-8 byte size must stay under 5.0 MB. Mismatches surface a specific error message, not a silent failure.
- Resolve page geometry. One of 6 standard page sizes, portrait or landscape, with a margin from None to Wide (25 mm). Width and height are expressed in millimetres so the @page rule needs only one unit.
- Inject styles. For fragment inputs, the HTML is wrapped in a full HTML5 skeleton with the @page rule and a print reset (table borders, page-break-after on headings, link colour). For full-document inputs, only the @page rule and a tiny print reset are inserted before
</head>, so the author's typography survives. - Render and print. The built document is set as the iframe's
srcdocattribute (so it inherits the parent origin underallow-same-origin), and the “Download as PDF” button callsiframe.contentWindow.print(). The browser opens its print dialog scoped to that iframe; the user picks the “Save as PDF” destination, which every major browser ships out of the box.
The iframe is sandboxed with sandbox="allow-modals allow-same-origin" — scripts are disabled, but the allow-modals token is what lets the print dialog open from a sandboxed frame (HTML Living Standard §4.8.5). Together those two tokens are the minimum permission set the print path needs.
Worked examples
Frequently asked questions
Sources & references
- W3C — CSS Paged Media Module Level 3 (@page rule, size and margin descriptors)
- W3C — CSS Fragmentation Module Level 3 (page-break-* and break-* properties)
- HTML Living Standard — the iframe element and sandbox token semantics
- HTML Living Standard — Window.print()
- ISO 216 — A-series paper sizes (A4, A3, A5)
- ANSI/ASME Y14.1 — US paper sizes (Letter, Legal, Tabloid)
The print-document builder was cross-checked against the above standards on 2026-05-11. The page is reviewed whenever the CSS Paged Media spec or the HTML Living Standard publishes errata that touch @page or the iframe sandbox token list.
Related tools
Comments & feedback
Spotted a bug or want an improvement? Tell us — our team reviews every comment, and good ideas get built. Comments are public and anonymous.
Found a bug, edge case, or want to suggest an improvement?
Email me at [email protected] — most fixes ship within 24 hours.