October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
HTML to PNG

How to Convert HTML to PNG with an npm Package (Node.js Guide)

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a server-side HTML string, the most direct npm solution is node-html-to-image. It uses Puppeteer in headless mode, renders your markup in Chromium, and writes a PNG (or JPEG) file or returns an image buffer. You do not need to open a visible browser window. If you already have a DOM element in a browser, use html-to-image instead; for maximum browser control, use Puppeteer or Playwright directly.

Choose the package that matches your input

The key decision is whether your HTML exists as a string on the server or as a live DOM node in a browser.

Situation Best fit Why
Node.js receives an HTML string and should create a file or buffer node-html-to-image Short API around headless Puppeteer; accepts html and an output path.
A page already contains the element you want to export html-to-image Clones a DOM node and returns a PNG data URL, blob, canvas, SVG, or JPEG.
You need direct browser, navigation, lifecycle, or element control Puppeteer Low-level Chromium API with page and element screenshots.
You need browser-engine coverage Playwright Screenshot APIs for Chromium, Firefox, and WebKit, including full-page capture.

There is no independent benchmark establishing that one option is universally faster or more pixel-perfect. Rendering depends on fonts, external assets, browser version, viewport, and page complexity.

Convert an HTML string with node-html-to-image

Install it

npm install node-html-to-image

The package uses Puppeteer, so installation downloads a Chromium build. Its documentation gives approximate download sizes of 170 MB on macOS, 282 MB on Linux, and 280 MB on Windows; these are package notes, not a performance benchmark. In minimal containers, allow disk space and ensure the browser can run with your sandbox policy.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Minimal ES module example

import nodeHtmlToImage from 'node-html-to-image';

await nodeHtmlToImage({
  output: './image.png',
  html: '<html><body><h1>Hello world!</h1></body></html>'
});

console.log('Wrote image.png');

Save this as convert.mjs and run node convert.mjs. The documented default type is PNG. The output path is created by the package; use a writable directory in production.

Return a buffer instead of writing a file

import fs from 'node:fs/promises';
import nodeHtmlToImage from 'node-html-to-image';

const html = `
  <!doctype html>
  <html>
    <head>
      <meta charset="utf-8">
      <style>
        body { margin: 0; font-family: Arial, sans-serif; }
        .card { width: 800px; padding: 40px; background: #111827; color: white; }
      </style>
    </head>
    <body><div class="card"><h1>Build report</h1><p>Rendered in Node.js</p></div></body>
  </html>`;

const image = await nodeHtmlToImage({ html });
await fs.writeFile('./report.png', image);
console.log(`Saved ${image.length} bytes`);

Returning bytes is useful for an HTTP response, object storage upload, or email attachment. Set your response content type to image/png.

Control what gets rendered

Target one element with selector

const image = await nodeHtmlToImage({
  html: `<body>
    <div id="page">Ignore this wrapper</div>
    <article class="invoice"><h1>Invoice 1042</h1></article>
  </body>`,
  selector: '.invoice',
  type: 'png'
});

The documented default selector is body. Selecting a component avoids capturing unrelated page content. Transparent PNG output is supported when your CSS leaves the target background transparent.

Wait for content and scripts

Use the package’s waitUntil, timeout, and lifecycle hooks when HTML depends on JavaScript or remote assets. beforeRendering runs before rendering and beforeScreenshot runs before the screenshot, allowing you to modify the page or wait for a selector.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const image = await nodeHtmlToImage({
  html: `<body>
    <div id="app">Loading...</div>
    <script>setTimeout(() => app.textContent = 'Ready', 300);</script>
  </body>`,
  selector: '#app',
  waitUntil: 'networkidle0',
  timeout: 30000,
  beforeScreenshot: async (page) => {
    await page.waitForSelector('#app');
  }
});

Choose a finite timeout even when waiting for network idle: analytics, streaming requests, or advertisements can keep a page active indefinitely.

PNG, JPEG, and output choices

Use type: 'png' for lossless text, transparency, and UI assets. Use type: 'jpeg' where a smaller photographic file matters; JPEG does not preserve transparency. The package can write to output or return image data when no output path is supplied.

Concurrency and repeatable rendering

For batch work, use the documented concurrency controls rather than launching an unlimited number of Chromium pages. Reuse a controlled browser process where your deployment allows it, cap simultaneous jobs, and place a queue in front of conversion. Set explicit viewport dimensions, install the fonts your design needs, and pin your package/browser versions if identical output matters.

Make external fonts, images, and CSS reliable

  • Fonts: A missing web font causes fallback metrics and changed line breaks. Bundle the font, preload it, or wait for document.fonts.ready in a hook.
  • Images: Use reachable HTTPS URLs or data URLs and wait for the images to complete. Private URLs need credentials or a server-side asset strategy.
  • Cross-origin content: Browser security rules still apply. Canvas-based approaches can fail on cross-origin or tainted content; configure CORS or inline the asset.
  • Layout: Give the target a deliberate width, height, margin, and background. Responsive designs otherwise use the default viewport and may wrap differently than expected.
  • Animation: Disable transitions and animation when deterministic output is required; otherwise the capture can occur at different frames.

