API

Working with HTML

Converting HTML to PDFs and images gives you complete control over the output. You can use any valid HTML, CSS, JavaScript, Sass, and externally hosted resources like fonts, stylesheets, and images. As long as the base64-encoded payload is under 10MB, cloudlayer.io will accept and convert it.

HTML Encoding

HTML must be base64-encoded before being included in the JSON request body. This avoids issues with special characters (double quotes, angle brackets, etc.) that would otherwise break JSON parsing.

Original HTML:

<html>
  <body>
    <h1>Hello world!</h1>
  </body>
</html>

Base64-encoded:

PGh0bWw+PGJvZHk+PGgxPkhlbGxvIHdvcmxkITwvaDE+PC9ib2R5PjwvaHRtbD4=

JSON payload:

{
  "html": "PGh0bWw+PGJvZHk+PGgxPkhlbGxvIHdvcmxkITwvaDE+PC9ib2R5PjwvaHRtbD4="
}

Encoding HTML in Different Languages

JavaScript (Node.js / Browser)

// Browser
const encoded = btoa("<html><body><h1>Hello!</h1></body></html>");

// Node.js / Bun
const encoded = Buffer.from(
  "<html><body><h1>Hello!</h1></body></html>"
).toString("base64");

Python

import base64

html = "<html><body><h1>Hello!</h1></body></html>"
encoded = base64.b64encode(html.encode("utf-8")).decode("utf-8")

C#

using System.Text;

var html = "<html><body><h1>Hello!</h1></body></html>";
var encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(html));

Ruby

require "base64"

html = "<html><body><h1>Hello!</h1></body></html>"
encoded = Base64.strict_encode64(html)

PHP

$html = "<html><body><h1>Hello!</h1></body></html>";
$encoded = base64_encode($html);

Go

import "encoding/base64"

html := "<html><body><h1>Hello!</h1></body></html>"
encoded := base64.StdEncoding.EncodeToString([]byte(html))

Java

import java.util.Base64;

String html = "<html><body><h1>Hello!</h1></body></html>";
String encoded = Base64.getEncoder().encodeToString(html.getBytes("UTF-8"));

Tip: If you are using VS Code, the vscode-base64 extension lets you encode and decode HTML interactively while developing.

Basic Examples

HTML to PDF

curl --request POST \
  --url https://api.cloudlayer.io/v2/html/pdf \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <YOUR-API-KEY>' \
  --data '{
    "html": "PGh0bWw+PGJvZHk+PGgxPkhlbGxvIHdvcmxkITwvaDE+PC9ib2R5PjwvaHRtbD4=",
    "async": false
  }'

HTML to Image

curl --request POST \
  --url https://api.cloudlayer.io/v2/html/image \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <YOUR-API-KEY>' \
  --data '{
    "html": "PGh0bWw+PGJvZHk+PGgxPkhlbGxvIHdvcmxkITwvaDE+PC9ib2R5PjwvaHRtbD4=",
    "async": false
  }'

With Viewport Options

{
  "html": "PGh0bWw+PGJvZHk+PGgxPkhlbGxvIHdvcmxkITwvaDE+PC9ib2R5PjwvaHRtbD4=",
  "viewPort": {
    "width": 800,
    "height": 600
  }
}

Embedding Images

For fully self-contained HTML documents, you can embed images as data URIs instead of referencing external URLs.

Data URI Format

<img src="data:image/{format};base64,{base64-encoded-image-data}" />

Supported formats include png, jpeg, gif, svg+xml, and webp.

<html>
  <body style="margin: 10px; background-color: #4E279C;">
    <div style="display: flex; align-items: center;">
      <img
        src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA..."
        width="36"
        height="36"
      />
      <div style="
        margin-left: 10px;
        font-size: 24px;
        color: #fff;
        font-weight: 500;
        font-family: sans-serif;
      ">
        cloudlayer.io
      </div>
    </div>
  </body>
</html>

How to Generate Data URIs

JavaScript

const fs = require("fs");
const imageBuffer = fs.readFileSync("logo.png");
const base64 = imageBuffer.toString("base64");
const dataUri = `data:image/png;base64,${base64}`;

Python

import base64

with open("logo.png", "rb") as f:
    base64_data = base64.b64encode(f.read()).decode("utf-8")
    data_uri = f"data:image/png;base64,{base64_data}"

