induwara.lk
induwara.lkDocuments · Privacy-first

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.

By Induwara AshinsanaUpdated May 11, 2026
HTML to PDF ConverterIn-browser · no upload
Files stay on your device
Everything happens in your browser. Nothing is uploaded.
Max 5.0 MB.

Paste HTML on the left to see a live preview here.

The preview applies the same @page rule the printer will use, so what you see is close to what your PDF will look like.

Page size
Orientation
Margin
Input size
0 B
HTML tags
0
Cross-checked by 2 parsers
Characters
0
Lines
0
Add HTML to begin

Paste HTML or upload a .html file above.

Built against the W3C CSS Paged Media Module Level 3 and the HTML Living Standard's iframe sandbox semantics. Verified 2026-05-11— full source list in the “Sources & references” section below.

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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. Render and print. The built document is set as the iframe's srcdoc attribute (so it inherits the parent origin under allow-same-origin), and the “Download as PDF” button calls iframe.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

Article fragment on portrait A4

A bare H1 + paragraph fragment with no <html> wrapper. The tool detects the fragment, wraps it in a full HTML5 skeleton with the chosen @page size, and prints to A4 portrait with 15 mm margins.

  1. Kind: Fragment (auto-wrapped)
  2. Input tags: 8 (cross-checked by 2 parsers)
  3. Page: A4 portrait · 15 mm margin
  4. Built document size: 2.0 KB

Invoice template on US Letter portrait

A full HTML document with its own <head> styles. The builder injects only the @page rule plus a print reset before </head>, so the user's typography survives. Prints to US Letter portrait, 25 mm margin.

  1. Kind: Full HTML document
  2. Input tags: 34 (cross-checked by 2 parsers)
  3. Page: US Letter portrait · 25 mm margin
  4. Built document size: 2.0 KB

Wide table on tabloid landscape, no margin

An edge case: a tabular fragment that would overflow A4. Tabloid landscape with a 0 mm margin gives a 432 × 279 mm content area — enough for an eight-column ledger printed edge to edge.

  1. Kind: Fragment (auto-wrapped)
  2. Input tags: 60 (cross-checked by 2 parsers)
  3. Page: Tabloid landscape · 0 mm margin
  4. Built document size: 2.3 KB

Frequently asked questions

Sources & references

Related tools

Rate this tool
Be the first to rate

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.