The fix is to make every image or other drawable resource in the capture readable under the browser’s same-origin and CORS rules. Set useCORS: true in html2canvas and configure the image host to send an Access-Control-Allow-Origin header for your page’s origin. If you cannot change that host, serve the resource through a suitable same-origin proxy or leave it out of the capture. The browser enforces this restriction; html2canvas cannot bypass it.
Why html2canvas throws this SecurityError
html2canvas reconstructs page content in a canvas; it does not take a privileged screenshot of the browser window. When a browser draws an image from another origin without successful CORS authorization, the canvas becomes tainted, or not origin-clean. The browser then blocks pixel-reading and export methods such as toDataURL(), toBlob(), and getImageData(), often with a SecurityError such as “The operation is insecure.” The html2canvas FAQ explains that drawing images outside the current page’s origin taints the canvas, and its guide says the library cannot circumvent browser content-policy restrictions.
A single unapproved image can taint the entire result. The image may be in a CSS background or SVG rather than an obvious <img>. An already-tainted canvas included in the page can cause the same problem. This is why a capture may render on screen but fail only when your code tries to export it.
Find the resource that taints the canvas
Start with the exact page and browser where the error occurs. Open developer tools, inspect the console and Network panel, and look at requests made during the capture. Check each image’s final response after redirects, not just the URL in your HTML. A same-origin-looking address may redirect to a CDN on another origin.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated 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
- Check every visible and hidden
<img>, including images loaded by components after the initial page render. - Inspect CSS
background-imageURLs, including stylesheets and pseudo-elements. - Inspect SVG files and SVG references to external images, fonts, or other resources.
- Check video frames, canvases already present in the page, and resources drawn by third-party widgets.
- For each cross-origin image request, verify the final response includes an
Access-Control-Allow-Originvalue that permits your page’s origin.
Do not treat a CORS error on an unrelated request as proof of the cause. Identify resources actually drawn into the capture, then test by temporarily removing or replacing a suspect resource. If the export succeeds, you have isolated a likely source.
Fix it in the order that best fits your setup
1. Use a same-origin image when possible
If you control the page and assets, serve the image from the same scheme, host, and port as the page. This avoids the cross-origin image permission problem. The html2canvas limitations guide describes same-origin assets as the straightforward case; a proxy is another option when assets must come from elsewhere.
2. Enable CORS loading in html2canvas
Set useCORS: true in the options passed to html2canvas, before starting the capture:
Rank #2
const element = document.querySelector('#receipt');
if (!element) throw new Error('Capture element #receipt was not found');
try {
const canvas = await html2canvas(element, { useCORS: true });
const pngDataUrl = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.href = pngDataUrl;
link.download = 'receipt.png';
link.click();
} catch (error) {
console.error('Could not capture or export the element:', error);
}
This example assumes html2canvas is already loaded and that the code runs in an async function or module. The capture promise must resolve before export. useCORS tells html2canvas to attempt CORS-enabled loading; it does not grant access by itself. The remote image server must return a permitting Access-Control-Allow-Origin header. The official options reference and FAQ make that limitation clear.
3. Configure the image host’s response
If you manage the image server, configure it to permit the actual origin of the page that runs html2canvas. Depending on your security policy, that may be a specific origin or an appropriate wildcard. Inspect the response in the browser’s Network panel and confirm that the header is present on the final response, including after redirects. A missing or unsuitable header cannot be repaired by a JavaScript option on your page.
4. Resolve redirects to a CDN
A URL that begins on your site may return a 301 or 302 and finish at a different host. The final host’s response must satisfy the browser’s CORS rules. The html2canvas project’s issue #3020 describes a redirect case where useCORS was not applied as expected; issue #2892 discusses a similar CDN taint pattern. Where practical, use the final CDN URL directly and configure its CORS response, or route the image through a proxy you control. Verify the behavior in your own browser and deployment because redirects and response headers determine the result.
5. Proxy resources you cannot configure
A same-origin proxy fetches a remote image on the server side and serves it back from the page’s origin. The official html2canvas guide documents the proxy option. Use a proxy only for hosts and content you are authorized to fetch, and restrict it to avoid turning it into an open proxy. Account for the extra server work, network hop, and latency; a proxy is a fallback, not a way to access resources that your application is not entitled to retrieve.
6. Exclude resources that cannot be made readable
If a third-party image, advertisement, or widget cannot be served with suitable CORS permission and is not essential to the output, omit it from the capture. Add data-html2canvas-ignore to the relevant element, as documented in the options reference, or remove it in a cloned capture document. This keeps the rest of the capture usable without pretending the excluded content was included.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsWhy common option changes do not solve it
allowTaint: true does not make export safe
allowTaint defaults to false. Setting it to true may allow tainting content to be drawn, but it does not make the resulting canvas origin-clean or permit pixel export. Project issue #3184 illustrates that combining allowTaint: true and useCORS: true can still fail at toDataURL(). If export is the goal, fix or exclude the resource instead of relying on this setting.
Rank #4
CORS settings do not grant iframe access
html2canvas cannot read a cross-origin iframe’s contentDocument. CORS image headers do not change that browser rule. If you control the framed application, arrange for the content to be rendered in a context your page can access; otherwise, capture the frame through its own permitted route or omit it. This is distinct from an image that can be fetched with CORS.
Special cases: local files, existing canvases, and blank output
Testing from file://
Opening an HTML file directly from disk can give it an origin that behaves differently from your deployed site and can expose restrictions with remote images. For a more representative test, serve the page over a local HTTP server and retry. This helps diagnose origin behavior; it does not make a remote server authorize your request.
Existing canvas or SVG content
A canvas that was previously tainted remains unreadable when another capture tries to use it. Inline the needed SVG where appropriate, use same-origin or CORS-approved source assets, or exclude the already-tainted element. Re-capturing the surrounding DOM does not cleanse its contents.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Best Value
Blank or cut-off results without a SecurityError
A blank or partial image is not necessarily a CORS failure. The html2canvas FAQ notes that browser canvas-size limits can produce blank or cut-off output without throwing an exception. Treat that symptom separately: check the capture dimensions and browser behavior, while reserving the origin/CORS investigation for blocked export or tainted-canvas errors.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Quick diagnostic checklist
- Wait for the html2canvas promise to resolve before calling
toDataURL()or another export method. - Inspect image, background, SVG, video, and existing-canvas content that is actually drawn.
- For cross-origin images, inspect the final Network response after redirects and check
Access-Control-Allow-Origin. - Set
useCORS: truebefore capture begins, then test again. - If you cannot configure the source, use a controlled same-origin proxy or exclude that resource.
- If the content is inside a cross-origin iframe, do not expect image CORS options to grant DOM access.
Or skip the browser setup
If your goal is a screenshot of a page URL rather than exporting a particular in-memory DOM state, ScreenshotNeo can return an image or PDF from one GET request. Its clean-shot steps accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step 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. It also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
For a quick test, replace the example URL with the page you want to capture and use your API key. See the ScreenshotNeo API documentation for parameters and response details.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. This captures a URL, so it is not a substitute when you need a particular browser session, unsaved UI state, or DOM selection that is not represented by that URL. Sign up for 1,000 free screenshots a month, with no card.
Recommended Free Tools
FAQ
Does this error mean the page is unsafe?
No. It indicates that the browser is preventing access to canvas pixels under its origin rules; it does not, by itself, establish that the page or image is malicious.
Can I use toBlob() instead of toDataURL()?
Changing the export method does not clear a tainted canvas. The browser’s origin-clean restriction applies to pixel-reading and export APIs, so the resource permission must be fixed first.
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.