Note: Having a base64-encoded image embedded inside a base64-encoded HTML string is perfectly valid. The outer encoding is for the JSON transport; the inner encoding is part of the HTML specification.

Using External Stylesheets

Since cloudlayer.io fetches external resources during rendering, you can use any publicly accessible CSS framework, font library, or stylesheet.

Tailwind CSS

<html>
  <head>
    <script src="https://cdn.tailwindcss.com"></script>
  </head>
  <body class="p-8 bg-white">
    <div class="max-w-md mx-auto bg-gray-50 rounded-lg shadow p-6">
      <h1 class="text-2xl font-bold text-gray-900">Order Confirmation</h1>
      <p class="text-gray-600 mt-2">Thank you for your purchase.</p>
    </div>
  </body>
</html>

Bootstrap

<html>
  <head>
    <link
      href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
      rel="stylesheet"
    />
  </head>
  <body>
    <div class="container mt-4">
      <div class="card">
        <div class="card-body">
          <h5 class="card-title">Report Summary</h5>
          <p class="card-text">Generated on 2024-01-15</p>
        </div>
      </div>
    </div>
  </body>
</html>

Google Fonts

<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap"
      rel="stylesheet"
    />
    <style>
      body { font-family: 'Inter', sans-serif; }
    </style>
  </head>
  <body>
    <h1 style="font-weight: 700;">Beautiful Typography</h1>
    <p style="font-weight: 400;">Using Google Fonts in your documents.</p>
  </body>
</html>

Complex Layouts

CSS Grid

<html>
  <head>
    <style>
      .dashboard {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 16px;
        padding: 24px;
      }
      .card {
        background: #f9fafb;
        border: 1px solid #e5e7eb;
        border-radius: 8px;
        padding: 20px;
      }
      .card h3 {
        margin: 0 0 8px 0;
        color: #374151;
        font-size: 14px;
      }
      .card .value {
        font-size: 28px;
        font-weight: 700;
        color: #111827;
      }
      .full-width {
        grid-column: 1 / -1;
      }
    </style>
  </head>
  <body>
    <div class="dashboard">
      <div class="card">
        <h3>Total Revenue</h3>
        <div class="value">$45,231</div>
      </div>
      <div class="card">
        <h3>Orders</h3>
        <div class="value">1,247</div>
      </div>
      <div class="card">
        <h3>Customers</h3>
        <div class="value">892</div>
      </div>
      <div class="card full-width">
        <h3>Monthly Sales Chart</h3>
        <!-- Chart content here -->
      </div>
    </div>
  </body>
</html>

Flexbox

<html>
  <head>
    <style>
      .header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 20px 40px;
        border-bottom: 2px solid #e5e7eb;
      }
      .logo { font-size: 24px; font-weight: 700; }
      .meta { text-align: right; color: #6b7280; }
      .two-column {
        display: flex;
        gap: 40px;
        padding: 40px;
      }
      .two-column > div { flex: 1; }
    </style>
  </head>
  <body>
    <div class="header">
      <div class="logo">Acme Inc.</div>
      <div class="meta">
        <div>Invoice #INV-001</div>
        <div>January 15, 2024</div>
      </div>
    </div>
    <div class="two-column">
      <div>
        <h3>From</h3>
        <p>Acme Inc.</p>
        <p>123 Business St.</p>
      </div>
      <div>
        <h3>Bill To</h3>
        <p>Jane Smith</p>
        <p>456 Customer Ave.</p>
      </div>
    </div>
  </body>
</html>

Practical Examples

Generating an Invoice PDF from HTML

A complete example that generates a styled invoice PDF using JavaScript.

const html = `
<html>
  <head>
    <script src="https://cdn.tailwindcss.com"></script>
  </head>
  <body class="bg-white p-8 font-sans">
    <div class="max-w-2xl mx-auto">
      <div class="flex justify-between mb-8">
        <div>
          <h1 class="text-2xl font-bold">Acme Inc.</h1>
          <p class="text-gray-600">123 Business Street</p>
          <p class="text-gray-600">New York, NY 10001</p>
        </div>
        <div class="text-right">
          <h2 class="text-xl font-semibold text-blue-600">INVOICE</h2>
          <p>#INV-2024-001</p>
          <p class="text-gray-600">January 15, 2024</p>
        </div>
      </div>

      <table class="w-full mb-8">
        <thead>
          <tr class="border-b-2">
            <th class="text-left py-2">Item</th>
            <th class="text-right py-2">Qty</th>
            <th class="text-right py-2">Price</th>
            <th class="text-right py-2">Total</th>
          </tr>
        </thead>
        <tbody>
          <tr class="border-b">
            <td class="py-3">Web Development</td>
            <td class="text-right">40</td>
            <td class="text-right">$150.00</td>
            <td class="text-right">$6,000.00</td>
          </tr>
          <tr class="border-b">
            <td class="py-3">UI Design</td>
            <td class="text-right">20</td>
            <td class="text-right">$120.00</td>
            <td class="text-right">$2,400.00</td>
          </tr>
        </tbody>
      </table>

      <div class="flex justify-end">
        <div class="w-64">
          <div class="flex justify-between py-1">
            <span>Subtotal</span>
            <span>$8,400.00</span>
          </div>
          <div class="flex justify-between py-1">
            <span>Tax (8%)</span>
            <span>$672.00</span>
          </div>
          <div class="flex justify-between py-2 border-t-2 font-bold text-lg">
            <span>Total</span>
            <span>$9,072.00</span>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>
`;

const encoded = Buffer.from(html).toString("base64");

const response = await fetch("https://api.cloudlayer.io/v2/html/pdf", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": "<YOUR-API-KEY>",
  },
  body: JSON.stringify({
    html: encoded,
    format: "letter",
    printBackground: true,
    margin: {
      top: "0.5in",
      bottom: "0.5in",
      left: "0.5in",
      right: "0.5in",
    },
    async: false,
  }),
});

