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

Most html2canvas image failures are browser security behavior, not a rendering bug. An image from a different scheme, host, or port can taint the canvas. With the default allowTaint: false, html2canvas skips resources that would make the canvas unreadable. Fix the problem by enabling CORS on the image server and using useCORS: true, or route the image through a secure same-origin proxy when you do not control that server.

What “cross-origin” means in this error

Two URLs are cross-origin when any of their scheme, host, or port differs. A page at https://app.example.com and an image at https://cdn.example.com have different origins even though they share a parent domain. HTTP and HTTPS are different origins, as are ports 443 and 8443.

Browsers protect pixel data in a canvas. Once a canvas contains an image that was fetched without permission from that image’s origin, the canvas is tainted. Reading pixels, calling toDataURL(), calling toBlob(), and similar export operations then fail with a security exception. html2canvas cannot bypass this policy. Its documented default is allowTaint: false, so it checks resources first and omits images that would taint the result.

First, identify the failing resource

  1. Open DevTools and capture the page again.
  2. In the Network panel, filter by Img and inspect redirects, status codes, and the response headers for every missing image. Background images and SVG references can fail too.
  3. Compare the page origin with each image URL, including scheme, host, and port.
  4. Look for a response header such as Access-Control-Allow-Origin. A header on your HTML page does not grant permission; the image response must provide it.
  5. Make sure the image has finished loading before capture. A request that is still pending can look like a CORS failure.

To surface resource-level failures, provide the onError callback:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const element = document.querySelector('#capture');
await html2canvas(element, {
  useCORS: true,
  onError: error => console.warn('html2canvas resource failed:', error.message)
});

Fix 1: configure CORS on the image server

Use this route when you own the image host or can change its CDN policy.

1. Send a compatible response header

For a public, non-credentialed asset, the image response can include:

Access-Control-Allow-Origin: https://app.example.com

Use the requesting origin explicitly when possible. A wildcard (*) can be suitable for genuinely public assets, but it cannot be combined with credentialed requests. If your application sends cookies or HTTP authentication, return the exact origin and configure the request for credentials according to your server’s policy.

2. Ask html2canvas to make a CORS request

const canvas = await html2canvas(document.querySelector('#capture'), {
  useCORS: true
});
const png = canvas.toDataURL('image/png');

useCORS defaults to false. Turning it on only changes how the browser requests the image; it cannot manufacture a permission header on a remote server.

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

3. Set the image request mode before it loads

If your code creates the image element, set crossorigin before assigning src:

const image = new Image();
image.crossOrigin = 'anonymous';
image.src = 'https://images.example.com/photo.jpg';
image.onload = () => document.querySelector('#gallery').append(image);

In markup, the equivalent is:

<img crossorigin="anonymous" src="https://images.example.com/photo.jpg" alt="">

The request mode and response header must agree. Adding the attribute after the request has started is too late. If an image was previously loaded without CORS, reload it with the attribute before calling html2canvas.

Fix 2: use a same-origin proxy

If you cannot change the remote server, fetch the image on your server and expose a controlled endpoint on the same origin as the page:

const canvas = await html2canvas(document.querySelector('#capture'), {
  proxy: '/image-proxy'
});

The proxy pattern described by html2canvas accepts a ?url= destination and returns the resource (often as a base64 data URI) so the browser sees a same-origin response. A minimal request would look like /image-proxy?url=https%3A%2F%2Fimages.example.com%2Fphoto.jpg.

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.

Proxy safeguards you should implement

  • Allow-list approved hostnames or destinations; never act as an unrestricted URL fetcher.
  • Block private IP ranges, localhost, cloud metadata addresses, and non-HTTP schemes to reduce server-side request-forgery risk.
  • Enforce maximum response bytes, dimensions, redirect count, and download time.
  • Check the upstream content type and reject HTML, scripts, and unexpected formats.
  • Set caching and rate limits deliberately, and avoid logging sensitive query strings.
  • Return a correct image content type and, if you return a data URI, encode the bytes exactly.

The proxy adds server bandwidth, latency, and an additional privacy boundary. It is nevertheless the practical fallback when the asset host is uncooperative.

Why common “fixes” fail

allowTaint: true

This option permits html2canvas to draw an image that taints the canvas. It does not make the canvas readable. Export calls can still throw a security error, so it is useful only when you never need pixel extraction or an image/PDF export.

Using useCORS: true by itself

Without a compatible Access-Control-Allow-Origin response, the browser still rejects the read. Use the server-header solution or a same-origin proxy.

