HTML to Image API: Render HTML/CSS Templates to PNG
Pricing
from $2.50 / 1,000 image rendereds
HTML to Image API: Render HTML/CSS Templates to PNG
Render HTML/CSS to image: PNG, JPG, WebP or PDF. Fill a template's {{placeholders}} from a list of data rows and get one image per row: OG images, social cards, certificates, badges. Transparent backgrounds, retina scale, element clipping. No API key. Pay per image.
Pricing
from $2.50 / 1,000 image rendereds
Rating
0.0
(0)
Developer
Alexander Daskalov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Turn HTML and CSS into PNG, JPG, WebP or PDF files, one per row of your data. Write one template with {{placeholders}}, give it a list of rows (blog posts, attendees, products…), and get a finished image for every row, each with its own download link:
- 🖼️ Templates + data rows:
{{title}},{{author}},{{user.name}}are filled from each row, so 500 rows make 500 images in one run. - 📦 PNG, JPEG, WebP or PDF: pick the format, size and quality.
- 🔍 Retina scale: render at 2× or 3× for crisp images on high-DPI screens.
- ✂️ Element clipping: capture just one element (a card, a badge) with a CSS selector, or the full page.
- 🫥 Transparent backgrounds: PNG and WebP badges and stickers with no white box.
- ⚙️ A real browser: headless Chromium runs your JavaScript (charts work), loads Google Fonts and public images, and has emoji and Chinese/Japanese/Korean fonts built in.
No API key, no account to connect, no setup.
What can you do with it?
- Open Graph and social share images: one branded card per blog post, product or listing for Facebook, LinkedIn, X and Slack previews.
- Certificates and badges from an attendee list: course certificates, event badges and name tags, one file per person.
- Price tags and product labels: shelf labels and promo tags from a product sheet.
- Email banners: personalised header images per customer or campaign.
- Charts rendered from HTML/JS: draw a chart with your favourite JavaScript library and save it as an image for reports and emails.
- HTML invoices and receipts to PDF: turn an invoice template and a list of orders into PDFs.
- Dynamic images for AI agents: let your assistant design an image in HTML and get back a PNG link.
How it works
- You write the HTML (a snippet or a full document) and, if you like, extra CSS.
- Each object in Data rows fills the template's placeholders and becomes one image.
- Every file is saved in the run's key-value store, and the dataset gets one record per image with its download link.
A short template:
<div class="card"><p class="site">{{site}}</p><h1>{{title}}</h1><p>{{author}} · {{date}}</p></div>
and its data rows:
[{"site": "blog.example.com", "title": "How we cut our cloud bill by 40%", "author": "Maria Lopez", "date": "Oct 2026", "fileName": "cloud-bill"},{"site": "blog.example.com", "title": "10 lessons from shipping every week", "author": "Sam Chen", "date": "Oct 2026", "fileName": "shipping-weekly"}]
give two images, cloud-bill.png and shipping-weekly.png.
Placeholder rules:
| Placeholder | What it inserts |
|---|---|
{{name}} | The value as text, HTML-escaped, so <, > and & in your data show up as typed |
{{{name}}} | The value as raw HTML, e.g. "<b>Gold</b> member" or an <img> tag |
{{user.name}}, {{items.0}} | Nested values: object fields and list items (counting from 0) |
| a field the row doesn't have | Renders empty, and is listed in the record's missingFields, so a typo in a field name is easy to spot |
A null value also renders empty. With no data rows, the HTML is rendered once as it is.
Output options
| Option | Default | What it does |
|---|---|---|
Format (format) | png | png, jpeg, webp or pdf |
Width / Height (width, height) | 1200 × 630 | Viewport size in CSS pixels, 16 to 4096. For PDF, the page size |
Scale (scale) | 1 | Device pixel ratio, 1 to 3. 2 = retina: a 1200×630 card becomes 2400×1260 pixels |
Full page (fullPage) | off | Capture the whole content height, not just the viewport. For PDF, one page as tall as the content |
Clip to element (selector) | none | Capture only the first element matching a CSS selector, e.g. #card (images only) |
Transparent background (transparentBackground) | off | No white background, for PNG and WebP. Your HTML must not set its own background |
Quality (quality) | 90 | JPEG and WebP quality, 1 to 100 |
Extra wait (waitMs) | 0 | Wait longer after the page, images and fonts have loaded, e.g. for chart animations (up to 10,000 ms) |
File name field (fileNameField) | fileName in the example | Which data field names the file. Names are cleaned up to safe characters and duplicates get -2, -3…; without it, files are image-1, image-2… |
How much does it cost?
Pay per image. No monthly fee.
| Event | Price (FREE/BRONZE) | Lower on paid plans |
|---|---|---|
| Image rendered (PNG, JPEG, WebP or PDF, saved with its link) | $0.003 / image | down to $0.0025 |
| Actor start | $0.00005 / run | — |
1,000 images cost $3. You pay only for images actually rendered and saved. Nothing is charged for an image that fails to render.
Cap your spend: set a maximum cost per run. When the budget runs out, no more images are rendered.
How to render HTML to images
- Click Try for free. The example input renders two blog post cards.
- Paste your own HTML into HTML template and your rows into Data rows.
- Optional: change the size, format, scale or file name field.
- Run, then open the Images view and click a download link, or open the Image files tab.
Input example
{"html": "<div class=\"badge\"><b>{{name}}</b><br>{{role}}</div>","css": ".badge { width: 400px; padding: 24px; border-radius: 16px; background: #111827; color: #fff; font: 24px sans-serif; }","data": [{"name": "Ana Petrova", "role": "Speaker", "fileName": "ana"},{"name": "Leo Martin", "role": "Attendee", "fileName": "leo"}],"selector": ".badge","scale": 2,"transparentBackground": true,"fileNameField": "fileName"}
Output
One record per image:
{"index": 0,"fileName": "cloud-bill.png","url": "https://api.apify.com/v2/key-value-stores/<store-id>/records/cloud-bill.png","format": "png","width": 1200,"height": 630,"bytes": 48211,"data": {"site": "blog.example.com", "title": "How we cut our cloud bill by 40%", "author": "Maria Lopez", "date": "Oct 2026", "fileName": "cloud-bill"},"missingFields": [],"renderMs": 310}
Getting the files:
urlis the download link of the file. If your account keeps storages private, add?token=YOUR_TOKENto it.- All files are also in the run's key-value store (the Image files tab in Console, or the API), under their
fileName. - For PDFs,
urlpoints to a.pdffile andwidth/heightare the page size in CSS pixels. widthandheightof images are real pixels, so they include the scale.
How fast is it?
Images are rendered 4 at a time in one browser. Measured on Apify: 200 images (1200×630 PNG) in 330 seconds with 1024 MB of memory, about 1.6 seconds per image (around 36 a minute).
Security and limits
- HTML up to 1 MB, up to 5,000 data rows per run, and 30 seconds per image.
- Pages can load public images, fonts and scripts from the internet.
- Page requests (HTTP and HTTPS) to private networks, such as localhost, internal IPs and cloud metadata addresses, are blocked, and local files aren't loaded. WebSockets and WebRTC are switched off, and audio and video aren't loaded.
- An image that fails (a timeout, or a selector that matches nothing) is skipped, logged with its row number and not charged; the other rows carry on. If 20 images fail in a row, the run stops starting new ones, since the template is most likely broken.
Use it with AI agents (MCP)
https://mcp.apify.com?tools=bossless/html-to-image
Ask your assistant "make an Open Graph image for each of these blog posts", and it writes the HTML, runs this actor and gives you the image links.
Use the API from code
curl -X POST "https://api.apify.com/v2/acts/bossless~html-to-image/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"html": "<h1 style=\"font:64px sans-serif\">{{title}}</h1>", "data": [{"title": "Hello"}], "width": 800, "height": 400}'
from pathlib import Pathfrom apify_client import ApifyClientclient = ApifyClient("YOUR_TOKEN")run = client.actor("bossless/html-to-image").call(run_input={"html": "<div style='padding:40px;font:48px sans-serif'>Certificate for <b>{{name}}</b></div>","data": [{"name": "Ana Petrova"}, {"name": "Leo Martin"}],"width": 1600,"height": 1100,"format": "pdf",})store = client.key_value_store(run["defaultKeyValueStoreId"])for item in client.dataset(run["defaultDatasetId"]).iterate_items():record = store.get_record_as_bytes(item["fileName"])Path(item["fileName"]).write_bytes(record["value"])print(item["fileName"], item["bytes"], "bytes", item["missingFields"])
FAQ
Can I use Google Fonts? Yes. Add the font's <link> tag from Google Fonts to your HTML (or an @import in the CSS) and use the font family. Any public font file works the same way.
Does JavaScript run? Do charts work? Yes. Scripts run in a real Chromium browser, so chart libraries loaded from a public CDN draw before the capture. If a chart animates, set Extra wait to a few hundred milliseconds.
Do emoji and Chinese, Japanese or Korean text work? Yes. Emoji and CJK fonts are installed, so text in any language renders instead of showing boxes.
How do I get a transparent PNG? Turn on Transparent background, choose PNG (or WebP), and make sure your HTML doesn't set a background on body or the element you capture. Clipping to the element with Clip to element gives a tight image with no empty margin.
How do I get retina images? Set Scale to 2 (or 3). The layout stays the same and the image gets 2× (or 3×) the pixels.
What page size does a PDF have? The Width × Height you set, in CSS pixels, with backgrounds printed. With Full page on, the page is as tall as the content.
How do I get the files? Every record has a url download link, and all files are in the run's key-value store under their fileName. See Output.
What if a placeholder isn't in my data? It renders empty and is listed in missingFields, so you can find typos without opening every image.
Is my HTML stored? Your input and the rendered files stay in your own Apify run storage. Nothing is sent anywhere else, except the requests your own page makes for its images, fonts and scripts.
Is this an official product of any provider? No. This is an independent tool and is not affiliated with or endorsed by Google, the Chromium project or any screenshot service.
Related tools
- Handwriting to Text: photos, scans and PDFs of handwritten notes, letters and forms turned into text, line by line, in any language.
