node-html-to-image
repository·master·Indexed 21 days ago
https://github.com/frinyvonnick/node-html-to-imageA Node.js library that generates PNG or JPEG images from HTML content using Puppeteer. It supports dynamic templating via Handlebars, TypeScript type definitions, and the ability to output images either as files or Buffers. Version 6.2.0 requires Node.js 22.12 or newer.
What's inside node-html-to-image
- node-html-to-image is a Node.js library used to generate images (such as PNG or JPEG) from HTML content. It works by using puppeteer in headless mode to render the HTML and Handlebars to allow for dynamic logic within your HTML templates.
Handle asset loading with `waitUntil: 'load'` in v6
masterIn v6, the default
waitUntilbehavior isload, which does not wait for the network to be idle. This can result in missing remote images or fonts in your output.To fix this, you have two options:
- Use Base64: Embed your images and fonts directly into the HTML as base64 strings.
- Use
beforeScreenshot: Manually wait for assets to load using thebeforeScreenshothook by evaluating a script on the page to check image completion.
Example of waiting for images in
beforeScreenshot:await nodeHtmlToImage({ html: "<html><body><img src='https://example.com/logo.png' /></body></html>", beforeScreenshot: async (page) => { // wait until all images are loaded await page.evaluate(() => Promise.all( Array.from(document.images).map((image) => image.complete ? null : new Promise((done) => (image.onload = image.onerror = done)), ), ); // Note: The snippet above requires a closing parenthesis for page.evaluate }, });await nodeHtmlToImage({ html: "<html><body><img src='https://example.com/logo.png' /></body></html>", beforeScreenshot: async (page) => { // wait until all images are loaded await page.evaluate(() => Promise.all( Array.from(document.images).map((image) => image.complete ? null : new Promise((done) => (image.onload = image.onerror = done)), ), ); }, });Use the node-html-to-image CLI
masterIf you prefer using a command-line interface instead of importing the module into your code, you can use the
node-html-to-image-clipackage.https://github.com/frinyvonnick/node-html-to-image-cliInstall node-html-to-image
masterInstall the library using npm or yarn. Note that the installation includes Puppeteer, which will download a compatible version of Chromium (approximately 170MB on Mac, 282MB on Linux, and 280MB on Windows).
npm install node-html-to-image # or yarn add node-html-to-imageTypeScript support
masterThe library is written in TypeScript and provides type definitions out of the box. You can import it directly into your TypeScript projects.
import nodeHtmlToImage from 'node-html-to-image'Set output image resolution using CSS
masterSince
node-html-to-imagetakes a screenshot of the body tag's content, you can control the output resolution by setting thewidthandheightof thebodyelement via CSS within your HTML string.const nodeHtmlToImage = require('node-html-to-image') nodeHtmlToImage({ output: './image.png', html: `<html> <head> <style> body { width: 2480px; height: 3508px; } </style> </head> <body>Hello world!</body> </html> ` }) .then(() => console.log('The image was created successfully!'))Handle local images and fonts
masterLocal Images
To include local images, convert them to a
base64data URI and pass the URI via thecontentproperty to your template.const nodeHtmlToImage = require('node-html-to-image') const fs = require('fs'); const image = fs.readFileSync('./image.jpg'); const base64Image = new Buffer.from(image).toString('base64'); const dataURI = 'data:image/jpeg;base64,' + base64Image nodeHtmlToImage({ output: './image.png', html: '<html><body><img src="{{{imageSource}}}" /></body></html>', content: { imageSource: dataURI } })Local Fonts
To apply local fonts, convert the font file to base64 and include it in a
@font-facerule within your HTML<style>block using a data URI.const font2base64 = require('node-font2base64') const _data = font2base64.encodeToDataUrlSync('../my/awesome/font.ttf') const html = ` <html <head <style @font-face { font-family: 'testFont'; src: url("{{{_data}}}") format('woff2'); // don't forget the format! } </style> </head> ...`Migrate from v5 to v6
masterWhen upgrading to
node-html-to-imagev6, you must ensure your environment and configuration are updated to accommodate breaking changes in Puppeteer and Node.js requirements.Migration Checklist
- Update Node.js: Ensure you are using Node.js 22.12 or newer on your local machine, CI, and servers.
- Update
waitUntiloption: The default value forwaitUntilhas changed fromnetworkidle0toload. Becauseloaddoes not wait for network activity to settle, remote assets (images/fonts) might not be fully rendered in the screenshot. - TypeScript Fixes: If using TypeScript,
networkidle0andnetworkidle2are no longer valid types and will cause errors. Replace them withload. - Puppeteer Compatibility: If you provide your own
puppeteerorpuppeteer-coreinstance via options, ensure it is compatible with Puppeteer 25. - Install v6:
npm install node-html-to-image@6
Understand the Screenshot class structure
masterThe
Screenshotclass represents the data and configuration for a generated image. When using the library, you interact with this model to define what HTML is being rendered, which CSS selector to target, and how the resulting image should be encoded or saved.Key properties include:
html: The source HTML string to render.selector: The CSS selector used to target a specific element within the HTML (defaults tobody).type: The image format (e.g.,png,jpeg).output: The file path where the image should be saved.quality: The image quality (only applicable whentypeisjpeg).transparent: A boolean indicating if the background should be transparent.buffer: The raw data of the image (Buffer or string).
Define Content for multi-element screenshots
masterThe
Contenttype allows you to provide either a single object or an array of objects to handle multiple outputs. When using an array, you can specify a uniqueoutputpath and an optionalselectorfor each item.Contentcan be:- An object:
{ [key: string]: any }(used for Handlebars context). - An array of objects:
Array<{ output: string; selector?: string }>.
export type Content = Array<{ output: string; selector?: string }> | object;- An object:
Fix TypeScript errors for `waitUntil` in v6
masterIn v6, Puppeteer 25 has removed
networkidle0andnetworkidle2. Using these values in TypeScript will result in aTS2322error. You should replace them withload.// error TS2322 await nodeHtmlToImage({ html, waitUntil: "networkidle0" }); // use this instead await nodeHtmlToImage({ html, waitUntil: "load" });Get image as a Buffer instead of saving to disk
masterIf you do not provide an
outputpath,nodeHtmlToImagereturns a Promise that resolves to a Buffer containing the image data. This is useful for serving images directly via web frameworks like Express.const express = require('express'); const router = express.Router(); const nodeHtmlToImage = require('node-html-to-image'); router.get(`/api/tweet/render`, async function(req, res) { const image = await nodeHtmlToImage({ html: '<html><body><div>Check out what I just did! #cool</div></body></html>' }); res.writeHead(200, { 'Content-Type': 'image/png' }); res.end(image, 'binary'); });