HTML to PDF
Generate a PDF document from raw HTML content. The HTML is sent as a base64-encoded string in the request body.
Endpoint
POST /v1/html/pdf
All requests are processed synchronously. The response body is the raw PDF file.
POST /v2/html/pdf
Requests default to asynchronous processing (async: true, storage: true). Add "async": false to receive the raw PDF directly. See Sync vs. Async for details.
Quick Start
Encode your HTML as base64 and send it in the html field:
cURL
# Base64 encode your HTML
HTML_BASE64=$(echo '<html><body><h1>Hello World</h1><p>Generated by cloudlayer.io</p></body></html>' | base64)
curl -X POST "https://api.cloudlayer.io/v1/html/pdf" \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d "{\"html\": \"$HTML_BASE64\"}" \
--output result.pdf
JavaScript (fetch)
const html = `<html>
<body>
<h1>Hello World</h1>
<p>Generated by cloudlayer.io</p>
</body>
</html>`;
const response = await fetch("https://api.cloudlayer.io/v1/html/pdf", {
method: "POST",
headers: {
"X-API-Key": "your-api-key-here",
"Content-Type": "application/json",
},
body: JSON.stringify({
html: btoa(html),
}),
});
const pdf = await response.arrayBuffer();
// Save to file, send to client, etc.
Python (requests)
import base64
import requests
html = """<html>
<body>
<h1>Hello World</h1>
<p>Generated by cloudlayer.io</p>
</body>
</html>"""
response = requests.post(
"https://api.cloudlayer.io/v1/html/pdf",
headers={
"X-API-Key": "your-api-key-here",
"Content-Type": "application/json",
},
json={
"html": base64.b64encode(html.encode()).decode(),
},
)
with open("result.pdf", "wb") as f:
f.write(response.content)
cURL
# Base64 encode your HTML
HTML_BASE64=$(echo '<html><body><h1>Hello World</h1><p>Generated by cloudlayer.io</p></body></html>' | base64)
curl -X POST "https://api.cloudlayer.io/v2/html/pdf" \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d "{\"html\": \"$HTML_BASE64\", \"async\": false}" \
--output result.pdf
JavaScript (fetch)
const html = `<html>
<body>
<h1>Hello World</h1>
<p>Generated by cloudlayer.io</p>
</body>
</html>`;
const response = await fetch("https://api.cloudlayer.io/v2/html/pdf", {
method: "POST",
headers: {
"X-API-Key": "your-api-key-here",
"Content-Type": "application/json",
},
body: JSON.stringify({
html: btoa(html),
async: false,
}),
});
const pdf = await response.arrayBuffer();
// Save to file, send to client, etc.
Python (requests)
import base64
import requests
html = """<html>
<body>
<h1>Hello World</h1>
<p>Generated by cloudlayer.io</p>
</body>
</html>"""
response = requests.post(
"https://api.cloudlayer.io/v2/html/pdf",
headers={
"X-API-Key": "your-api-key-here",
"Content-Type": "application/json",
},
json={
"html": base64.b64encode(html.encode()).decode(),
"async": False,
},
)
with open("result.pdf", "wb") as f:
f.write(response.content)
Tip: Omit
"async": falseto use the default async mode. The API will return a JSON response with the job ID immediately, and the generated PDF will be stored and accessible via the Assets endpoint.
Parameters
Required
| Parameter | Type | Description |
|---|---|---|
html | string | Required. Base64-encoded HTML content. The HTML can include inline CSS, <style> tags, and <link> references to external stylesheets. |
Base Parameters
These parameters control page loading behavior, viewport configuration, and general output settings.
| Parameter | Type | Default | Description |
|---|---|---|---|
autoScroll | boolean | false | Automatically scroll the page to the bottom before generating the PDF. Useful for triggering lazy-loaded images and infinite scroll content. |
delay | number | 0 | Time in milliseconds to wait after the page has loaded (and after waitUntil is satisfied) before generating the PDF. Use this to allow JavaScript animations or dynamic content to finish rendering. |
filename | string | — | Sets the Content-Disposition header filename on the response. When set, browsers will prompt to save the file with this name. Include the .pdf extension (e.g., "invoice-2024.pdf"). |
generatePreview | object | — | Generate a thumbnail preview image alongside the PDF. See generatePreview for details. |
height | string | — | Override the page height. Accepts CSS units (e.g., "11in", "297mm", "1200px"). When set, takes precedence over the format height. |
width | string | — | Override the page width. Accepts CSS units (e.g., "8.5in", "210mm", "800px"). When set, takes precedence over the format width. |
inline | boolean | false | When true, sets the Content-Disposition header to inline instead of attachment, causing browsers to display the PDF in the browser tab rather than downloading it. |
landscape | boolean | false | Generate the PDF in landscape orientation. |
preferCSSPageSize | boolean | false | When true, use the CSS @page size declaration instead of the format parameter. Useful when your CSS already defines the page dimensions via @page { size: A4; }. |
projectId | string | — | Associate this generation with a specific project for organization and filtering in the dashboard. |
scale | number | 1 | Scale of the web page rendering. Valid range: 0.1 to 2. Values less than 1 shrink the content; values greater than 1 enlarge it. |
timeout | number | 30000 | Maximum time in milliseconds to wait for the page to load. If the page does not load within this time, the request fails with a timeout error. Maximum value depends on your plan. |
timeZone | string | — | Set the browser timezone for rendering. Uses IANA timezone names (e.g., "America/New_York", "Europe/London", "Asia/Tokyo"). Affects Date objects and time-related rendering. |
viewPort | object | — | Configure the browser viewport. See viewPort for details. |
waitForSelector | object | — | Wait for a specific CSS selector to appear in the DOM before generating. See waitForSelector for details. |
waitUntil | string | "networkidle2" | When to consider the page navigation complete. See waitUntil for options. |
PDF Parameters
These parameters control PDF-specific output settings like page size, margins, headers, and footers.
| Parameter | Type | Default | Description |
|---|---|---|---|
pageRanges | string | — | Paper ranges to print, e.g., "1-5", "8", "1-3, 5". An empty string means all pages. |
format | string | "letter" | Page size format. See format for all options. |
margin | object | — | Page margins. See margin for details. |
printBackground | boolean | true | Print background graphics (colors, images, gradients). Set to false to exclude backgrounds. |
headerTemplate | object | — | Custom page header. See headerTemplate / footerTemplate for details. |
footerTemplate | object | — | Custom page footer. See headerTemplate / footerTemplate for details. |
Parameter Details
generatePreview Object
Generate a thumbnail preview image of the first page of the PDF.
| Field | Type | Default | Description |
|---|---|---|---|
width | number | 300 | Width of the preview image in pixels. |
height | number | 400 | Height of the preview image in pixels. |
type | string | "png" | Image format: "png", "jpg", or "webp". |
quality | number | 80 | Image quality (1-100). Only applies to jpg and webp. |
maintainAspectRatio | boolean | true | Maintain the aspect ratio of the PDF page in the preview. When true, the image fits within the given dimensions without distortion. |
{
"html": "...",
"generatePreview": {
"width": 600,
"height": 800,
"type": "png",
"quality": 90,
"maintainAspectRatio": true
}
}
viewPort Object
Configure the browser viewport used for rendering. This affects how responsive layouts, media queries, and CSS breakpoints behave.
| Field | Type | Default | Description |
|---|---|---|---|
width | number | 1440 | Viewport width in pixels. |
height | number | 900 | Viewport height in pixels. |
deviceScaleFactor | number | 1 | Device scale factor (DPR). Set to 2 for Retina-style rendering. |
isMobile | boolean | false | Emulate a mobile device (affects navigator.userAgent and viewport meta tag behavior). |
hasTouch | boolean | false | Enable touch event support. |
isLandscape | boolean | false | Set the viewport to landscape orientation. |
{
"html": "...",
"viewPort": {
"width": 1920,
"height": 1080,
"deviceScaleFactor": 2
}
}
waitForSelector Object
Wait for a specific element to appear in the DOM before generating the PDF. Useful for single-page applications or pages that render content dynamically.
| Field | Type | Default | Description |
|---|---|---|---|
selector | string | — | Required. CSS selector to wait for (e.g., "#content-loaded", ".chart-rendered"). |
options | object | — | Options for the wait behavior. |
options.visible | boolean | false | Wait for the element to be visible (not just present in the DOM). |
options.hidden | boolean | false | Wait for the element to be hidden or removed from the DOM. |
options.timeout | number | 30000 | Maximum time in milliseconds to wait for the selector. |
{
"html": "...",
"waitForSelector": {
"selector": "#charts-loaded",
"options": {
"visible": true,
"timeout": 10000
}
}
}
waitUntil
Controls when the page is considered “loaded.” Choose the strategy that best fits your content:
| Value | Description |
|---|---|
"load" | Wait for the load event (all resources including images and stylesheets). |
"domcontentloaded" | Wait for the DOMContentLoaded event (HTML parsed, but images/stylesheets may still be loading). Fastest option. |
"networkidle0" | Wait until there are no more than 0 network connections for at least 500ms. Best for pages that make many API calls. |
"networkidle2" | Wait until there are no more than 2 network connections for at least 500ms. Good default for most pages. |
Format Options
Standard paper sizes for the format parameter:
| Value | Dimensions |
|---|---|
"letter" | 8.5in x 11in |
"legal" | 8.5in x 14in |
"tabloid" | 11in x 17in |
"ledger" | 17in x 11in |
"a0" | 33.1in x 46.8in |
"a1" | 23.4in x 33.1in |
"a2" | 16.54in x 23.4in |
"a3" | 11.7in x 16.54in |
"a4" | 8.27in x 11.7in |
"a5" | 5.83in x 8.27in |
"a6" | 4.13in x 5.83in |
Margin Object
Set page margins using CSS units. Supported units: px, in, cm, mm.
| Field | Type | Default | Description |
|---|---|---|---|
top | string | "0" | Top margin (e.g., "1in", "25mm", "20px"). |
bottom | string | "0" | Bottom margin. |
left | string | "0" | Left margin. |
right | string | "0" | Right margin. |
{
"html": "...",
"margin": {
"top": "1in",
"bottom": "1in",
"left": "0.75in",
"right": "0.75in"
}
}
Note: When using
headerTemplateorfooterTemplate, you must set sufficient top or bottom margins to make space for them. Headers and footers render inside the margin area.
headerTemplate / footerTemplate Object
Add custom headers and footers to each page of the PDF. The template content is rendered inside the margin area, so make sure your margin.top or margin.bottom is large enough to accommodate the template.
| Field | Type | Default | Description |
|---|---|---|---|
selector | string | — | CSS selector of an element within your HTML to use as the header/footer content. The element’s inner HTML is extracted and used as the template. |
method | string | "text" | How to extract the template content: "text" extracts inner HTML, "isolate" extracts the element with its computed styles. |
margin | object | — | Override margins specifically for the header/footer area. Same format as the page margin object. |
style | string | — | Additional CSS to apply to the header/footer. Use this for positioning, font sizes, etc. |
imageStyle | string | — | CSS styles applied specifically to images within the header/footer. Useful for controlling logo sizing. |
Templates support these special CSS classes that are automatically populated:
| CSS Class | Value |
|---|---|
date | Current date |
title | Document title |
url | Document URL |
pageNumber | Current page number |
totalPages | Total number of pages |
{
"html": "...",
"margin": {
"top": "100px",
"bottom": "80px"
},
"headerTemplate": {
"selector": "#page-header",
"method": "isolate",
"style": "font-size: 10px; width: 100%; text-align: center; padding: 10px 0;",
"imageStyle": "max-height: 40px; width: auto;"
},
"footerTemplate": {
"selector": "#page-footer",
"method": "isolate",
"style": "font-size: 9px; width: 100%; text-align: center; padding: 10px 0;"
}
}
Tip: Include the header and footer elements in your HTML content (they can be hidden with
display: none), then reference them with theselectorfield. Theisolatemethod preserves their styling.
Full Example
Generate a styled invoice PDF with custom margins, headers, and footers:
cURL
HTML=$(cat <<'HTML'
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 40px; }
.invoice-header { display: flex; justify-content: space-between; margin-bottom: 40px; }
.company { font-size: 24px; font-weight: bold; color: #333; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
th { background: #f8f9fa; font-weight: 600; }
.total { font-size: 18px; font-weight: bold; text-align: right; margin-top: 20px; }
#page-footer { display: none; }
</style>
</head>
<body>
<div class="invoice-header">
<div class="company">Acme Corp</div>
<div>Invoice #1042 — 2024-01-15</div>
</div>
<table>
<thead>
<tr><th>Item</th><th>Qty</th><th>Price</th><th>Total</th></tr>
</thead>
<tbody>
<tr><td>Widget A</td><td>10</td><td>$25.00</td><td>$250.00</td></tr>
<tr><td>Widget B</td><td>5</td><td>$40.00</td><td>$200.00</td></tr>
<tr><td>Service Fee</td><td>1</td><td>$75.00</td><td>$75.00</td></tr>
</tbody>
</table>
<div class="total">Total: $525.00</div>
<div id="page-footer">
Page <span class="pageNumber"></span> of <span class="totalPages"></span>
</div>
</body>
</html>
HTML
)
HTML_BASE64=$(echo "$HTML" | base64 -w 0)
curl -X POST "https://api.cloudlayer.io/v2/html/pdf" \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d "{
\"html\": \"$HTML_BASE64\",
\"format\": \"letter\",
\"margin\": {
\"top\": \"0.75in\",
\"bottom\": \"1in\",
\"left\": \"0.75in\",
\"right\": \"0.75in\"
},
\"printBackground\": true,
\"footerTemplate\": {
\"selector\": \"#page-footer\",
\"method\": \"text\",
\"style\": \"font-size: 9px; width: 100%; text-align: center; color: #999;\"
},
\"filename\": \"invoice-1042.pdf\"
}" \
--output invoice-1042.pdf
JavaScript (fetch)
const html = `<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 40px; }
.invoice-header { display: flex; justify-content: space-between; margin-bottom: 40px; }
.company { font-size: 24px; font-weight: bold; color: #333; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
th { background: #f8f9fa; font-weight: 600; }
.total { font-size: 18px; font-weight: bold; text-align: right; margin-top: 20px; }
</style>
</head>
<body>
<div class="invoice-header">
<div class="company">Acme Corp</div>
<div>Invoice #1042</div>
</div>
<table>
<thead><tr><th>Item</th><th>Qty</th><th>Price</th><th>Total</th></tr></thead>
<tbody>
<tr><td>Widget A</td><td>10</td><td>$25.00</td><td>$250.00</td></tr>
<tr><td>Widget B</td><td>5</td><td>$40.00</td><td>$200.00</td></tr>
</tbody>
</table>
<div class="total">Total: $450.00</div>
</body>
</html>`;
const response = await fetch("https://api.cloudlayer.io/v2/html/pdf", {
method: "POST",
headers: {
"X-API-Key": "your-api-key-here",
"Content-Type": "application/json",
},
body: JSON.stringify({
html: btoa(html),
format: "letter",
margin: {
top: "0.75in",
bottom: "0.75in",
left: "0.75in",
right: "0.75in",
},
printBackground: true,
filename: "invoice-1042.pdf",
}),
});
const pdfBuffer = await response.arrayBuffer();
Python (requests)
import base64
import requests
html = """<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 40px; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
th { background: #f8f9fa; }
.total { font-size: 18px; font-weight: bold; text-align: right; margin-top: 20px; }
</style>
</head>
<body>
<h1>Invoice #1042</h1>
<table>
<thead><tr><th>Item</th><th>Qty</th><th>Price</th><th>Total</th></tr></thead>
<tbody>
<tr><td>Widget A</td><td>10</td><td>$25.00</td><td>$250.00</td></tr>
<tr><td>Widget B</td><td>5</td><td>$40.00</td><td>$200.00</td></tr>
</tbody>
</table>
<div class="total">Total: $450.00</div>
</body>
</html>"""
response = requests.post(
"https://api.cloudlayer.io/v2/html/pdf",
headers={
"X-API-Key": "your-api-key-here",
"Content-Type": "application/json",
},
json={
"html": base64.b64encode(html.encode()).decode(),
"format": "letter",
"margin": {
"top": "0.75in",
"bottom": "0.75in",
"left": "0.75in",
"right": "0.75in",
},
"printBackground": True,
"filename": "invoice-1042.pdf",
},
)
with open("invoice-1042.pdf", "wb") as f:
f.write(response.content)
Tips
- External resources: Your HTML can reference external CSS, fonts, and images via URLs. Make sure they are publicly accessible, or the renderer will not be able to load them.
- Web fonts: Use
<link>tags to load Google Fonts or other web fonts. SetwaitUntilto"networkidle0"to ensure fonts finish loading before rendering. - Large documents: For documents with many pages, increase the
timeoutvalue and consider using async mode. - Print styles: Use
@media printCSS rules to control what appears in the PDF. The renderer respects print media queries. - Base64 encoding: Make sure your base64 encoding does not include line breaks. Use
base64 -w 0on Linux or equivalent.