API

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": false to 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

ParameterTypeDescription
htmlstringRequired. 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.

ParameterTypeDefaultDescription
autoScrollbooleanfalseAutomatically scroll the page to the bottom before generating the PDF. Useful for triggering lazy-loaded images and infinite scroll content.
delaynumber0Time 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.
filenamestringSets 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").
generatePreviewobjectGenerate a thumbnail preview image alongside the PDF. See generatePreview for details.
heightstringOverride the page height. Accepts CSS units (e.g., "11in", "297mm", "1200px"). When set, takes precedence over the format height.
widthstringOverride the page width. Accepts CSS units (e.g., "8.5in", "210mm", "800px"). When set, takes precedence over the format width.
inlinebooleanfalseWhen 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.
landscapebooleanfalseGenerate the PDF in landscape orientation.
preferCSSPageSizebooleanfalseWhen 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; }.
projectIdstringAssociate this generation with a specific project for organization and filtering in the dashboard.
scalenumber1Scale of the web page rendering. Valid range: 0.1 to 2. Values less than 1 shrink the content; values greater than 1 enlarge it.
timeoutnumber30000Maximum 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.
timeZonestringSet 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.
viewPortobjectConfigure the browser viewport. See viewPort for details.
waitForSelectorobjectWait for a specific CSS selector to appear in the DOM before generating. See waitForSelector for details.
waitUntilstring"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.

ParameterTypeDefaultDescription
pageRangesstringPaper ranges to print, e.g., "1-5", "8", "1-3, 5". An empty string means all pages.
formatstring"letter"Page size format. See format for all options.
marginobjectPage margins. See margin for details.
printBackgroundbooleantruePrint background graphics (colors, images, gradients). Set to false to exclude backgrounds.
headerTemplateobjectCustom page header. See headerTemplate / footerTemplate for details.
footerTemplateobjectCustom page footer. See headerTemplate / footerTemplate for details.

Parameter Details

generatePreview Object

Generate a thumbnail preview image of the first page of the PDF.

FieldTypeDefaultDescription
widthnumber300Width of the preview image in pixels.
heightnumber400Height of the preview image in pixels.
typestring"png"Image format: "png", "jpg", or "webp".
qualitynumber80Image quality (1-100). Only applies to jpg and webp.
maintainAspectRatiobooleantrueMaintain 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.

FieldTypeDefaultDescription
widthnumber1440Viewport width in pixels.
heightnumber900Viewport height in pixels.
deviceScaleFactornumber1Device scale factor (DPR). Set to 2 for Retina-style rendering.
isMobilebooleanfalseEmulate a mobile device (affects navigator.userAgent and viewport meta tag behavior).
hasTouchbooleanfalseEnable touch event support.
isLandscapebooleanfalseSet 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.

FieldTypeDefaultDescription
selectorstringRequired. CSS selector to wait for (e.g., "#content-loaded", ".chart-rendered").
optionsobjectOptions for the wait behavior.
options.visiblebooleanfalseWait for the element to be visible (not just present in the DOM).
options.hiddenbooleanfalseWait for the element to be hidden or removed from the DOM.
options.timeoutnumber30000Maximum 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:

ValueDescription
"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:

ValueDimensions
"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.

FieldTypeDefaultDescription
topstring"0"Top margin (e.g., "1in", "25mm", "20px").
bottomstring"0"Bottom margin.
leftstring"0"Left margin.
rightstring"0"Right margin.
{
  "html": "...",
  "margin": {
    "top": "1in",
    "bottom": "1in",
    "left": "0.75in",
    "right": "0.75in"
  }
}

Note: When using headerTemplate or footerTemplate, 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.

FieldTypeDefaultDescription
selectorstringCSS 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.
methodstring"text"How to extract the template content: "text" extracts inner HTML, "isolate" extracts the element with its computed styles.
marginobjectOverride margins specifically for the header/footer area. Same format as the page margin object.
stylestringAdditional CSS to apply to the header/footer. Use this for positioning, font sizes, etc.
imageStylestringCSS 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 ClassValue
dateCurrent date
titleDocument title
urlDocument URL
pageNumberCurrent page number
totalPagesTotal 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 the selector field. The isolate method 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. Set waitUntil to "networkidle0" to ensure fonts finish loading before rendering.
  • Large documents: For documents with many pages, increase the timeout value and consider using async mode.
  • Print styles: Use @media print CSS 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 0 on Linux or equivalent.