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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

To turn HTML into an image with JavaScript, choose the renderer based on what you have: use html2canvas to capture an element already rendered in the browser; use a hosted HTML-rendering API for supplied markup; or use a screenshot API when the page is already available at a public URL. These approaches have different execution environments and limitations. In particular, html2canvas reconstructs an image from DOM information—it does not take a native browser screenshot.

Choose the right JavaScript rendering path

Your input Where it renders Typical choice Main constraint
An element in the page currently open in a browser In that browser html2canvas It reconstructs the element from DOM information; cross-origin assets and unsupported rendering details can affect output.
HTML and CSS you provide A hosted or locally managed browser renderer An HTML-to-image endpoint or browser automation You must manage the rendering environment, execution, and any API credentials.
A publicly accessible webpage A hosted screenshot service or your own browser automation A URL screenshot endpoint Dynamic page readiness, network access, authentication, and service-specific options matter.

Use a browser-side library when the target is already in the visitor’s DOM and the capture can remain in the browser. Choose server-side rendering when you need a repeatable output from supplied markup or a URL, or when the result should be generated by your application rather than the visitor’s browser. There is no universal winner for fidelity, speed, or cost; the right choice depends on the page and deployment.

Capture an existing DOM element with html2canvas

html2canvas traverses page DOM information and builds a representation on a canvas. It does not ask the browser for a true screenshot. As the project documentation explains, “The screenshot is based on the DOM and as such may not be 100% accurate to the real representation as it does not make an actual screenshot, but builds the screenshot based on the information available on the page.” The result may differ from what the browser displays, especially where the library cannot reproduce a particular CSS effect or resource.

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

Install and load the library

For a bundled application, install the package with your package manager:

npm install html2canvas

Then import it from the module where you perform the capture:

import html2canvas from 'html2canvas';

If you use a script tag instead, load the library before the code that calls it. Ensure your target element exists and is visible when capture begins.

Capture and download a PNG

The function returns a Promise that resolves to a canvas, so use await inside an async function or handle the Promise with .then(). This example captures an element with the ID capture and triggers a PNG download:

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.
async function downloadCapture() {
  const element = document.querySelector('#capture');
  if (!element) {
    throw new Error('Could not find #capture');
  }

  const canvas = await html2canvas(element);
  const link = document.createElement('a');
  link.download = 'capture.png';
  link.href = canvas.toDataURL('image/png');
  link.click();
}

downloadCapture().catch(console.error);

Keep this work in a user-initiated action, such as a button click, if your browser or application flow requires a user gesture to download. The example writes the canvas as PNG. Check that the resulting canvas dimensions suit your use case, especially for long or large elements.

Capture a region, increase scale, or exclude an element

Capture a child element rather than the whole page to limit the output to a specific region. The project also documents options for scaling output, configuring cross-origin image handling, and excluding elements from the capture. These settings can help with particular pages, but they do not guarantee that every external asset or browser-rendered effect will be reproduced. Consult the html2canvas documentation for the options supported by the version you install.

For example, the library’s documented scale option can create a larger canvas, and the ignoreElements option can leave selected nodes out. Do not raise scale without considering the extra canvas memory required: a canvas with twice the width and height contains four times as many pixels.

Understand browser security and fidelity limits

Cross-origin images can taint the canvas

Browsers restrict reading pixel data from cross-origin resources. If an image is loaded from another origin without appropriate cross-origin permission, drawing it into the canvas can taint that canvas; operations such as toDataURL() may then fail with a security error. The image host must permit the relevant cross-origin request, and the image must be loaded in a compatible way. A library option cannot override the browser’s security policy.

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

Cross-origin iframes are not readable

Browser same-origin protections prevent a page script from recursively reading the DOM of a cross-origin iframe. A DOM reconstruction library cannot capture the iframe’s internal contents by reaching through that security boundary. If you control the embedded content, consider capturing it from its own origin or arranging a permitted server-side rendering path.

DOM reconstruction is not pixel-perfect screenshotting

Because html2canvas recreates the image from information available in the DOM, it may not match the browser’s final pixels. If exact browser output is essential, use a real browser screenshot workflow and validate it against the page and browser versions you support. Do not treat either a library’s successful Promise resolution or a generated file as proof that every visual detail was captured correctly.

Render supplied HTML or capture a live URL on a server

When the input is HTML you provide, a service’s HTML endpoint can render that markup, including inline CSS and JavaScript, before creating an image. When the page already exists online, a URL screenshot endpoint loads the page and captures it after the page’s own scripts run. Those are distinct workflows: according to the HTML to Image documentation, its URL screenshot endpoint does not inject your custom JavaScript into the target page.

Choose the endpoint by input

  • Supplied markup: send the HTML to the HTML endpoint when you need the renderer to execute inline scripts in that markup.
  • Hosted webpage: send a publicly accessible URL to the screenshot endpoint when the service should load the site’s own page and scripts.
  • Existing visitor DOM: use a browser-side library if you need the element currently rendered in that visitor’s session; a URL renderer will not automatically share that browser’s DOM or login state.

