DEV Community

reynaldi
reynaldi

Posted on • Originally published at corsfix.com

4 1 1 1 1

Tainted Canvas: why the browser blocks your canvas (and how to unblock it)

Working with the <canvas> feels simple at first, load an image, draw it, export it. But the moment that image lives on a different origin you hit an error: calls such as canvas.toDataURL() or getImageData() shows error with “Tainted canvases may not be exported.” The browser is preventing you from reading the pixels of that canvas.

Tainted canvas error
Tainted canvas error

What’s with the tainted canvas?

When you draw an image fetched from another origin without proper CORS setup, the browser makes the entire canvas as “tainted.” Any attempt to read those pixels (getImageData, toBlob, toDataURL, etc.) is then blocked.

To solve this, you need to add crossOrigin="anonymous" to asks the browser to send the request in CORS mode, but the server must still reply with a matching Access-Control-Allow-Origin header.

<img src="https://example.com/image.png" crossorigin="anonymous" />
Enter fullscreen mode Exit fullscreen mode

Solving the tainted canvas error

You’ve got two options to solve the tainted canvas error:

  • Control the server?

    Add the header Access-Control-Allow-Origin: * (or your domain) and keep crossOrigin="anonymous" on your <img> tag or drawImage source.

  • Don’t control the server?

    • Backend relay: Fetch the image in your own backend, then serve it with the right CORS header so the browser sees it as same-origin.
    • CORS proxy: Use a CORS proxy that injects the header for you, ideal if you are running a static only site or don't have a backend.
  const image = new Image();
  image.crossOrigin = "anonymous";
  image.src = "https://proxy.corsfix.com/?https://example.com/image.png";
  image.onload = () => {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    ctx.drawImage(image, 0, 0);
    const dataUrl = canvas.toDataURL();
    console.log(dataUrl);
  };
Enter fullscreen mode Exit fullscreen mode

Conclusion

A tainted canvas is just the browser’s way of preventing you from accessing a canvas that contains cross-origin data. Tell the browser to expect CORS (crossOrigin="anonymous") and tell the server to allow it (Access-Control-Allow-Origin). If you can’t modify the server, relay the image through your backend or use a CORS proxy. Need something production-ready? Give Corsfix a spin, it’s free to start and only costs when you scale.

A Layered Approach to Mobile App Protection

A Layered Approach to Mobile App Protection

Attackers use static analysis to understand how your app functions and the data it contains. By using multiple layers of protections like code obfuscation and string encryption, you can prevent attackers from accessing your app.

Read more

Top comments (0)

Heroku

Save time with this productivity hack.

See how Heroku MCP Server connects tools like Cursor to Heroku, so you can build, deploy, and manage apps—right from your editor.

Learn More

👋 Kindness is contagious

Take a moment to explore this thoughtful article, beloved by the supportive DEV Community. Coders of every background are invited to share and elevate our collective know-how.

A heartfelt "thank you" can brighten someone's day—leave your appreciation below!

On DEV, sharing knowledge smooths our journey and tightens our community bonds. Enjoyed this? A quick thank you to the author is hugely appreciated.

Okay