Fix: Tainted canvases may not be exported.

The other day, I came across a frustrating CORS-related error while developing a Facebook Instant Game. This is a short post on how I fixed it.

The error that appeared in my console read as follows:

Failed to execute ‘toDataURL’ on ‘HTMLCanvasElement’: Tainted canvases may not be exported.

The SecurityError exception.

Essentially, I had added an image to my canvas element that was considered to be “tainted”. As a result, the browser refused to convert my canvas into an image. The JavaScript code that threw this particular error was:

//Convert canvas element to image.
var imgURL = canvas.toDataURL();

Due to the CORS mechanism that most browsers implement, the toDataURL method will throw a SecurityError exception if any of the contents of the canvas have been loaded from another site.

In my particular case, I had added the user’s photograph to the canvas using FBInstant.player.getPhoto(). However – I had made the fatal mistake of not setting the crossOrigin attribute of the Image object to “anonymous”.

To fix this issue, I had the to set the origin attribute like so:

var img = new Image();
img.origin = 'anonymous';
img.src = 'http://example.com/img/example.jpg';

Note that the code above will only work if example.com has an Access-Control-Allow-Origin policy that allows it.

Because Facebook does support such a policy, I was able to load the player’s profile picture like so:

//JS Image object for the user's profile picture.
var profileImage = new Image();

//Set the crossOrigin attribute to anonymous.
profileImage.crossOrigin = 'anonymous';

//Get the user's image and set it as the src attribute.
profileImage.src = FBInstant.player.getPhoto();

Hopefully, this post saved you a bit of time and effort!