const result = await response.json();
console.log("PDF URL:", result.assetUrl);

Creating a Social Media Image

Generate an Open Graph or social media card image from HTML.

import base64
import requests

html = """
<html>
  <head>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@700;400&display=swap" rel="stylesheet">
    <style>
      body {
        margin: 0;
        width: 1200px;
        height: 630px;
        display: flex;
        align-items: center;
        justify-content: center;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        font-family: 'Inter', sans-serif;
      }
      .card {
        text-align: center;
        color: white;
        padding: 60px;
      }
      h1 {
        font-size: 48px;
        font-weight: 700;
        margin-bottom: 16px;
      }
      p {
        font-size: 24px;
        opacity: 0.9;
      }
    </style>
  </head>
  <body>
    <div class="card">
      <h1>Automate Your Document Generation</h1>
      <p>PDFs, images, and more -- powered by cloudlayer.io</p>
    </div>
  </body>
</html>
"""

encoded = base64.b64encode(html.encode("utf-8")).decode("utf-8")

response = requests.post(
    "https://api.cloudlayer.io/v2/html/image",
    headers={
        "Content-Type": "application/json",
        "x-api-key": "<YOUR-API-KEY>",
    },
    json={
        "html": encoded,
        "viewPort": {
            "width": 1200,
            "height": 630,
        },
        "async": False,
    },
)

result = response.json()
print("Image URL:", result["assetUrl"])

PDF-Specific Options

When converting HTML to PDF, you can control the output with these common options:

ParameterTypeDefaultDescription
formatstringPaper format: letter, legal, a4, etc.
landscapebooleanfalseUse landscape orientation
printBackgroundbooleanfalseInclude background colors and images
marginobject0.4inPage margins (top, bottom, left, right)
pageRangesstringall pagesWhich pages to include (e.g., "1-3, 5")
scalenumber1Scale factor (0.1 to 2)
preferCSSPageSizebooleanfalseUse CSS @page size instead of format

Paper Formats

FormatDimensions
letter8.5in x 11in
legal8.5in x 14in
tabloid11in x 17in
ledger17in x 11in
a033.1in x 46.8in
a123.4in x 33.1in
a216.54in x 23.4in
a311.7in x 16.54in
a48.27in x 11.7in
a55.83in x 8.27in
a64.13in x 5.83in

Tips

  • Always base64-encode your HTML before placing it in the JSON payload. Raw HTML in JSON leads to parsing errors.
  • Use printBackground: true if your HTML uses background colors or images — Chrome’s PDF renderer omits backgrounds by default.
  • External resources are fetched at render time. Any publicly accessible image, font, or stylesheet URL will be loaded. Private or localhost URLs will not work.
  • For large HTML documents, consider using the multipart form upload with the template endpoint instead of base64-encoding everything into a single JSON string.
  • Test locally first. Open your HTML in a browser, use Ctrl+P (print), and verify it looks correct before sending it to the API.