We use cookies
We use cookies to enhance your experience and analyse site usage.
Generate PDFs from HTML or any URL with a single POST request.
All requests require an Authorization header with a Bearer token:
Authorization: Bearer YOUR_API_KEY
Get your API key from the Dashboard → API Keys page. Keys start with sk_.
https://api.htmlpdf.dev
Generate a PDF from HTML or a URL.
https://api.htmlpdf.dev/api/pdfSend a JSON body with either url or html (not both). Returns a PDF binary by default, or JSON/Base64 when specified.
| Parameter | Type | Default | Description |
|---|---|---|---|
| url | string | — | URL to navigate and render (provide url OR html, not both) |
| html | string | — | Raw HTML string to render (provide html OR url, not both) |
| format | string | A4 | Paper size: A4 | Letter | A3 | A5 | Legal | Tabloid |
| landscape | boolean | false | Landscape orientation |
| margin.top | string | 0.4in | Top margin in CSS units (e.g. "1in", "20mm", "40px") |
| margin.right | string | 0.4in | Right margin in CSS units |
| margin.bottom | string | 0.4in | Bottom margin in CSS units |
| margin.left | string | 0.4in | Left margin in CSS units |
| printBackground | boolean | true | Include CSS background colors and images |
| scale | number | 1 | Page scale factor between 0.1 and 2.0 |
| pageRanges | string | all | Page ranges to include, e.g. "1-3, 5" |
| preferCSSPageSize | boolean | false | Use the CSS @page size if declared in stylesheet |
| displayHeaderFooter | boolean | false | Enable header and footer templates |
| headerTemplate | string | "" | HTML template for page header (requires displayHeaderFooter: true) |
| footerTemplate | string | "" | HTML template for page footer (requires displayHeaderFooter: true) |
| emulateMediaType | string | CSS media type: "screen" or "print" | |
| waitForSelector | string | — | CSS selector to wait for before rendering (10s timeout) |
| waitForTimeout | number | 0 | Additional wait in ms after page load (max 10000) |
| responseType | string | binary | Response format: "binary" | "base64" | "json" |
| filename | string | document.pdf | Content-Disposition filename for binary responses |
Returns raw PDF bytes. Headers include Content-Type: application/pdf and Content-Disposition: attachment; filename="document.pdf".
Returns a JSON object with the PDF encoded as a Base64 string:
{
"base64": "JVBERi0xLjQKJeLjz9MKN...",
"size": 42801
}Returns metadata about the generated PDF:
{
"size": 42801,
"generatedAt": "2026-03-23T12:00:00.000Z"
}All errors return JSON with an error field:
{ "error": "Provide either \"url\" or \"html\", not neither." }| Status | Meaning |
|---|---|
| 400 | Bad Request — missing or invalid parameters |
| 401 | Unauthorized — missing or invalid API key |
| 408 | Request Timeout — PDF generation exceeded 30 seconds |
| 429 | Too Many Requests — monthly quota or rate limit exceeded |
| 500 | Internal Server Error — retry after a moment |
| Format | Millimetres | Inches |
|---|---|---|
| A3 | 297 × 420 mm | 11.7 × 16.5 in |
| A4 | 210 × 297 mm | 8.27 × 11.7 in |
| A5 | 148 × 210 mm | 5.83 × 8.27 in |
| Letter | 216 × 279 mm | 8.5 × 11 in |
| Legal | 216 × 356 mm | 8.5 × 14 in |
| Tabloid | 279 × 432 mm | 11 × 17 in |
Each plan has a monthly PDF quota and an hourly rate limit. Exceeding either returns 429. Quotas reset on your billing date.
| Plan | Monthly PDFs | Rate limit |
|---|---|---|
| Free | 100/mo | 10 req/hr |
| Starter | 500/mo | 60 req/hr |
| Growth | 2,500/mo | 300 req/hr |
| Business | 10,000/mo | 1,200 req/hr |
| Scale | 50,000/mo | 6,000 req/hr |
| Enterprise | 200,000/mo | 24,000 req/hr |
Check current usage in the Dashboard → Usage page.
curl -X POST https://api.htmlpdf.dev/api/pdf \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Invoice #1042</h1><p>Total: $249</p>",
"format": "A4",
"margin": { "top": "1in", "bottom": "1in", "left": "1in", "right": "1in" }
}' \
--output invoice.pdfconst response = await fetch('https://api.htmlpdf.dev/api/pdf', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
html: '<h1>Invoice</h1><p>Total: $249</p>',
format: 'A4',
margin: { top: '1in', bottom: '1in', left: '1in', right: '1in' },
}),
})
const pdf = await response.arrayBuffer()
fs.writeFileSync('invoice.pdf', Buffer.from(pdf))import requests
response = requests.post(
'https://api.htmlpdf.dev/api/pdf',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
json={
'html': '<h1>Invoice</h1><p>Total: $249</p>',
'format': 'A4',
'margin': {'top': '1in', 'bottom': '1in', 'left': '1in', 'right': '1in'},
},
)
with open('invoice.pdf', 'wb') as f:
f.write(response.content)$ch = curl_init('https://api.htmlpdf.dev/api/pdf');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_KEY',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'html' => '<h1>Invoice</h1><p>Total: $249</p>',
'format' => 'A4',
]),
CURLOPT_RETURNTRANSFER => true,
]);
file_put_contents('invoice.pdf', curl_exec($ch));payload := map[string]interface{}{
"html": "<h1>Invoice</h1><p>Total: $249</p>",
"format": "A4",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST",
"https://api.htmlpdf.dev/api/pdf",
bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
pdf, _ := io.ReadAll(resp.Body)
os.WriteFile("invoice.pdf", pdf, 0644)