npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@html2img/client

v2.0.0

Published

Official JavaScript and TypeScript SDK for the html2img HTML-to-image API: render HTML or CSS to PNG, screenshot live URLs, generate images from templates, and export PDFs.

Readme

html2img - HTML to image API, rendered in real Chrome

html2img JavaScript client

npm Version Node Version Downloads License

The official JavaScript and TypeScript client for the HTML to Image API at html2img.com. Turn HTML and CSS into images, capture screenshots of live URLs, and render named templates, all returning a typed response object.

Every render runs in real Chrome, so flexbox, grid, custom properties, web fonts and inline JavaScript behave exactly as they do in the browser. The package has zero runtime dependencies, is built on the standard fetch API, and ships with full TypeScript types and dual ESM and CommonJS builds, so it works in Node.js, Bun, Deno and serverless or edge runtimes. The full API reference lives in the documentation.

What you can build

Browse the full template library, or try the no-signup browser tools to see the output before you write any code.

Requirements

  • Node.js 18 or newer (for the built-in global fetch). Bun, Deno and edge runtimes work too.
  • An HTML to Image API key, issued per account from your dashboard

Keep your API key on the server. This client is designed for server-side use: Node.js scripts, API routes, background jobs and serverless functions. Shipping your key in browser code would let anyone spend your credits.

Installation

npm install @html2img/client
# or
pnpm add @html2img/client
# or
yarn add @html2img/client
# or
bun add @html2img/client

Quick start

import { Html2img } from '@html2img/client';

const client = new Html2img('your-api-key');

const response = await client.html({
  html: '<!doctype html><html><body><h1>Hello</h1></body></html>',
  width: 1200,
  height: 630,
});

console.log(response.url); // https://i.html2img.com/abc123def456.png

CommonJS works too:

const { Html2img } = require('@html2img/client');

The API returns a JSON envelope containing the CDN URL of the generated image, not the raw bytes, so you can cache and re-serve it from your own infrastructure. New to the API? Start with the getting started guide.

TypeScript declarations are bundled, so every option, response property and error class is fully typed with no extra @types package.

Configuration

Pass your API key as a string, or an options object with optional overrides:

import { Html2img } from '@html2img/client';

const client = new Html2img({
  apiKey: 'your-api-key',
  baseUrl: 'https://app.html2img.com', // default
  timeout: 35_000, // milliseconds, default
});

Authentication is sent on every request as the X-API-Key header. See the authentication docs for issuing and rotating keys.

Injecting your own fetch

Pass a custom fetch implementation to route requests through a proxy, add your own retry or logging middleware, or support a runtime without a global fetch. The SDK still sends the X-API-Key, Accept and Content-Type headers on every request.

import { Html2img } from '@html2img/client';

const client = new Html2img({
  apiKey: 'your-api-key',
  fetch: (url, init) => myInstrumentedFetch(url, init),
});

Usage

Render HTML

POST /api/html. Send a complete HTML document and get back an image of the rendered result. Inline your CSS in a <style> block, or reference remote stylesheets and web fonts via <link> tags in the document head. See the html parameter docs for the full input.

const response = await client.html({
  html: document,
  css: 'body { background: #0f172a; color: #fff; }', // injected after load
  width: 794,
  fullpage: true,
  dpi: 2, // retina
  format: 'png',
});

Capture a screenshot

POST /api/screenshot. Fetch a public URL in a real browser and capture it. Use selector to crop to a single element, and css to hide cookie banners or chat widgets before the capture. See the url parameter docs.

const response = await client.screenshot({
  url: 'https://example.com',
  width: 1200,
  height: 630,
  selector: '#hero',
  css: '.cookie-banner, .intercom-launcher { display: none !important; }',
  dpi: 2,
});

Generate a PDF

Set format to 'pdf' on either request and the render comes back as an A4 portrait vector PDF instead of a PNG: text stays selectable and searchable, webfonts are embedded and long content paginates automatically. The API ignores width, height, dpi, fullpage and selector in PDF mode, and the response url points at a .pdf file. One credit, the same as an image. This is the HTML to PDF API; see the format parameter docs.

const response = await client.html({
  html: '<h1>Invoice #1042</h1><p>Due within 30 days.</p>',
  format: 'pdf',
});

console.log(response.url); // https://i.html2img.com/....pdf

Render a template

POST /api/v1/templates/{slug}. Render one of your named templates from a JSON data payload. The data is validated server-side per template. Browse the templates to find a slug. Templates output PNG only; format is not available on template renders.