Adding headers in client JavaScript

JavaScript cannot add an Access-Control-Allow-Origin response header after the request. Configure the image server, CDN, or proxy instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
HTML5 HTML Logo Web Programmer Nerd Funny - Computer Coding T-Shirt
  • Are you familiar with html5? Then get this "HTML5 HTML Logo Web Programmer Nerd Funny" featuring HTML logo. Perfect for computer programmer, developer, software developer and technician who does computer programming language, coding and gaming on internet.
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem

Confusing an iframe with an image

A cross-origin iframe is a separate restriction. Its contentDocument is inaccessible, so html2canvas cannot inspect and render the frame’s contents merely because image CORS is enabled. Render the framed application from its own origin or use a capture service that loads the URL independently.

Choosing between CORS and a proxy

Consideration CORS on image host Same-origin proxy
Server control You can change the CDN or origin policy You cannot change the remote host
Browser path Direct request with crossorigin and useCORS Browser requests your own endpoint
Latency and cost Usually one request; CDN caching remains direct Extra hop, bandwidth, caching, and processing
Credentials Requires an exact origin and carefully matched credential policy Credentials can remain server-side, but must be protected
Security exposure Controlled by the asset server’s CORS policy Requires SSRF, size, type, and rate-limit defenses
Best fit Public assets or an image service you operate Third-party assets with no CORS support

Reliable capture sequence

  1. Render the target element and ensure every image has a final URL.
  2. Wait for images to complete:
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 });
  });
}));
  1. Capture with either useCORS: true and server permission, or proxy pointing to your validated endpoint.
  2. Check the returned canvas dimensions and export it only after the promise resolves.
  3. Keep onError logging in development so a failed background image is not mistaken for a layout problem.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting by symptom

Images are missing, but no export exception appears

With allowTaint: false, html2canvas may skip an image before it is drawn. Inspect the image response and add useCORS only after confirming the server sends permission. If the host cannot be changed, switch to a proxy.

“Tainted canvases may not be exported” appears

An image was drawn without readable CORS permission, possibly by another library before html2canvas ran. Reload that image with crossorigin="anonymous", make the response header compatible, or remove the image and use a proxy. Do not expect allowTaint to repair an already tainted canvas.

The header is present, but the browser still blocks the image

  • Check the final response after redirects, not only the first URL.
  • Verify the header value exactly matches the page origin when credentials are involved.
  • Confirm a CDN or cache is not serving a response generated for another origin; vary cached responses by Origin when needed.
  • Ensure crossorigin was set before src and before the first load.

The proxy returns an error or a blank result

Request the proxy URL directly, inspect its status and content type, and verify it can reach the upstream URL. Check destination allow-lists, redirect handling, response-size limits, and server timeouts. A proxy that returns an HTML error page is not a usable image response.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
The SQL Programming Language: .
  • Used Book in Good Condition

Only an embedded app is missing

That is likely a cross-origin iframe, not an image CORS issue. html2canvas cannot read the frame’s document. Capture the embedded page separately from an environment that has access, or change the integration so the content is same-origin.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server when you need a rendered URL rather than a canvas inside your page. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the page verdict and billing status. Its MCP tools—take_screenshot, get_page_info, and capture_pdf—let Claude, Cursor, and other MCP clients capture pages.

One GET request returns PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation for options such as full-page and element capture, device presets, custom CSS/JavaScript, waiting rules, request blocking, cookies and headers, PDF settings, caching, signed links, asynchronous webhooks, bulk capture, and usage reporting.

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}`);

The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

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

Frequently Asked Questions

Can I use a wildcard CORS header for every image?

Only for assets and request patterns where public wildcard access is appropriate. Credentialed requests require a specific allowed origin instead of *.

Does html2canvas support cross-origin SVG images?

SVG resources follow the same browser-origin rules as other images; inspect their requests and provide CORS permission or route them through a controlled proxy.

Will clearing the browser cache fix a tainted canvas?

No. Cache changes can alter which response you see, but they do not grant cross-origin permission. Correct the request mode and response policy.

Quick Recap

Bestseller No. 3
Bestseller No. 4
HTML5 HTML Logo Web Programmer Nerd Funny - Computer Coding T-Shirt
HTML5 HTML Logo Web Programmer Nerd Funny - Computer Coding T-Shirt
Lightweight, Classic fit, Double-needle sleeve and bottom hem
$19.99
Bestseller No. 5
The SQL Programming Language: .
The SQL Programming Language: .
Used Book in Good Condition
$4.23

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.

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