The CORS error seen is:

Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported

All this doesn't work:

OpenLayers 3: Cross-Origin Request Blocked: The Same Origin Policy disallows

Enabling CORS in OpenLayers

https://stackoverflow.com/questions/20260620/openlayers-3-and-xyz-layer ( the exemple jsfiddle don't even work)

Can't do this (I don't own the server):


I'm tring to save my map as PNG (http://openlayers.org/en/v3.0.0/examples/export-map.html).

The example works nice in my server with only the OSM layer, but when I add one more layer from anywhere, I got the CORS error.

My application allow the user to add arbitrary layers from any getMap link, so I have no control over the source Geoserver.

I have an addLayer function to do the job (add the user's layer to the map).

function addLayer( serverUrl, serverLayers, layerName ) {
    var newLayer = new ol.layer.Tile({
        source: new ol.source.TileWMS({
            url: serverUrl,
            isBaseLayer : false,
            crossOrigin: 'anonymous',  <<<<--- PROBLLEM
            params: {
                'layers': serverLayers,
                'format': 'image/png'
            projection: ol.proj.get('EPSG:4326')
    newLayer.set('name', layerName);
    map.addLayer( newLayer );
    return newLayer;

When I add the crossOrigin: 'anonymous' nothing works anymore. Without crossOrigin it work if the map have only the OSM layer. By adding any other layer I got the CORS error.

Is there any other way to get the Map as image than using the canvas?

I've searched over all this site and found many different answers but none worked.

I cannot configure server side.

This is my export function:

function exportMap() {
    map.once('postcompose', function(event) {
        var canvas = event.context.canvas;
        var xx = canvas.toDataURL('image/png'); <<------- CORS Error !!
        console.log( xx );
  • What is the precise "CORS error" that you received? If you were able to resolve that then the rest of your question would become unnecessary. Also, even though you have been on the site for 3-4 years I noticed that you have not yet taken the Tour which is intended to introduce all users to the site and its protocols.
    – PolyGeo
    Jun 22, 2016 at 20:01
  • Do you even know what is the CORS ? I'm receiving THE CORS error. When I try to access some resource from a cross domain. In the Chrome it is like Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.. For those reading about the crossOrigin parameter in my question will know exactly what I'm talking about. If don't, he will not know a correct answer. No, I don't take the Tour. Thanks for advised me.
    – Magno C
    Jun 24, 2016 at 1:32
  • The Stack Exchange model is as much and probably more geared towards educating future visitors as it is to the needs of the original question asker. That is why details should not be glossed over. Your question is not just for a few potential answerers but is for the GIS community.
    – PolyGeo
    Jun 24, 2016 at 2:58
  • Thanks. As part of the moderation members you're doing a great job on leading us to improve the questions quality.
    – Magno C
    Jun 24, 2016 at 3:13

2 Answers 2


Unfortunate, what you are experiencing, is expected behavior, and not a Bug.

Once you add an Image from an external domain, or cross-domain, and use it on the canvas, the canvas becomes "tainted" and the browser will not allow you to pull data out of it.

The only solution for this is two step:

  1. Proper headers need to be sent by the server, which is sending you the images

  2. The crossOrigin attribute on the image itself in the JavaScript. In OpenLayers, you can do this by using crossOrigin: 'anonymous' in the layer settings. For example:

    var wms_layer=new ol.layer.Tile({
      extent: [-13884991, 2870341, -7455066, 6338219],
      source: new ol.source.TileWMS({
        url: 'http://demo.boundlessgeo.com/geoserver/wms',
        params: {'LAYERS': 'topp:states', 'TILED': true},
        serverType: 'geoserver',
        crossOrigin: 'anonymous'

Now I know that you do not have control over the server, so you cannot do the first step.

In-case the server allows it, you could have a proxy on your own server, which serves these tiles, and the whole issue will be side-stepped.

  • Please see my addLayer function. I'm already tried crossOrigin and I don't know how to use crossOriginKeyword in a ol.source.TileWMS. The result was: My map stops to show all my layers due to the CORS. All blank. Removing the crossOrigin property makes my layers to work on the map but the canvas becomes tainted when I try to save as PNG.
    – Magno C
    Jun 24, 2016 at 4:13
  • Even if you manage to use the crossorigin parameter, it will not work, since the server needs to send the proper header. Jun 24, 2016 at 4:16
  • So there is no way to make it to work without changing at server side? I've tried jsfiddle.net/8ypxW/3 but all I've got was the map screen with the controls but no layers passing the #map div.. No CORS problem... almost there!
    – Magno C
    Jun 24, 2016 at 4:18
  • @MagnoC: Yes, you need the server to send the Access-Control-Allow-Origin header. Jun 24, 2016 at 4:30
  • Oh Lord... so there is no way to do this...
    – Magno C
    Jun 29, 2016 at 11:47

I had the same problem and realized the solution as follows:

If your geoserver address and application address different then you get this error.

For Example;

C# Project Publish Address: http://localhost:51245/ApplicationName
Geoserver Address in Your Application:

You will receive this error because the port numbers and ip addresses of the above addresses are different.

If you redirect geoserver address with ISS and publish application in same server then it will solve.

For Example:

C# Project Publish Address:
Geoserver Address in Your Application:

You must install AARv3 on server and 'Enable Proxy' from 'Application Request Routing Cache'. After then publish routing application on IIS.

Enable Proxy

Publish this code in webconfig

<?xml version="1.0" encoding="UTF-8"?>

                <rule name="ReverseProxyInboundRule1" stopProcessing="true">
                    <match url="(.*)" />
                    <action type="Rewrite" url="{R:1}" />
      <requestLimits maxQueryString="32768"/>
      <httpRuntime maxQueryStringLength="32768" maxUrlLength="65536"/>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.