Free PDF tool
Convert HTML to PDF
Paste a page or a snippet with its CSS, check the preview and save it as a PDF. The tool uses your browser's own print engine, so the result follows the same CSS rules as printing a web page.
Your files stay on your device
- Free, no account needed
- Built on your browser's print engine
Paste, type, open a file or drop one onto the editor. The example shows what the tool does.
How it works
Convert HTML to PDF in 4 steps
- 1
Paste your HTML
Paste markup with its styles, or open an .html file. The preview updates as you type.
- 2
Set up the page
Choose paper size, orientation and margins. They are added to the page as an @page rule.
- 3
Create the PDF
Select Save as PDF. Your browser's print dialog opens.
- 4
Save
Choose Save as PDF as the destination, turn on background graphics if your design uses colored backgrounds, and save.
Questions
Frequently asked questions
Are my files uploaded to a server?
No. The tool runs entirely in your browser: your files are read and converted on your device, and their contents are never sent to our servers.
Why does a print dialog open?
A browser can only turn HTML into a PDF by printing it. Choose Save as PDF (or Microsoft Print to PDF) as the destination. In Chrome and Edge the PDF comes from Chromium's layout engine, which our API also runs on the server.
Are external images, fonts and scripts loaded?
No. The preview does not fetch files from other websites and does not run scripts, which keeps pasted code from doing anything unexpected. Embed images and fonts as data URLs, or use the API, which loads remote assets and waits for your JavaScript before rendering.
How do I control page breaks?
With CSS, as in any print style sheet: break-before: page starts a new page, break-inside: avoid keeps a block together. Your own @page rules take precedence over the settings in the tool.
Automate it
Do the same in your application with Dynamic Document API
Render HTML server-side in Chromium, with headers and footers, page numbers, remote images and fonts and a wait for your JavaScript. The PDF comes back as a file or a signed link, without a print dialog.
POST /v1/pdf/from-htmlAvailablecurl -X POST https://api-eu.dynamicdocumentapi.com/v1/pdf/from-html \
-H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Invoice 2026-0412</h1><p>Thank you for your order.</p>",
"pdf": {
"paper": {
"size": "A4"
},
"margin": {
"top": "20mm",
"bottom": "20mm",
"left": "15mm",
"right": "15mm"
},
"print_background": true
}
}'const response = await fetch("https://api-eu.dynamicdocumentapi.com/v1/pdf/from-html", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DYNAMIC_DOCUMENT_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"html": "<h1>Invoice 2026-0412</h1><p>Thank you for your order.</p>",
"pdf": {
"paper": {
"size": "A4"
},
"margin": {
"top": "20mm",
"bottom": "20mm",
"left": "15mm",
"right": "15mm"
},
"print_background": true
}
}),
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const result = await response.json();
console.log(result);import os
import uuid
import requests
response = requests.post(
"https://api-eu.dynamicdocumentapi.com/v1/pdf/from-html",
headers={
"Authorization": f"Bearer {os.environ['DYNAMIC_DOCUMENT_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"html": "<h1>Invoice 2026-0412</h1><p>Thank you for your order.</p>",
"pdf": {
"paper": {
"size": "A4",
},
"margin": {
"top": "20mm",
"bottom": "20mm",
"left": "15mm",
"right": "15mm",
},
"print_background": True,
},
},
timeout=90,
)
response.raise_for_status()
print(response.json())