HTML to Image
html2png.devKey Features
Tech Stack
Key Features
Tech Stack
I thought webp would be better for this and checked again just to be sure, and yes, it would be better for this. WebP is quite well supported, albeit not as well supported as png, and it can have significantly smaller file sizes for the same lossless image as png.
chromium --headless --disable-gpu --screenshot=output.png --window-size=1920,1080 --hide-scrollbars index.html
Also works great for HTML to PDF: chromium --headless --disable-gpu --no-pdf-header-footer --run-all-compositor-stages-before-draw --print-to-pdf=output.pdf index.htmlGenerally I find production-ready images have more synergy and tend to be web-scale. Often they're built from the ground up for AI & are blazing fast, at scale, and empower your team whilst unlocking new possibilities. As my sibling comment suggests, being cloud-native is a crucial factor too.
No cruft. No legacy formats.
Just buttery smooth production readiness.
But buttery bloated if the images don't run OptiPNG before exporting.
Claude Code loves to say that everything is production ready, even if it doesn't quite compile or pass automated tests yet.
# html2png.dev Infrastructure Analysis
## Server Location
| Property | Value | |----------|-------| | *IP Address* | `104.28.157.29` | | *Organization* | *CLOUDFLARENET* | | *ASN* | AS13335 (Cloudflare) | | *City* | Narita | | *Region* | Chiba | | *Country* | *Japan* |
## Browser Engine
| Property | Value | |----------|-------| | *Browser* | Chrome 126.0.0.0 (Headless) | | *Automation* | Puppeteer/Playwright (`navigator.webdriver: true`) | | *User Agent* | `Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36` | | *Platform* | Linux x86_64 | | *Vendor* | Google Inc. |
## Graphics Rendering
| Property | Value | |----------|-------| | *WebGL Renderer* | ANGLE (Google, Vulkan 1.3.0 SwiftShader Device (Subzero)) | | *WebGL Vendor* | Google Inc. (Google) | | *GPU Type* | SwiftShader (software GPU - no real GPU!) | | *Color Depth* | 16 bit |
## Server Hardware
| Property | Value | |----------|-------| | *CPU Cores* | 4 | | *Device Memory* | Hidden (containerized) | | *Virtual Screen* | 1024x768 @ 2x DPR | | *Outer Window* | 500x88 (headless indicator) | | *Max Touch Points* | 0 | | *Languages* | en-US |
## Automation Detection Signals
| Property | Value | |----------|-------| | *navigator.webdriver* | `true` ← Puppeteer/Playwright! | | *window.chrome* | `object` (exists) | | *chrome.runtime* | `undefined` | | *chrome.app* | `object` | | *chrome.csi* | `function` | | *chrome.loadTimes* | `function` | | *plugins.length* | 5 |
## Full Tech Stack
``` ┌─────────────────────────────────────────────────────────────┐ │ html2png.dev Stack │ ├─────────────────────────────────────────────────────────────┤ │ CDN/Proxy: Cloudflare (AS13335) │ │ Edge: Cloudflare Japan (Narita, Chiba) │ │ Frontend: Nuxt.js 3 (Vue.js) │ │ Backend: Node.js API │ │ Renderer: Puppeteer/Playwright │ │ Browser: Headless Chrome 126 │ │ GPU: SwiftShader (software rendering) │ │ Platform: Linux x86_64 container (4 cores) │ │ Storage: Ephemeral blob storage │ ├─────────────────────────────────────────────────────────────┤ │ Likely Host: Cloudflare Workers + Durable Objects │ │ or: Vercel/Railway behind Cloudflare │ └─────────────────────────────────────────────────────────────┘ ```
## How It Works
1. *Request* → Cloudflare edge (Japan) 2. *API* → Node.js server receives HTML + params 3. *Render* → Puppeteer launches headless Chrome 4. *Capture* → SwiftShader renders WebGL/CSS without GPU 5. *Store* → Image saved to blob storage 6. *Response* → JSON with public URL returned
## Key Insights
- *Cost-efficient*: SwiftShader means no expensive GPUs needed - just CPU containers - *Headless Chrome 126*: Recent but not bleeding edge version - *Cloudflare-fronted*: Fast global delivery via CF edge network - *Ephemeral storage*: Generated images are temporary/public - *No auth required*: Free tier, open API
## API Endpoint
```bash POST https://html2png.dev/api/convert?width=1200&height=630&forma... Content-Type: text/html
<your-html-here> ```
--- Analysis performed: 2024-12-24
- IP: 104.28.157.29 - Org: Cloudflare (AS13335) - Location: Narita, Chiba, Japan - Browser: Chrome 126.0.0.0 headless - Automation: Puppeteer/Playwright - navigator.webdriver: true - Platform: Linux x86_64 - CPU cores: 4 - WebGL: ANGLE + Vulkan 1.3.0 + SwiftShader - GPU: SwiftShader (software rendering) - Screen: 1024x768 virtual - DevicePixelRatio: 2 - Color depth: 16 bit - Window: 500x88 outer (headless) - Languages: en-US - Plugins: 5 - Frontend: Nuxt.js - Storage: ephemeral blob
<!doctype html>
<html lang="en">
<body>
<pre class="mermaid">
graph LR
A --- B
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
</pre>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
</script>
</body>
</html>
Then html2png.dev will serve you: https://html2png.dev/api/blob/oTVGhhCc6rDZYQFDIE3EGkcKs-KO6J9-_DHs-jO2OJc-d23fb4f2.png
[^1]: https://mermaid.js.org/config/usage.html#simple-full-exampleWhat if the input to the JavaScript (mermaid in this case) is not trusted to run on the end client machines but by running untrusted input on a sandbox (this service, or self hosted idk) is somehow acceptable and the output a blob of an image is acceptable to display on the actual client machines.
Takes the planets to align just right and need us to squint just enough but I think we can find something if we look hard enough.
But then mermaid can simply output PNG so you could run it as a worker... Thinking...
I'm not sure of what "production ready" is supposed to mean here, but the demo image is not optimized, `optipng` command decreases its size by 53.21%.
Seeing this term in marketing materials signals that the target audience is non-professionals (and I don’t mean this derisively, only that we need to apply a different lens).
> The high-performance HTML to PNG engine. Built for developers, agents, and automation. Completely free to use. All generated assets are public and ephemeral.
...I assume the implications are that:
1. this service will scale to meet request load without QoS degradation (i.e. it's probably running on FaaS infra), rather than being a fixed-size slowly-elastic cluster that would get choked out if your downstream service got popular and flooded it with thousands of concurrent requests
2. you can directly take the URLs the service spits out, and serve them to your downstream service's clients, without worrying much about deliverability, because there's an object store + edge CDN involved.
In other words, it's not just a single headless-chromium instance running on a box somewhere; you could actually use this thing as an upstream dependency and rely on it.
> the demo image is not optimized, `optipng` command decreases its size by 53.21%
Given that the author's imagined use-case is giving non-multimodal LLMs a way to emit visuals (the prompt at the bottom of the page starts "When asked to create visuals, charts, or mockups"), I think their idea is that the resulting rendered images would more-likely-than-not only be requested once, immediately, to display the result to the same user who caused the prompt to be evaluated.
Where, in that case, the metric of concern isn't "time+bytes cost for each marginal fetch of the resulting image from the CDN"; but rather "end-to-end wall-clock time required to load the HTML in the headless browser, bake the image, push it to the object store, and serve it once to the requesting user."
OptiPNG would slightly lower that last "serve it once" cost, but massively inflate the "bake the image" time, making it not worth it.
(I suppose they could add image optimization as something you could turn on — but "image optimization at the edge" is already a commodity product you can get from numerous vendors, e.g. Cloudflare.)
Think of the GitHub thumbnails where the PR number changes constantly and has to be reflected on the image preview
google-chrome --headless --screenshot=my_screenshot.png https://www.example.com
So it's installed now but still un-personalized like it was installed 5 minutes ago. I don't use it except with Antigravity.
And I guess this is exactly what this service does under the hood.
Works fine.
What’s the catch, or how I can I be sure it will still be around in 3 months?
No snark, genuinely curious as I would use this if I could count on it.
I created an svg to png API to generate open graph images a while back. It works pretty well and can be hosted on Cloudflare Workers for free.
Not that it matters, but curious what percentage of this service was “vibe-coded”?
it's literally waht i've been saying all along when I came across mcp "why can't i just give agent a prompt and it will run the rest api calls for me"
there's still some MCPs which makes sense but we have it for literally everything when just a prompt will do the job!
now on the topic of html2png i do wonder is this like the self-hostable version on github https://github.com/maranemil/HTML2Png where they use canvas? or is this something else ?
I am sure @simonw has some ideas :) -- he recently blogged about HTML tools which is also one or my favorite use cases for LLMs.
Maybe similar to SVG generation, this could be a more powerful / flexible way to generate complex images / screen mockups and the like on-the-fly.
Not affiliated with Hacker News or Y Combinator. We simply enrich the public API with analytics.