Español

Lee este artículo en español.

HTML to Image: 6 Ways to Convert HTML to PNG or JPG (with Code)

Short answer: to turn HTML into an image you need something that draws it the way a browser does and then takes a picture. Inside a web page, use the html-to-image or html2canvas JavaScript libraries. On a server, open the HTML in headless Chrome with Puppeteer or Playwright and call screenshot(). If you'd rather not run a browser yourself, send the HTML to an HTML to image API and get the PNG back in one request.

Converting HTML to an image is how most social cards, Open Graph images, certificates, tickets, receipts and email banners get made: you design once in HTML and CSS, fill in the data, and export a PNG, JPG or WebP. The hard part is never the idea. It's getting fonts, images and CSS to look exactly like they do in your browser, every time, without anything cut off.

This guide covers the six ways that actually work, with code you can copy, and when each one is the right choice.

Which method to pick

MethodRuns onSame as Chrome?Best for
html-to-imageVisitor's browserAlmostDownloads from your page
html2canvasVisitor's browserAlmostThe same, older
PuppeteerYour serverYesNode.js projects
PlaywrightYour serverYesPython, Java, .NET or Node
html2imageYour computerYesQuick Python scripts
An APISomeone else's serverYesNo-code tools, no browser

One method is missing on purpose: wkhtmltoimage (and Python's imgkit, which wraps it). It uses a very old browser engine, the project was archived in 2023, and modern CSS such as grid layouts often comes out broken. Avoid it for new projects.

1. In the browser: html-to-image

If the HTML is already on screen and you want the visitor to download it as an image, the html-to-image package does it without any server:

import { toPng } from 'html-to-image';

const node = document.getElementById('card');
const dataUrl = await toPng(node, { pixelRatio: 2 });

const link = document.createElement('a');
link.download = 'card.png';
link.href = dataUrl;
link.click();

There are also toJpeg, toSvg and toBlob. Things to know: images from another domain only appear if that server allows it (CORS), web fonts must have finished loading, and a few CSS effects can come out slightly different. It only works where there's a browser, so it doesn't help in a backend or an automation.

2. In the browser: html2canvas

html2canvas is the older, very popular alternative. It reads the page's CSS and redraws it on a canvas:

const canvas = await html2canvas(document.getElementById('card'), { scale: 2 });
const png = canvas.toDataURL('image/png');

Because it re-implements the drawing itself, CSS it doesn't support is simply skipped, so check complex designs carefully. Same limits as above with images from other domains.

3. On a server with Node.js: Puppeteer

When the image has to be made on a server (a card per new blog post, a certificate per student), you need a real browser. Puppeteer opens headless Chrome, loads your HTML and takes the screenshot:

import puppeteer from 'puppeteer';

const html = '<div style="font:700 48px sans-serif;padding:40px">Hello</div>';

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1200, height: 630, deviceScaleFactor: 2 });
await page.setContent(html, { waitUntil: 'networkidle0' });
await page.screenshot({ path: 'card.png' });
await browser.close();

The result is exactly what Chrome shows. The price is running a browser on your server: memory for every page, updates, timeouts, and care with security if the HTML comes from users, because that browser can reach anything your server can reach.

4. In Python: Playwright or html2image

Playwright does the same from Python (pip install playwright, then playwright install chromium):

from playwright.sync_api import sync_playwright

html = "<div style='font:700 48px sans-serif;padding:40px'>Hello</div>"

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page(viewport={"width": 1200, "height": 630}, device_scale_factor=2)
    page.set_content(html, wait_until="networkidle")
    page.screenshot(path="card.png")
    browser.close()

For a quick script on your own computer, the html2image package uses the Chrome or Edge you already have installed:

from html2image import Html2Image

hti = Html2Image(size=(1200, 630))
hti.screenshot(html_str="<h1>Hello</h1>", save_as="card.png")

5. In PHP, Java and .NET

The idea is the same in every language: drive a headless browser.

6. With an API: no browser to run

An HTML to image API runs the browser for you: you send the HTML, it sends back the image. It's the practical option when you work in a no-code tool, when you don't want to keep Chrome running on a server, or when you only need a few images a day.

With Cofferdock, one request is enough:

curl -X POST "https://api.cofferdock.com/capture?width=1200&height=630" \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: text/html" \
  --data-binary "<h1 style='font-family:sans-serif'>Hello</h1>" \
  -o card.png

The same from Python, sending the options as JSON:

import requests

r = requests.post(
    "https://api.cofferdock.com/capture",
    headers={"x-api-key": "YOUR_KEY"},
    json={"html": "<h1>Hello</h1>", "width": 1200, "height": 630, "format": "png", "output": "binary"},
)
open("card.png", "wb").write(r.content)

What to know before choosing it: it returns PNG, JPEG or WebP up to 3840 x 2160 pixels (or the full page height), web fonts and images from the internet load fine, and wait_ms waits up to 5 seconds for them. It does not run JavaScript, so a chart drawn by a script needs one of the methods above, or a chart made by another API. Each image uses 1 credit; the free plan includes 50 a month, and you can try it without an account first.

In n8n, Make or Zapier it's one HTTP step: see the guides for n8n, Make and Zapier.

Common problems (whatever the method)

FAQ

What's the easiest way to convert HTML to an image? Without code, an HTML to image API or its online demo. With code inside a web page, the html-to-image library. On a server, Puppeteer or Playwright.

Can I convert HTML to an image without a browser? Not reliably. Something has to understand the CSS and draw it. Libraries that don't use a browser only support a small part of CSS, and APIs simply run the browser for you.

Is html-to-image the same as html2canvas? No. Both run in the visitor's browser, but html-to-image copies the element into an SVG and lets the browser draw it, while html2canvas redraws it on a canvas by itself. html-to-image tends to look closer to the original.

PNG, JPG or WebP? PNG for text, logos and sharp edges. JPG for photos, when file size matters more. WebP is lighter than both, but check that wherever you'll use the image accepts it.

How do I convert HTML to an image in n8n? With an HTTP Request node that sends the HTML to an API and returns the file. Step by step, with a free workflow to import: HTML to image in n8n.

Related guides

Full reference with every option: HTML to image API. No account yet? Create one for free.