Free tools Windows power users keep installed
One-click scans. No signup required.
The standard browser workflow is HTML element → canvas → PNG: select the element, render it with html2canvas, then export the canvas with the browser’s PNG-capable APIs. This is convenient for cards, invoices, charts and previews, but it reconstructs the DOM rather than photographing browser pixels. If you need the exact rendered page, use Playwright or Puppeteer—or an API such as ScreenshotNeo.
Convert an HTML element to PNG in the browser
Install html2canvas with your package manager:
npm install html2canvas
Give the element an identifier and call html2canvas(element). The promise resolves to a canvas, which can be downloaded as a PNG:
import html2canvas from 'html2canvas';
async function downloadPng() {
const element = document.querySelector('#capture');
if (!element) throw new Error('Capture element not found');
const canvas = await html2canvas(element, {
backgroundColor: null,
scale: window.devicePixelRatio,
useCORS: true
});
const blob = await new Promise(resolve =>
canvas.toBlob(resolve, 'image/png')
);
if (!blob) throw new Error('PNG export failed');
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'capture.png';
link.click();
URL.revokeObjectURL(url);
}
document.querySelector('#download').addEventListener('click', downloadPng);
Example markup:
<article id="capture">
<h1>Monthly report</h1>
<p>Revenue: $12,480</p>
</article>
<button id="download" type="button">Download PNG</button>
backgroundColor: null requests transparency when the captured element has no background. scale controls output density and defaults to the device pixel ratio when omitted. useCORS attempts to load images with CORS, but it cannot override the remote server’s policy.
Wait for fonts, images and dynamic content
Capture only after the element is populated. For images, wait for their load events; for fonts, await document.fonts.ready. Frameworks should capture after the relevant render state exists. Otherwise the canvas may contain fallback fonts or blank image areas.
#1 Best Overall
await document.fonts.ready;
await Promise.all([...document.images].map(img => {
if (img.complete) return Promise.resolve();
return new Promise(resolve => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', resolve, { once: true });
});
}));
await downloadPng();
PNG export choices: toBlob() versus toDataURL()
canvas.toBlob() creates a binary Blob and is the better default for downloads and large images because it avoids placing the entire encoded image in a JavaScript string. The object URL should be revoked after the browser has consumed it; if a target browser cancels downloads when cleanup is immediate, defer URL.revokeObjectURL(url) briefly.
canvas.toDataURL('image/png') returns a base64 data URL, useful when an inline URL is specifically required:
const dataUrl = canvas.toDataURL('image/png');
window.open(dataUrl, '_blank');
PNG is the required canvas export format and is used when no type is supplied or an unsupported type is requested. Both methods can throw a SecurityError when the canvas is not origin-clean.
Cross-origin images and the canvas security boundary
An image hosted on another origin can be skipped or taint the canvas. useCORS: true succeeds only when that server returns compatible CORS headers. You cannot make an origin-tainted canvas readable by setting allowTaint; a tainted canvas cannot be exported.
Rank #2
Practical fixes
- Host the asset on the same origin as the page.
- Configure the asset server to return an appropriate
Access-Control-Allow-Originvalue, then load the image with CORS enabled. - Proxy the asset through a server you control, preserving content type and applying your own access policy.
- Replace remote images with data URLs or inline SVG when that is appropriate and safe.
Do not use an unrestricted public proxy for private images or credentials. CORS is a browser security rule, not an html2canvas setting that can be bypassed.
What html2canvas can—and cannot—reproduce
html2canvas traverses the DOM and computed styles to construct a canvas. Its documentation states: “The screenshot is based on the DOM and as such may not be 100% accurate to the real representation of the page.” Unsupported or partially supported CSS, pseudo-elements, transforms, filters, complex SVG, web fonts and timing-sensitive effects can differ from what the browser displays.
- Compare output in every target evergreen browser.
- Test the actual fonts, SVGs, animations and responsive breakpoints used by your component.
- Disable animations or capture at a stable state.
- Use a simple, explicit background when transparency is not required.
Full-page, scrolling and oversized elements
A captured element is limited by the renderer’s viewport and canvas dimensions. If content is cropped, provide dimensions based on the element’s scroll area:
const element = document.querySelector('#capture');
const canvas = await html2canvas(element, {
windowWidth: Math.max(document.documentElement.clientWidth, element.scrollWidth),
windowHeight: Math.max(document.documentElement.clientHeight, element.scrollHeight),
scale: 1
});
Very large canvases may be blank or partial. Maximum dimensions vary by browser, GPU, operating system and device, so do not rely on one universal limit. Reduce scale, split a long document into sections, or capture at a smaller output size. Higher scale increases pixels, memory use and encoding time.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →When to use a real browser screenshot instead
html2canvas runs in a browser because it depends on window, document and computed styles; it is not a Node.js conversion library. For server-side jobs or pixel-level browser output, use Playwright or Puppeteer to load the page and call the native screenshot API. That route executes the page in a real browser, so browser layout, fonts and CSS are the things being captured.
| Requirement | Best fit | Reason |
|---|---|---|
| Download one rendered component in a web app | html2canvas | No server browser required; direct DOM-to-canvas flow. |
| Exact browser pixels, full page or extension tab | Playwright/Puppeteer or native extension API | Captures the actual browser rendering. |
| Already have a canvas | toBlob() |
Skips DOM reconstruction entirely. |
| Automated URL screenshots without browser setup | ScreenshotNeo | Hosted capture, clean-page processing and usage reporting. |
There is no universal accuracy or speed winner among libraries. Capture a representative page in your target browsers and measure memory, latency and output quality.
Export an existing canvas directly
If your chart or drawing is already in a <canvas>, do not render its parent element:
const source = document.querySelector('#chart');
const blob = await new Promise(resolve => source.toBlob(resolve, 'image/png'));
if (!blob) throw new Error('Could not encode canvas');
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'chart.png';
a.click();
setTimeout(() => URL.revokeObjectURL(url), 0);
Or skip the browser setup
For a URL screenshot, ScreenshotNeo provides a hosted GET endpoint. It accepts the cookie or consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and response headers identify the page verdict and whether it was billed. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients. Every plan includes the features; 1,000 shots per month are free without a card, Starter is $5 for 3,000, and paid plans start at $5.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →cURL:
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)
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}`);
See the ScreenshotNeo API documentation for PNG, JPEG, WebP, PDF, selectors, device presets, custom CSS and JavaScript, waits, blocking rules, headers, cookies, geolocation, signed links, asynchronous jobs, bulk capture and usage endpoints. Create a free ScreenshotNeo account to get 1,000 screenshots each month with no card.
Rank #4
Troubleshooting checklist
“Capture element not found”
The selector ran before the component mounted or does not match the markup. Run the function after rendering, verify the ID, and check for shadow-DOM boundaries.
Blank or incomplete output
Wait for images and fonts, remove animation, inspect browser console errors, reduce the capture dimensions and lower scale. Oversized canvases can exceed platform limits.
Images missing
Check the image response’s CORS headers. Same-origin hosting or a controlled proxy is required when the canvas must be exported.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteText or CSS differs
Confirm the font actually loaded, test unsupported CSS and pseudo-elements, and remember that DOM reconstruction is not a native screenshot.
Best Value
“SecurityError” on export
The canvas is origin-tainted, usually by a cross-origin image or SVG. Fix the asset’s CORS policy or remove the asset; do not attempt to bypass the browser security model.
Download does not start
Use toBlob() and an object URL, trigger the link from a user gesture, and delay URL revocation if necessary.
Performance and reliability practices
- Capture only the required element instead of the whole document.
- Use the lowest scale that meets your pixel requirements.
- Reuse a stable component state and avoid capturing during layout changes.
- Release object URLs and avoid retaining large data URLs.
- For server jobs, set navigation and resource timeouts, retry transient failures, and record the browser and page URL with each result.
- Validate output dimensions and file size before storing or publishing the PNG.
Frequently Asked Questions
Can html2canvas convert an entire webpage to PNG?
It can attempt a large element or document, but scrolling content and platform canvas limits may require dimension settings or section-by-section capture.
Does html2canvas work in Node.js?
No. It depends on browser globals and computed styles; use Playwright, Puppeteer or a hosted screenshot API for Node.js jobs.
Why is my PNG transparent?
The example requests transparency with backgroundColor: null. Set a CSS background or a concrete html2canvas background color when you need an opaque image.
Is PNG better than JPEG for HTML captures?
PNG preserves text, line art and transparency. Choose another format only when your delivery requirements favor smaller lossy files.
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.