Browser-side option: html-to-image

html-to-image is designed for an existing browser DOM node. It clones the node, copies computed styles, embeds fonts and images, serializes through SVG foreignObject, and rasterizes to a canvas.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { toPng } from 'html-to-image';

const node = document.querySelector('#card');
const dataUrl = await toPng(node, {
  backgroundColor: '#ffffff',
  pixelRatio: 2,
  cacheBust: true
});

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

Its options include background color, width and height, canvas dimensions, pixel ratio, cache busting, font embedding, and image placeholders. Very large DOM trees can exceed data-URL limits. Cross-origin images or fonts without appropriate CORS headers may taint the canvas and prevent a successful export. This is a browser-DOM tool, not a replacement for server-side Chromium when your input is only an HTML string.

Use Puppeteer directly when you need browser control

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({ headless: true });
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1200, height: 800, deviceScaleFactor: 2 });
  await page.setContent(`<html><body><h1>Hello</h1></body></html>`, {
    waitUntil: 'networkidle0'
  });
  await page.screenshot({ path: 'puppeteer.png', fullPage: true });
} finally {
  await browser.close();
}

Puppeteer’s official API supports page screenshots that return a base64 string or Uint8Array, as well as element screenshots. Choose it when you need request interception, authentication flows, custom browser flags, or fine-grained page lifecycle control that a wrapper does not expose.

Use Playwright for multi-engine coverage

import { chromium } from 'playwright';

const browser = await chromium.launch();
try {
  const page = await browser.newPage({ viewport: { width: 1200, height: 800 }, deviceScaleFactor: 2 });
  await page.setContent('<h1>Playwright</h1>');
  await page.screenshot({ path: 'playwright.png', fullPage: true });
} finally {
  await browser.close();
}

Playwright’s screenshot API infers PNG from the .png extension and supports full-page, element, quality, viewport, and CSS/device-scale options. Its value is browser-engine choice and a broad automation API; its trade-off is another browser installation and a larger operational surface.

Or skip the browser setup

ScreenshotNeo is a hosted screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report X-Page-Verdict and X-Billed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Example using cURL (see the ScreenshotNeo documentation for all options):

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Equivalent Node.js and Python calls:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also provides full-page and CSS-selector captures, dark mode, device presets and custom viewports, retina scale, PDF controls, custom CSS/JavaScript, clicks, waits, request blocking, headers/cookies/user agents, timezone and geolocation, transparent backgrounds, resizing, selectable-TTL caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to try it.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting common failures

“Cannot find Chromium” or launch errors

Run the package installation again so Puppeteer’s browser download completes, verify the container has executable shared libraries, and check your sandbox flags and permissions. Do not assume a system Chrome path unless you configure it explicitly.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The image is blank or only partly rendered

Wait for the specific application selector rather than relying only on a short delay. Confirm that scripts are allowed, remote assets resolve from the server, and the selected element actually has dimensions.

Fonts or images differ from the webpage

Inspect network access and CORS, bundle critical assets, wait for font and image completion, and set a fixed viewport. A headless process cannot load assets that require a browser session unless you provide cookies or authorization.

The job times out

Use a finite, appropriate timeout; replace perpetual network-idle waits with a readiness selector; block unnecessary requests; and investigate long-running third-party scripts.

html-to-image throws a security or canvas error

Check for cross-origin images, fonts, or iframes. Serve them with CORS headers, inline them, or move the capture to a server-side browser.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Batch conversion exhausts memory

Limit concurrency, close pages and browsers in finally blocks, avoid retaining base64 strings, and stream or upload buffers promptly. Large full-page captures consume more memory than viewport shots.

Operational checklist

  1. Choose server HTML (node-html-to-image) or an existing DOM (html-to-image).
  2. Set a fixed viewport, target selector, output type, and background.
  3. Make fonts, images, and authenticated resources available.
  4. Wait for a real readiness condition and enforce a timeout.
  5. Cap concurrency and clean up browser resources.
  6. Test transparent, long, asset-heavy, and failure cases before production.
  7. Record package and browser versions when reproducibility matters.

Frequently Asked Questions

Can I convert HTML to PNG without opening a visible browser?

Yes. node-html-to-image runs Puppeteer in headless mode, so no visible browser window is required.

Which package should I use for an HTML string in Node.js?

Start with node-html-to-image; it is the shortest documented path from an HTML string to a PNG file or buffer.

Why does my exported image miss web fonts?

The rendering process may finish before fonts load, or the server may not be able to fetch them. Bundle or authorize the fonts and wait for document.fonts.ready.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Is html-to-image suitable for server-side HTML conversion?

It is primarily for an existing browser DOM node. For a server-side string, use node-html-to-image, Puppeteer, or Playwright.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.