const response = await client.template('invoice', {
  number: 1042,
  amount: '$240.00',
  due_date: '2026-07-01',
});

console.log(response.template); // invoice
console.log(response.url);

Options

client.html() and client.screenshot() both accept the following. Any option left undefined is omitted from the request, so the server applies its own default. Option names are camelCase in JavaScript and sent to the API in snake_case. The complete reference is in the parameter docs.

| Option | Type | Notes | | ----------------- | --------- | --------------------------------------------------------------------------------------------- | | css | string | Extra CSS injected after the page loads. | | width | number | Viewport width in CSS pixels (1 to 5000). | | height | number | Viewport height in CSS pixels (1 to 5000). Ignored when fullpage is true. | | fullpage | boolean | Capture the full scroll length instead of the viewport. | | dpi | number | Device pixel ratio, 1 to 4. Use 2 for retina. | | webhookUrl | string | Switch to async delivery (see below). | | msDelay | number | Wait this many milliseconds after load before capturing (1 to 5000). | | waitForSelector | string | Wait until this CSS selector appears before capturing. | | format | string | 'png' (default) or 'pdf'. PDF output is A4 portrait and ignores the sizing options above. |

client.screenshot() also accepts selector (string) to crop the capture to a single element. client.html() does not, since you control the markup.

Out-of-range values fail fast with a native TypeError or RangeError before any request is sent, mirroring the server-side validation rules.

Custom fonts are loaded by referencing them with <link> tags in your HTML document head, or by linking a web font from your captured page.

The response

Every method resolves to a RenderResponse:

response.success; // boolean
response.id; // string | null, the render id
response.url; // string | null, the CDN URL of the image
response.expiresAt; // string | null, ISO 8601 expiry of a free-tier render; null on paid plans
response.creditsRemaining; // number | null, credits left after this call
response.status; // string | null, "processing" for async jobs
response.message; // string | null
response.template; // string | null, the template slug, when applicable
response.isProcessing(); // boolean
response.raw; // object, the full decoded JSON payload

Asynchronous delivery

Synchronous requests have a 30 second budget. For captures likely to exceed it, pass a webhookUrl. The API responds immediately with status: "processing" and url: null, then POSTs the final image URL to your endpoint once rendering finishes. See the webhook_url docs.

const response = await client.screenshot({
  url: 'https://example.com/long-report',
  fullpage: true,
  webhookUrl: 'https://your-app.example.com/hooks/html2img',
});

if (response.isProcessing()) {
  // The final URL will arrive at your webhook, not on this response.
}

Error handling

Every failed request rejects with an Html2imgError. Catch that single type to handle any error, or check for a specific subclass. No raw fetch error escapes the client.

import { Html2imgError, ValidationError, InsufficientCreditsError } from '@html2img/client';

try {
  const response = await client.html({ html: document });
} catch (error) {
  if (error instanceof ValidationError) {
    // 400 or 422: inspect the per-field messages
    for (const [field, messages] of Object.entries(error.details)) {
      // ...
    }
  } else if (error instanceof InsufficientCreditsError) {
    // 402: out of credits
    const left = error.creditsRemaining;
  } else if (error instanceof Html2imgError) {
    // anything else
    error.statusCode; // number | null
    error.errorCode; // string | null, the API "code" field
    error.payload; // object, the decoded body
  }
}

| Error | When | | -------------------------- | ------------------------------------------------ | | AuthenticationError | 401, missing or invalid API key. | | InsufficientCreditsError | 402, no credits remaining. | | NotSubscribedError | 403, no active subscription. | | NotFoundError | 404, for example an unknown template slug. | | ValidationError | 400 or 422, with details per field. | | TimeoutError | 504, the synchronous render budget was exceeded. | | ServerError | 5xx, an unexpected renderer error. | | ConnectionError | the request never reached a response. | | Html2imgError | base type for all of the above. |

Other languages

Anything that can make an HTTP request works with the API. There is an official PHP client and a Laravel package, plus worked guides for Laravel, Ruby and Rails, Python, JavaScript and Node.js, React and Vue.

Development

npm install
npm test              # vitest
npm run typecheck     # tsc --noEmit
npm run lint          # prettier --check
npm run check         # all of the above
npm run build         # tsup, outputs dist/

Links

HTML to Image API · Screenshot API · HTML to PDF API · Documentation · JavaScript guide · Templates · Tools · Features · Comparisons · Articles · Pricing

Licence

MIT. See LICENSE.