GuidesHTML to Image

How to Convert HTML to an Image with an API

Jun 14, 2026 · 4 min read · ScreenshotInk

Sooner or later most apps need to turn a chunk of HTML and CSS into a flat image. Open Graph cards for link previews. Email and receipt images that have to look identical in every inbox. Certificates and tickets. Social share cards. Server-rendered charts. The markup already exists — you just need a picture of it.

Doing this on your own machine means running headless Chromium: install it, keep it patched, manage a process pool, handle the memory it eats, and wrap all of that in a queue so two requests don't fight over the same browser. An API does that part for you. You send markup, you get an image back.

The idea

You POST your markup in the html parameter to a single endpoint. It renders on real Chromium — the same engine your users run — and returns a URL to the finished image. Inline CSS, linked stylesheets, and web fonts all apply, so what you see in a browser is what you get in the file.

The endpoint is https://screenshotink.com/v1/capture. Authenticate with a bearer token (Authorization: Bearer sk_live_…). That's the whole contract.

cURL

The fastest way to confirm it works from your terminal:

curl "https://screenshotink.com/v1/capture" \
  -H "Authorization: Bearer sk_live_…" \
  --data-urlencode html="<h1 style='font-family:sans-serif'>Hello</h1>" \
  -d format=png

The response is JSON:

{ "image_url": "https://screenshotink.com/…png" }

Fetch that URL to download the PNG, or hand it straight to an <img> tag.

Node.js

No SDK needed — fetch is built in on modern Node:

const res = await fetch("https://screenshotink.com/v1/capture", {
  method: "POST",
  headers: {
    "Authorization": "Bearer sk_live_…",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    html: "<h1 style='font-family:sans-serif'>Hello from Node</h1>",
    format: "png",
  }),
});

const { image_url } = await res.json();
console.log(image_url);

image_url is the link to your rendered PNG. Store it, email it, or pipe it into whatever needs the picture.

Python

Using the requests library:

import requests

res = requests.post(
    "https://screenshotink.com/v1/capture",
    headers={"Authorization": "Bearer sk_live_…"},
    json={
        "html": "<h1 style='font-family:sans-serif'>Hello from Python</h1>",
        "format": "png",
    },
)

image_url = res.json()["image_url"]
print(image_url)

PHP

Plain cURL, no dependencies:

<?php
$ch = curl_init("https://screenshotink.com/v1/capture");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer sk_live_…",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "html"   => "<h1 style='font-family:sans-serif'>Hello from PHP</h1>",
        "format" => "png",
    ]),
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);

echo $response["image_url"];

If your host disables cURL, the same request works with file_get_contents and a stream context:

<?php
$context = stream_context_create([
    "http" => [
        "method"  => "POST",
        "header"  => "Authorization: Bearer sk_live_…\r\n" .
                     "Content-Type: application/json\r\n",
        "content" => json_encode([
            "html"   => "<h1 style='font-family:sans-serif'>Hello</h1>",
            "format" => "png",
        ]),
    ],
]);

$response = json_decode(
    file_get_contents("https://screenshotink.com/v1/capture", false, $context),
    true
);

echo $response["image_url"];

Sizing and formats

A few parameters cover almost every layout you'll hit:

Fonts behave the way they do in a browser. System font stacks render, and @font-face web fonts load over the network before the capture is taken, so your brand typeface shows up correctly. Both inline styles and linked stylesheets (<link rel="stylesheet">) are applied, so you can paste a real template in without flattening the CSS first.

One more thing worth knowing: identical renders are cached for 24 hours. If you ask for the same HTML and the same parameters again within that window, you get the cached image back and it doesn't count against your quota — handy when the same OG card gets requested by every crawler that visits a page.

ScreenshotInk runs on EU-hosted infrastructure, with 100 free renders a month to build and test against, and $9/mo for 2,000 when you go to production.

Try it: HTML to image tool. Building link previews specifically? The Open Graph image generator wires the 1200×630 sizing up for you.

Capture it with the API

Everything here runs on the ScreenshotInk API — 100 free captures a month, no card.

More guides

The Best Screenshot APIs in 2026, Compared

An honest comparison of the top screenshot APIs in 2026 — ScreenshotInk, ScreenshotOne, ApiFlash, Urlbox and more — on pricing, formats, tooling and AI-agent support.