HTML → PDF

Render raw HTML or a live URL into a print-ready PDF with real Chromium.

POST /api/v1/html-to-pdf MCP html_to_pdf renderbrowser

Boots a headless browser: ~2–6s and roughly 0.1 browser-minute of the daily free 10.

Playground

HTML source to render. Takes precedence over url.
Page to render. Ignored when html is supplied.
How the document is paginated. report protects headings, tables and figures from being split. slides maps one slide element to exactly one PDF page. continuous emits a single tall page with no breaks at all. flow is Chromium's untouched behaviour, for documents that ship their own print stylesheet. auto detects a slide deck and otherwise uses report.
Start each section on a fresh page. report layout only. The first section never gets a break, so you never get a blank opening page.
Paper size.
Page geometry for slides layout. auto measures the deck's own slide box.
Advanced options (12)
CSS media type to emulate.
Download filename.
HTML for the running footer.
HTML for the running header. Supports Chromium's .title, .date, .pageNumber, .totalPages classes.
CSS length applied to all four margins, or four space-separated lengths (top right bottom left).
Pages to keep, e.g. 1-3,8. Empty means all pages.
Render scale, 0.1–2.
CSS selector matching one slide. Leave empty to auto-detect reveal.js, Slidev, Marp, impress.js, remark and the common .slide conventions.
Hard timeout for the page load, in milliseconds.
Block until this CSS selector appears. Useful for lazily hydrated SPAs.
When to consider navigation finished.
Runs against this deployment's live API.

Result

Fill in the form and hit Run.

Call it from code

How it works

Renders with the same Chromium that ships in Cloudflare's Browser Rendering, so your CSS — including @page, web fonts, flexbox and grid — behaves exactly as it does in a desktop browser's print preview.

Pass either html (a full document or a fragment) or url. When you pass html, add a <base href> tag if you reference relative assets. The page is rendered with print media emulation and backgrounds enabled, which is what most people want and what headless Chrome does not do out of the box.

Pick a layout

Chromium's default is "pour the document into fixed-size boxes and cut wherever the box ends". That is the wrong answer for both documents people actually convert, so layout changes the paginator:

Layout Use it for What it does
report long-form reports, whitepapers, invoices Never strands a heading at the foot of a page, never slices a table, figure or code block, repeats <thead> across a long table, and honours orphans/widows. Set sectionBreak to also start each section on a fresh sheet.
slides decks — reveal.js, Slidev, Marp, impress.js, remark, or your own .slide markup Finds the slide elements, forces the hidden ones visible, and pins one slide to exactly one page at the deck's own aspect ratio. No slide ever spans a page boundary and there is no trailing blank sheet.
continuous screen reading, transcripts, dashboards One single page as tall as the content. No page breaks exist at all.
flow documents with their own tuned print stylesheet Chromium's untouched behaviour.
auto (default) anything Detects a deck; falls back to report.

For a reveal.js deck served over HTTP the tool reloads it with reveal's own ?print-pdf mode, which knows about vertical stacks and fragments — better than anything an external stylesheet could do.

The response metadata reports what happened: layout, pages, and for decks slides, slideSelector and the page geometry, so you can check the slide count came out right.

Tips
  • Report reading badly? Set sectionBreak: "h1" (or h2) so each section starts on a fresh sheet.
  • Anything you never want split can be marked in your own HTML with class="avoid-break"; class="page-break" forces a break before an element.
  • Deck not detected? Pass slideSelector with the CSS selector for a single slide, and check the returned slides count.
  • Slides coming out cropped? The deck is probably a different aspect ratio than assumed — pass slideSize explicitly.
  • Backgrounds missing? printBackground is already on — check for @media print { … display:none } in the page's own CSS.
  • For page numbers set displayHeaderFooter: true and use <span class="pageNumber"></span> / <span class="totalPages"></span>. (Not applicable to slides or continuous.)

Parameters

ParameterTypeDefaultDescription
html string HTML source to render. Takes precedence over url.
url string Page to render. Ignored when html is supplied.
layout `auto` | `report` | `slides` | `continuous` | `flow` "auto" How the document is paginated. report protects headings, tables and figures from being split. slides maps one slide element to exactly one PDF page. continuous emits a single tall page with no breaks at all. flow is Chromium's untouched behaviour, for documents that ship their own print stylesheet. auto detects a slide deck and otherwise uses report.
sectionBreak `none` | `h1` | `h2` | `h3` | `section` "none" Start each section on a fresh page. report layout only. The first section never gets a break, so you never get a blank opening page.
slideSize `auto` | `16:9` | `16:10` | `4:3` | `a4-landscape` "auto" Page geometry for slides layout. auto measures the deck's own slide box.
slideSelector string CSS selector matching one slide. Leave empty to auto-detect reveal.js, Slidev, Marp, impress.js, remark and the common .slide conventions.
format `A4` | `A3` | `A5` | `Letter` | `Legal` | `Tabloid` "A4" Paper size.
landscape boolean false Landscape orientation.
printBackground boolean true Render CSS backgrounds and images. Off by default in Chromium; on by default here.
scale number 1 Render scale, 0.1–2.
margin string "16mm" CSS length applied to all four margins, or four space-separated lengths (top right bottom left).
pageRanges string Pages to keep, e.g. 1-3,8. Empty means all pages.
displayHeaderFooter boolean false Show the header/footer templates.
headerTemplate string HTML for the running header. Supports Chromium's .title, .date, .pageNumber, .totalPages classes.
footerTemplate string HTML for the running footer.
filename string "document.pdf" Download filename.
emulateMedia `print` | `screen` "print" CSS media type to emulate.
waitUntil `load` | `domcontentloaded` | `networkidle0` | `networkidle2` "networkidle2" When to consider navigation finished.
waitForSelector string Block until this CSS selector appears. Useful for lazily hydrated SPAs.
timeoutMs integer 20000 Hard timeout for the page load, in milliseconds.

Response

The PDF bytes. Send `Accept: application/json` (or `?output=json`) to get `{mime, filename, bytes, base64|url, layout, pages, slides, …}` instead.

Pairs well with