How to Convert HTML to Images with a Free API

2026-04-17 | Tags: [html2image, api, screenshot, automation, tutorial]

How to Convert HTML to Images with a Free API

Need to turn HTML into an image? Maybe you're generating social cards, email headers, invoices, or badges. The typical approach — spin up Puppeteer, render HTML in a headless browser, take a screenshot — is slow to set up and painful to maintain in production.

The HTML to Image API does this in one POST request. Send HTML, get an image back.

Quick Start

curl -X POST "https://hermesforge.dev/api/html2image" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<div style=\"padding:40px;background:#1a1a2e;color:#e94560;font-family:sans-serif;font-size:48px;text-align:center\">Hello World</div>",
    "width": 800,
    "height": 200,
    "format": "png"
  }' --output hello.png

That's it. No API key required for basic usage. The response is the raw image bytes.

Python: Generate Dynamic Images

import requests

def html_to_image(html, filename, width=800, height=600, fmt="webp"):
    """Convert HTML string to an image file."""
    response = requests.post(
        "https://hermesforge.dev/api/html2image",
        json={
            "html": html,
            "width": width,
            "height": height,
            "format": fmt,
        }
    )
    with open(filename, "wb") as f:
        f.write(response.content)
    print(f"Saved {filename} ({len(response.content)} bytes)")

# Example: status badge
html_to_image(
    '<div style="display:inline-flex;align-items:center;gap:8px;padding:6px 12px;'
    'background:#2d333b;border-radius:6px;font-family:monospace;font-size:14px;color:#adbac7">'
    '<span style="width:8px;height:8px;border-radius:50%;background:#3fb950"></span>'
    'All systems operational</div>',
    "status.webp",
    width=300,
    height=40,
)

Use Case: Social Cards from Templates

Generate unique social/OG images for every blog post without a design tool:

def social_card(title, author, bg_color="#667eea"):
    """Generate a 1200x630 social card."""
    html = f"""
    <div style="width:1200px;height:630px;display:flex;align-items:center;
    justify-content:center;background:linear-gradient(135deg,{bg_color},#764ba2);
    font-family:-apple-system,sans-serif;color:white;text-align:center">
      <div>
        <h1 style="font-size:52px;margin:0 60px 20px">{title}</h1>
        <p style="font-size:22px;opacity:0.8">by {author}</p>
      </div>
    </div>"""
    return requests.post(
        "https://hermesforge.dev/api/html2image",
        json={"html": html, "width": 1200, "height": 630, "format": "png"}
    ).content

# Generate cards for all posts
posts = [
    ("How We Cut API Latency by 80%", "Alice"),
    ("Migrating to Postgres 17", "Bob"),
]
for title, author in posts:
    filename = title.lower().replace(" ", "-")[:40] + ".png"
    with open(filename, "wb") as f:
        f.write(social_card(title, author))

This replaces tools like Cloudinary's text overlay API or Vercel's @vercel/og — but works with any stack, not just Next.js.

Use Case: Invoices and Receipts

def generate_invoice(items, total):
    rows = "".join(
        f'<tr><td style="padding:8px;border-bottom:1px solid #eee">{name}</td>'
        f'<td style="padding:8px;border-bottom:1px solid #eee;text-align:right">${price:.2f}</td></tr>'
        for name, price in items
    )
    html = f"""
    <div style="padding:40px;font-family:-apple-system,sans-serif;background:white;color:#333">
      <h1 style="color:#1a1a2e;margin-bottom:30px">Invoice</h1>
      <table style="width:100%;border-collapse:collapse">
        <tr style="border-bottom:2px solid #333">
          <th style="text-align:left;padding:8px">Item</th>
          <th style="text-align:right;padding:8px">Amount</th>
        </tr>
        {rows}
        <tr>
          <td style="padding:12px 8px;font-weight:bold;font-size:18px">Total</td>
          <td style="padding:12px 8px;text-align:right;font-weight:bold;font-size:18px">${total:.2f}</td>
        </tr>
      </table>
    </div>"""
    return requests.post(
        "https://hermesforge.dev/api/html2image",
        json={"html": html, "width": 600, "height": 400, "format": "png", "background": "#ffffff"}
    ).content

Parameters

Parameter Default Description
html required HTML string to render
width 800 Image width in pixels (max 1920)
height 600 Image height in pixels (max 1080)
format png png, jpeg, or webp
scale 1 Retina scaling: 1, 2, or 3
background transparent CSS color for background
quality 80 JPEG/WebP quality (1-100)

Tips

vs. Screenshot API

Both endpoints produce images, but they serve different purposes:

HTML to Image Screenshot API
Input Raw HTML string URL to capture
Use case Generate images from templates Capture existing web pages
Hosting No hosting needed Page must be accessible via URL
Speed Faster (no network fetch) Depends on page load time

If you're generating images from data (cards, badges, invoices), use HTML to Image. If you're capturing an existing webpage, use the Screenshot API.

Getting Started

No signup needed. Just POST your HTML:

POST https://hermesforge.dev/api/html2image
Content-Type: application/json

{"html": "<h1>Your HTML here</h1>"}

Free tier: 10 requests/day without an API key, 50/day with a free key.