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.

Wait for the Promise returned by html2canvas(element). When it fulfills, its value is the rendered <canvas>. Put export, display, or upload code after await, or in .then(); handle a rejected Promise separately. The old onrendered callback is not the current completion API.

The completion signal is Promise fulfillment

html2canvas reconstructs the target element from the DOM and resolves a Promise with a canvas. That fulfillment is the supported signal that this particular rendering call has produced an output you can consume.

async function captureElement(element) {
  try {
    const canvas = await html2canvas(element);
    // This runs only after this html2canvas call has fulfilled.
    return canvas;
  } catch (error) {
    // The rendering call rejected.
    console.error('html2canvas failed:', error);
    throw error;
  }
}

The Promise settles only for the invocation you made. It does not certify that every network request in your application has ended, that an animation has reached its final frame, or that the pixels exactly match a browser screenshot. html2canvas builds its own representation and supports only the CSS and browser features it understands.

What each signal means

Signal Meaning Use it for completion?
Promise fulfillment A canvas was produced for this call. Yes. Continue with export or display.
Promise rejection This call could not complete successfully. Yes. Enter your failure path.
onError option A resource failed while rendering; rendering can continue. No. It is a resource notification, not a finished-render callback.
onrendered Legacy callback from older examples. No. Use the Promise API.

Use async/await in modern code

An async function makes the ordering explicit. Everything after await html2canvas(...) runs after fulfillment, while catch handles a rejected Promise.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
import html2canvas from 'html2canvas';

async function downloadCard() {
  const element = document.querySelector('#invoice-card');
  if (!element) {
    throw new Error('Invoice card was not found');
  }

  try {
    const canvas = await html2canvas(element, {
      backgroundColor: '#ffffff',
      imageTimeout: 15000
    });

    const link = document.createElement('a');
    link.download = 'invoice-card.png';
    link.href = canvas.toDataURL('image/png');
    link.click();
  } catch (error) {
    console.error('Could not create the image:', error);
    // Show an error message or retry according to your application rules.
  }
}

document.querySelector('#download').addEventListener('click', downloadCard);

imageTimeout is 15,000 milliseconds by default. Setting it explicitly documents the behavior your capture expects; it does not make an inaccessible cross-origin image readable.

Use .then() when callbacks fit your code

The callback form waits on the same Promise and is equivalent to await. Always attach .catch() so a rejected render does not become an unhandled rejection.

const element = document.querySelector('#report');

html2canvas(element, { scale: 2 })
  .then((canvas) => {
    document.querySelector('#preview').replaceChildren(canvas);
    return canvas.toBlob((blob) => {
      if (blob) {
        console.log('PNG blob is ready', blob.size, 'bytes');
      }
    }, 'image/png');
  })
  .catch((error) => {
    console.error('Render rejected:', error);
  });

Do not put follow-up work immediately after the html2canvas call and assume it has finished:

const promise = html2canvas(element);
// This line runs before the Promise has fulfilled.
console.log('Capture started');

Keep export, upload, or UI updates inside the fulfillment path.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors

Prepare application state before calling html2canvas

Promise fulfillment covers html2canvas’s work, not arbitrary application readiness. If your page loads data, swaps images, applies fonts, or changes classes asynchronously, make those conditions explicit before starting the capture.

Wait for your own data and UI state

async function renderReadyReport() {
  await reportStore.load();
  await customElements.whenDefined('sales-report');

  const report = document.querySelector('sales-report');
  report.classList.add('capture-mode');

  // Let layout and style changes reach a frame.
  await new Promise(requestAnimationFrame);

  return html2canvas(report);
}

The exact readiness condition belongs to your application. For example, wait for the API request that supplies table rows, then wait for the component that displays them, then capture.

Check images and fonts when they matter

For images already in the document, you can wait for each element’s load or error state. A failed image should be handled deliberately rather than mistaken for a successful visual result.

function waitForImage(image) {
  if (image.complete) {
    return image.naturalWidth > 0
      ? Promise.resolve()
      : Promise.reject(new Error(`Image failed: ${image.src}`));
  }

  return new Promise((resolve, reject) => {
    image.addEventListener('load', resolve, { once: true });
    image.addEventListener('error', () => reject(new Error(`Image failed: ${image.src}`)), { once: true });
  });
}

async function captureWithAssets(element) {
  await Promise.all([...element.querySelectorAll('img')].map(waitForImage));
  if (document.fonts) {
    await document.fonts.ready;
  }
  return html2canvas(element);
}

This preparation prevents a race in your application; it does not remove browser security restrictions. Images served from another origin may require suitable CORS headers, and the project documents cross-origin limitations.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.

Use onclone for capture-only changes

The options reference provides an onclone hook that receives the cloned document. It is useful for hiding controls, adding a print class, or freezing a visual state without changing the live page. The hook is a preparation hook, not a completion notification.

