How to fix getImageData() error The canvas has been tainted by cross-origin data?

JavascriptHtmlHtml5 Canvas

Javascript Problem Overview


My code is working very well on my localhost but it is not working on the site.

I got this error from the console, for this line .getImageData(x,y,1,1).data:

Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. 

part of my code:

jQuery.Event.prototype.rgb=function(){
		var x =  this.offsetX || (this.pageX - $(this.target).offset().left),y =  this.offsetY || (this.pageY - $(this.target).offset().top);
		if (this.target.nodeName!=="CANVAS")return null;
		return this.target.getContext('2d').getImageData(x,y,1,1).data;
	}

Note: my image url (src) is from a subdomain url

Javascript Solutions


Solution 1 - Javascript

As others have said you are "tainting" the canvas by loading from a cross origins domain.

https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image

However, you may be able to prevent this by simply setting:

img.crossOrigin = "Anonymous";

This only works if the remote server sets the following header appropriately:

Access-Control-Allow-Origin "*"

The Dropbox file chooser when using the "direct link" option is a great example of this. I use it on oddprints.com to hoover up images from the remote dropbox image url, into my canvas, and then submit the image data back into my server. All in javascript

Solution 2 - Javascript

I found that I had to use .setAttribute('crossOrigin', '') and had to append a timestamp to the URL's query string to avoid a 304 response lacking the Access-Control-Allow-Origin header.

This gives me

var url = 'http://lorempixel.com/g/400/200/';
var imgObj = new Image();
imgObj.src = url + '?' + new Date().getTime();
imgObj.setAttribute('crossOrigin', '');

Solution 3 - Javascript

You won't be able to draw images directly from another server into a canvas and then use getImageData. It's a security issue and the canvas will be considered "tainted".

Would it work for you to save a copy of the image to your server using PHP and then just load the new image? For example, you could send the URL to the PHP script and save it to your server, then return the new filename to your javascript like this:

<?php //The name of this file in this example is imgdata.php

  $url=$_GET['url'];

  // prevent hackers from uploading PHP scripts and pwning your system
  if(!@is_array(getimagesize($url))){
    echo "path/to/placeholderImage.png";
    exit("wrong file type.");
  }

  $img = file_get_contents($url);

  $fn = substr(strrchr($url, "/"), 1);
  file_put_contents($fn,$img);
  echo $fn;

?>

You'd use the PHP script with some ajax javascript like this:

xi=new XMLHttpRequest();
xi.open("GET","imgdata.php?url="+yourImageURL,true);
xi.send();
  
xi.onreadystatechange=function() {
  if(xi.readyState==4 && xi.status==200) {
    img=new Image;
    img.onload=function(){ 
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
    }
    img.src=xi.responseText;
  }
}

If you use getImageData on the canvas after that, it will work fine.

Alternatively, if you don't want to save the whole image, you could pass x & y coordinates to your PHP script and calculate the pixel's rgba value on that side. I think there are good libraries for doing that kind of image processing in PHP.

If you want to use this approach, let me know if you need help implementing it.

edit-1: peeps pointed out that the php script is exposed and allows the internet to potentially use it maliciously. there are a million ways to handle this, one of the simplest being some sort of URL obfuscation... i reckon secure php practices deserves a separate google ;P

edit-2: by popular demand, I've added a check to ensure it is an image and not a php script (from: https://stackoverflow.com/questions/15408125/php-check-if-file-is-an-image).

Solution 4 - Javascript

I was seeing this error on Chrome while I was testing my code locally. I switched to Firefox and I am not seeing the error any more. Maybe switching to another browser is a quick fix.

If you are using the solution given in the first answer, then make sure you add img.crossOrigin = "Anonymous"; just after you declare the img variable (for eg. var img = new Image();).

Solution 5 - Javascript

When working on local, add a server.

I had a similar issue when working on local. Your URL is going to be the path to the local file, for example, file:///Users/PeterP/Desktop/folder/index.html.

Please note that I am on a Mac.

I got around this by installing an HTTP server globally. I used https://www.npmjs.com/package/http-server

Steps

  1. Global install: npm install http-server -g
  2. Run server: http-server ~/Desktop/folder/

These steps assume that you have node installed, otherwise you won't get very far running npm commands.

Solution 6 - Javascript

My problem was so messed up I just base64 encoded the image to ensure there couldn't be any CORS issues

Solution 7 - Javascript

You are "tainting" the canvas by loading from a cross origins domain. Check out this MDN article:

https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image

Solution 8 - Javascript

Your problem is that you load an external image, meaning from another domain. This causes a security error when you try to access any data of your canvas context.

Solution 9 - Javascript

As matt burns says in his answer, you may need to enable CORS on the server where the problem images are hosted.

If the server is Apache, this can be done by adding the following snippet (from here) to either your VirtualHost config or an .htaccess file:

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
            SetEnvIf Origin ":" IS_CORS
            Header set Access-Control-Allow-Origin "*" env=IS_CORS
        </FilesMatch>
    </IfModule>
</IfModule>

...if adding it to a VirtualHost, you'll probably need to reload Apache's config too (eg. sudo service apache2 reload if Apache's running on a Linux server)

Solution 10 - Javascript

you can convert the image to a data string as use the image source instead of the actual image source.

[https://www.base64-image.de/][1] to convert image to data string. Convert and copy string data from the above website. set image.src = .

Solution 11 - Javascript

workaround solution, convert source image URL to Base64 data and assign to img

for example, use Axios

const getBase64 = async(url)=>{
      try {
        let image = await axios.get(url, { responseType: 'arraybuffer' });
        let raw = Buffer.from(image.data).toString('base64');
        return "data:" + image.headers["content-type"] + ";base64,"+raw;
      } catch (error) {
          console.log(error)
      } 
}

var image = new Image()

image.src=getBase64(url)

no cross-origin dependency from canvas

Solution 12 - Javascript

I meet the same problem today, and solve it by the code follows.

html code:

<div style='display: none'>
  <img id='img' src='img/iak.png' width='600' height='400' />
</div>
<canvas id='iak'>broswer don't support canvas</canvas>

js code:

var canvas = document.getElementById('iak')
var iakImg = document.getElementById('img')
var ctx = canvas.getContext('2d')
var image = new Image()
image.src=iakImg.src
image.onload = function () {
   ctx.drawImage(image,0,0)
   var data = ctx.getImageData(0,0,600,400)
}

code like above, and there is no cross-domain problem.

Solution 13 - Javascript

I was having the same issue, and for me it worked by simply concatenating https:${image.getAttribute('src')}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionErfan SafarpoorView Question on Stackoverflow
Solution 1 - Javascriptmatt burnsView Answer on Stackoverflow
Solution 2 - JavascriptKirbyView Answer on Stackoverflow
Solution 3 - JavascriptSymbolicView Answer on Stackoverflow
Solution 4 - JavascriptSafwanView Answer on Stackoverflow
Solution 5 - JavascriptAnasView Answer on Stackoverflow
Solution 6 - JavascriptbumsoverboardView Answer on Stackoverflow
Solution 7 - JavascriptsrquinnView Answer on Stackoverflow
Solution 8 - JavascriptaxelduchView Answer on Stackoverflow
Solution 9 - JavascriptNick FView Answer on Stackoverflow
Solution 10 - JavascriptBikrant JajwareView Answer on Stackoverflow
Solution 11 - JavascriptSrinu RavuriView Answer on Stackoverflow
Solution 12 - JavascriptKarryView Answer on Stackoverflow
Solution 13 - JavascriptLivia RettView Answer on Stackoverflow