Recommended Free Tools
To make html2canvas output repeatable, make every rendering input deterministic: fix the scale and viewport, wait for fonts and images, freeze dynamic content in onclone, exclude intentionally changing elements, and control cross-origin assets. Capture only after the returned promise resolves. These steps reduce layout and pixel drift, but html2canvas reconstructs an image from the DOM rather than taking a native compositor screenshot, so it cannot promise identical pixels for every browser feature.
What “consistent” means for html2canvas
A repeatable capture has the same canvas dimensions, element geometry, text metrics, image content, colors and state each time it runs. That is the standard needed for visual-regression tests, generated reports and cacheable exports.
html2canvas reads the DOM and computed styles, then paints its own representation. It does not ask the browser for the already-composited screen. Consequently, differences in fonts, media-query breakpoints, device-pixel ratio, animation time, timers, random values, scroll position and resource availability can change the result. The project documentation cautions that a screenshot is “based on the DOM” and may not be “100% accurate to the real representation.”
The workflow below makes the inputs explicit. It cannot make an inaccessible cross-origin iframe available, and it cannot guarantee native-browser pixel identity for features html2canvas does not reconstruct.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware match#1 Best Overall
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
Build a deterministic capture
1. Freeze the capture geometry
Capture the same element and specify the dimensions and coordinates used by your test. Set windowWidth and windowHeight so responsive breakpoints do not change. Set width, height, x and y when the target must have a fixed rectangle. Keep scrollX and scrollY constant; otherwise fixed-position headers and sticky controls can move.
Do not rely on the test runner’s host viewport or on whatever scroll position a previous test left behind. A CSS-pixel viewport of 1280 by 720 and zero scroll is a practical baseline, but choose values that represent your application and keep them unchanged between runs.
2. Choose a fixed scale
The documented default for scale is window.devicePixelRatio. That value differs between a laptop display, a headless browser and a high-density monitor, so the same CSS layout can produce canvases with different pixel dimensions. Set scale: 1 for one output pixel per CSS pixel, or choose another fixed value shared by every test worker.
3. Wait for fonts before measuring or painting
Use the browser’s font readiness promise before invoking html2canvas:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
await document.fonts.ready;
Also ensure the intended web-font files have successfully loaded. A fallback font changes glyph widths, line wrapping and element heights; capturing a few milliseconds earlier can therefore change the entire downstream layout.
4. Wait for every image to load and decode
An image can report that its request completed while decoding is still pending. Resolve both cases before capture, and make the timeout an explicit policy. The following helper waits for already-complete images to decode and waits for load or error on the rest. An error is resolved rather than hanging the test, so diagnostics can report the missing asset.
Rank #2
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
async function waitForImages(images = [...document.images]) {
await Promise.all(images.map(img => {
if (img.complete) {
return img.decode?.().catch(() => {});
}
return new Promise(resolve => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', resolve, { once: true });
});
}));
}
Call it after the page has inserted all expected images. html2canvas’s imageTimeout is documented as 15,000 milliseconds by default; set it deliberately when your application has a different loading budget.
5. Freeze changing state in onclone
html2canvas clones the document before rendering. Use onclone to modify that clone, leaving the production DOM untouched. Replace timestamps, random identifiers, live counters, rotating carousel content, caret or focus styling, animation classes and network-populated placeholders with stable values. For example, mark volatile nodes with data-volatile and replace their text in the clone.
6. Exclude content that is supposed to vary
Ads, clocks, cursor indicators, video overlays and live chat should not participate in a pixel comparison unless they are the subject of the test. Add data-html2canvas-ignore to such nodes, or provide an ignoreElements function. Excluding a deliberately variable element is more reliable than trying to predict its current frame.
7. Make external images CORS-safe
Set useCORS: true only when the image server sends a suitable Access-Control-Allow-Origin response. Otherwise the browser may skip the image or leave the canvas tainted, preventing a later toDataURL or toBlob. If you cannot change the remote server, fetch the asset through a same-origin proxy that applies the required headers and security checks. CORS does not grant access to a cross-origin iframe’s document; browser same-origin rules still prevent html2canvas from rendering that iframe’s contents.
8. Set the background and export format explicitly
The documented default backgroundColor is #ffffff. Set it explicitly for opaque regression images. Use null only when transparency is intentional, and make that choice part of the test contract. Keep logging: true while diagnosing resource problems; disable verbose logging in normal production captures after the issue is understood. Call toBlob or toDataURL only after the html2canvas promise fulfills.
Rank #3
A complete deterministic JavaScript pattern
This example combines fixed geometry, readiness waits, cloned-state normalization, filtering and a PNG export. Adapt the selector and volatile-element rules to your page.
async function waitForImages(images = [...document.images]) {
await Promise.all(images.map(img => {
if (img.complete) return img.decode?.().catch(() => {});
return new Promise(resolve => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', resolve, { once: true });
});
}));
}
async function captureDeterministically() {
await document.fonts.ready;
await waitForImages();
const target = document.querySelector('#capture');
if (!target) throw new Error('Missing #capture element');
const canvas = await html2canvas(target, {
scale: 1,
windowWidth: 1280,
windowHeight: 720,
width: 1280,
height: 720,
x: 0,
y: 0,
scrollX: 0,
scrollY: 0,
backgroundColor: '#ffffff',
useCORS: true,
imageTimeout: 15000,
onclone: clonedDoc => {
clonedDoc.querySelectorAll('[data-volatile]').forEach(el => {
el.textContent = '[frozen]';
el.classList.remove('is-animating', 'has-focus-effect');
});
clonedDoc.querySelectorAll('video').forEach(video => video.pause());
},
ignoreElements: el => el.matches('.clock, .ad, .cursor, .live-chat')
});
const blob = await new Promise((resolve, reject) => {
canvas.toBlob(result => result ? resolve(result) : reject(new Error('PNG encoding failed')), 'image/png');
});
return blob;
}
captureDeterministically().then(blob => {
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'capture.png';
link.click();
URL.revokeObjectURL(link.href);
}).catch(console.error);
The fixed width and height in this sample assume that the target is intended to occupy that rectangle. If your target is smaller or full-page, derive those values once from a controlled layout and reuse them; do not let each run choose a different bounding box.
Diagnose a mismatch systematically
When two outputs disagree, compare the following in order. Record them with each test artifact so a failure is explainable rather than anecdotal.
| Axis | What to inspect | Typical correction |
|---|---|---|
| Canvas size | Pixel width and height, plus the configured scale | Fix scale, width and height; do not inherit device-pixel ratio |
| Viewport and scroll | windowWidth, windowHeight, scrollX, scrollY |
Use the same values for every worker and reset scroll before capture |
| Typography | Computed font family, loaded font files, font readiness | Await document.fonts.ready and fix failed font requests |
| Images | Request status, decode completion and CORS response headers | Await image readiness; enable CORS only with server support or use a same-origin proxy |
| DOM state | Timestamps, random values, animation progress, live data | Normalize the clone in onclone or ignore the node |
| Environment | Browser version, operating system, device-pixel ratio and rendering backend | Pin the browser/test image and keep workers homogeneous |
Common failure modes and fixes
The canvas changes size between runs
Cause: the default scale follows device-pixel ratio, or responsive CSS sees different viewport dimensions.
Fix: set a numeric scale, fixed window dimensions and explicit target dimensions. Verify the resulting canvas width and height before comparing pixels.
Text wraps differently or appears in a fallback font
Cause: capture started before web fonts were ready, or a font request failed.
Fix: await document.fonts.ready, inspect the computed font family and verify that the same font files are available in every environment.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsRank #4
Images are missing, blank or make export fail
Cause: an image was not loaded or decoded, or its origin is not permitted by CORS.
Fix: wait for load and decode, set a deliberate imageTimeout, inspect network responses, and configure the image server or a same-origin proxy. useCORS: true cannot bypass a server that omits the appropriate header.
A clock, carousel or cursor causes tiny pixel differences
Cause: the DOM contains time-dependent or animated state.
Fix: replace the value in onclone, pause animation/video in the clone, or exclude the element with ignoreElements or data-html2canvas-ignore.
An embedded frame never appears
Cause: the frame is cross-origin and its contentDocument is inaccessible under browser security rules.
Fix: render content you control from the same origin, capture the frame through a service that can access it legitimately, or use a native browser screenshot of the page rather than trying to reconstruct the frame in html2canvas.
Debugging reports an error but still produces an image
Keep logging enabled and attach an onerror handler to record failed resources while investigating. The renderer can continue after reporting a resource error, so treat the output as suspect until the missing asset is resolved or intentionally excluded.
Free tools Windows power users keep installed
One-click scans. No signup required.
When html2canvas is the wrong boundary
Use html2canvas when you need a client-side, DOM-driven image and can control the page state. If the requirement is an exact view of browser compositor output—including inaccessible frames, browser-native controls or features html2canvas does not reconstruct—use a native browser screenshot API instead. Keep the same determinism principles: pin the viewport and browser, wait for fonts and network resources, disable animation, and define how dynamic content is handled.
Best Value
- JavaScript Jquery
- Introduces core programming concepts in JavaScript and jQuery
- Uses clear descriptions, inspiring examples, and easy-to-follow diagrams
Or skip the browser setup
For a server-side screenshot, ScreenshotNeo accepts one GET request and returns PNG, JPEG, WebP or PDF. Its cleanup steps accept cookie and consent banners before capture and remove more than 60 known consent platforms, newsletter popups and chat widgets; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the page and billing result with X-Page-Verdict and X-Billed headers.
See the complete parameter reference in the ScreenshotNeo documentation. The same endpoint supports fixed viewports and device presets, full-page lazy-image loading, CSS-selector element capture, dark mode, retina scale, PDF paper settings, custom CSS and JavaScript, clicks, waits, hidden selectors, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparency, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting and an OpenAPI specification.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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 an MCP server with take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients. The Free plan includes 1,000 shots each month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Cost and reliability considerations
- For in-browser tests, the main cost is test runtime and the maintenance burden of controlling state; deterministic waits prevent flaky retries but should not be unbounded.
- Use a fixed browser and device-pixel ratio in CI. A different browser build or rendering environment can alter antialiasing even when DOM values match.
- Keep diagnostic logs and failed-resource details with visual-regression artifacts. This distinguishes a real UI change from a missing font or image.
- Do not compare compressed formats when exact pixels matter. Encode PNG consistently and compare images at identical dimensions.
- Cache only after inputs are stable. A cache can hide a resource change during debugging; record the cache policy and invalidate it when page state or assets change.
FAQ
Does setting scale: 1 guarantee identical screenshots?
No. It fixes the pixel-to-CSS-pixel ratio, but fonts, images, dynamic DOM state, browser rendering and cross-origin resources must also be controlled.
Should I use toDataURL or toBlob?
Either can export a completed canvas. toBlob is generally preferable for a file workflow because it avoids placing the entire encoded string in JavaScript memory; the determinism requirement is to call it only after html2canvas resolves.
Can html2canvas capture a cross-origin iframe if useCORS is enabled?
No. useCORS concerns image resources. Same-origin browser rules still prevent reading a cross-origin iframe document.
Frequently Asked Questions
How do I make a visual-regression test fail for missing assets instead of comparing a partial image?
Treat image and font readiness as test prerequisites: collect failed requests in your diagnostics hook, assert that required assets loaded, and only then compare the PNG. Use intentional exclusions for assets that are allowed to be absent.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →What should be stored with each baseline image?
Store the canvas dimensions, scale, viewport and scroll values, browser version, device-pixel ratio, font-load result and a list of ignored or normalized selectors. That metadata makes a mismatch reproducible.
Quick Recap
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.