const canvas = await html2canvas(document.querySelector('#dashboard'), {
  onclone: (clonedDocument) => {
    clonedDocument.body.classList.add('capture-mode');
    clonedDocument.querySelectorAll('.live-only').forEach((node) => {
      node.style.display = 'none';
    });
  }
});

A reliable end-to-end capture function

This pattern validates the target, waits for application assets, invokes html2canvas once, and returns only after a canvas exists.

async function capture(selector) {
  const element = document.querySelector(selector);
  if (!element) {
    throw new Error(`No element matches ${selector}`);
  }

  await Promise.all([...element.querySelectorAll('img')].map(waitForImage));
  if (document.fonts) {
    await document.fonts.ready;
  }
  await new Promise(requestAnimationFrame);

  try {
    const canvas = await html2canvas(element, {
      imageTimeout: 15000,
      onclone: (doc) => doc.body.classList.add('capture-mode')
    });
    return canvas;
  } catch (error) {
    console.error(`html2canvas rejected for ${selector}:`, error);
    throw error;
  }
}

Callers can now decide whether to display the canvas, call toBlob(), or send the resulting bytes to a server. Those operations belong after the returned Promise resolves.

Troubleshoot a render that appears not to finish

The Promise never appears to settle

  • Confirm that the code actually calls html2canvas and that the target is a real element, not null.
  • Inspect the browser console for an exception thrown before the call or inside your own readiness code.
  • Check large or unreachable resources. The default imageTimeout is 15 seconds; reduce the number of assets or set a timeout appropriate to your page.
  • Do not wait on a Promise that your application creates but never resolves. Log immediately before the html2canvas call and in both fulfillment and rejection handlers.

The Promise fulfills but the canvas is incomplete

Fulfillment proves that html2canvas produced a canvas, not that every visual dependency was available. Verify image load state, font readiness, data rendering, and the target’s computed styles before invoking the library. Cross-origin images can be omitted or taint the canvas when server permissions are not configured.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient

You used onError as a finished callback

onError reports a resource failure while rendering continues. It can be useful for diagnostics, but the only place to run “done” logic is the Promise fulfillment branch. Keep a separate error counter if you want to warn about missing assets.

let failedResources = 0;

const canvas = await html2canvas(element, {
  onError: (error) => {
    failedResources += 1;
    console.warn('Resource warning:', error);
  }
});

console.log('Canvas produced; resource warnings:', failedResources);

An old example uses onrendered

Older snippets may show an onrendered option. That callback was removed in favor of the Promise-returning API. Replace it with await html2canvas(...) or .then(...); adding the old option will not provide a current completion signal.

The output changes between runs

Freeze application state before capture. Pause carousels or animations, use a capture-only class, wait for a stable layout frame, and avoid starting multiple captures against the same changing element. If the page must be pixel-identical, control fonts, image dimensions, viewport size, and device scale in your own code.

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

Performance and reliability choices

  • Capture only what you need. A smaller subtree uses less memory and finishes sooner than the entire document.
  • Avoid duplicate renders. Debounce buttons and state-change handlers so one user action does not start several expensive Promise operations.
  • Choose scale deliberately. Higher canvas scale improves detail but increases memory and encoding time.
  • Keep ownership of readiness. html2canvas has no universal callback that means every application resource, font, animation, or asynchronous state is ready. Define those preconditions yourself.
  • Handle rejection. Report a useful message, preserve the original error for logging, and offer a retry only when the underlying condition can change.

Finally, remember the product boundary: html2canvas is a DOM reconstruction library, not a browser-pixel recorder. Unsupported CSS, cross-origin content, and browser rendering differences can remain even when its Promise fulfills.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

Or skip the browser setup

If your goal is a server-side website screenshot rather than a canvas generated inside your page, ScreenshotNeo provides a GET-based screenshot API and an MCP server for AI clients such as Claude and Cursor. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers.

One request with cURL

See the ScreenshotNeo documentation for parameter details.

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

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

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 failed: ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', buffer);

Options for production captures

ScreenshotNeo supports full-page captures with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets or custom viewports, retina scale, PDF paper size/margins/orientation/page ranges, HTML/CSS input, custom JavaScript and CSS, pre-capture clicks, hidden selectors, waits for a selector, delay, or network idle, blocking ads, trackers, requests, or resource types, custom headers/cookies/user agents/Authorization, timezone and geolocation, transparent backgrounds, image resizing, caller-selected cache TTLs, signed links for public image tags, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, an OpenAPI specification, and familiar parameter names for easier migration.

Every feature is included on every plan. The Free plan provides 1,000 shots per month with no card; Starter is $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free.

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

Sign up for ScreenshotNeo free to get 1,000 screenshots a month without a card; paid plans start at $5 for 3,000 shots.

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.