The exact request format, output parameters, service limits, and current package instructions are specific to the provider. Read the current endpoint documentation before integrating it; the HTML to Image docs describe a 30-second script budget for its HTML endpoint and a maximum five-second delay for its iframe/embed workaround on the screenshot endpoint. Those are service-specific documented limits, not general browser limits.

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

Keep API credentials on the server

The HTML to Image JavaScript client is described as a server-side SDK built on fetch, for Node.js, Bun, Deno, serverless functions, and edge runtimes. Its integration page specifies Node.js 18 or a runtime with global fetch and warns not to expose the API key in browser bundles. Follow that rule for any hosted screenshot API: keep secrets in server-side environment variables, and let your application call its own backend rather than embedding a private key in client JavaScript. The service’s advertised 50 free credits for new accounts are an offer documented on that integration page; check the provider’s current terms before relying on it.

Wait for dynamic content before capturing

A page can return initial HTML before its meaningful content is ready. Client-side rendering, lazy-loaded images, fonts, and third-party widgets may appear later. A capture taken too early can be blank or incomplete even though the URL loaded successfully.

Wait for a readiness signal when possible

If the page has a stable element that appears only after the content is ready, configure a selector wait where the rendering service supports it. This is generally more specific than guessing a fixed delay: the capture proceeds when the page signals readiness rather than after an arbitrary interval.

Use a delay only when the page offers no useful signal

A delay can be a practical fallback for content that arrives asynchronously without a dependable selector. Keep it no longer than needed, since every extra wait adds latency. For application pages you control, expose an explicit readiness marker after the content required for the image has rendered.

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.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. For a hosted page, make one GET request with the URL. The following cURL example saves a WebP screenshot of Stripe; replace the URL with your target and use your API key:

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

JavaScript can call the same endpoint from a server-side Node.js application. Keep the key out of browser bundles:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

See the ScreenshotNeo API documentation for request options. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each of those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses include X-Page-Verdict and X-Billed headers. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients. The free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots.

Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot common problems

The capture is blank or misses late content

  • Likely cause: capture began before client-rendered content appeared, or the selected element was absent or hidden.
  • Fix: check the target selector before calling html2canvas. For a hosted renderer, wait for a meaningful selector or use a short delay where the page provides no readiness signal.

toDataURL() throws a security error

  • Likely cause: a cross-origin image without compatible CORS permission was drawn into the canvas.
  • Fix: serve the image from an origin that grants the needed permission, configure the image request and library according to the project documentation, or use a rendering approach that is permitted to load the asset. Client-side code cannot bypass browser origin rules.

An iframe’s contents are missing

  • Likely cause: the frame is cross-origin and the browser prevents access to its DOM.
  • Fix: capture the embedded page separately from a context with access, or use a server-side workflow appropriate to the target. Do not attempt to work around the browser’s same-origin security boundary.

The image looks different from the browser

  • Likely cause: the library reconstructs from DOM data and may not support all rendering details or assets on the page.
  • Fix: reduce the capture to the relevant element, check unsupported effects and external resources, and compare against a real browser screenshot if fidelity is a hard requirement.

The API request fails or returns an unexpected result

  • Likely cause: invalid credentials, an inaccessible URL, an unsupported request parameter, or a page that has not reached its ready state.
  • Fix: inspect the HTTP response and the provider’s current API documentation, confirm the server-side key and URL, and add an appropriate selector wait or delay. Do not expose the key to diagnose a client-side request.

Performance, reliability, and cost decisions

Browser-side capture avoids sending the DOM to a rendering service, but it depends on the visitor’s browser, available memory, page assets, and origin permissions. Very large or high-scale canvases can consume substantial memory. Hosted rendering moves browser execution to the service or your own server and can simplify repeatable captures, but adds network latency, external availability dependencies, credential management, and potentially per-use charges. Compare current provider pricing and limits for your workload; the cited documentation does not establish a controlled benchmark of fidelity, latency, memory use, or total cost across these options.

For production, test representative pages rather than only a simple static example. Include pages with external images, embedded frames, delayed content, and the largest expected capture dimensions. Decide whether a failed capture should be retried, how long a request may wait, and whether generated files should be cached or regenerated. The appropriate retry and caching policy depends on whether the page changes frequently and whether stale output is acceptable.

Frequently asked questions

Can JavaScript turn HTML into a downloadable image?

Yes. In a browser, a library can turn an existing DOM element into a canvas that can be downloaded as an image. For supplied HTML or a hosted URL, a server-side renderer can return an image. The two methods do not render the same input in the same environment.

Can html2canvas capture an entire Drupal page?

It can be given a page element, but the output depends on what the library can reconstruct from the DOM and access under browser security rules. A successful capture does not guarantee a pixel-identical result or access to cross-origin iframe contents.

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

Can a URL screenshot endpoint run my custom JavaScript on the target site?

Not necessarily. The HTML to Image documentation distinguishes its HTML endpoint, which runs inline scripts in supplied markup, from its URL screenshot endpoint, which runs the target page’s own scripts but does not accept injected custom JavaScript.

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.