Unable to load WMTSTileSource url, in CustomJS, CORS policy: No 'Access-Control-Allow-Origin'

Hi, setting the WMTSTileSource url works fine in python, but bokeh cant load it inside a CustomJS.

Getting the error “Access to image at ‘https://tile.openstreetmap.org/{z}/{x}/{y}.png’ from origin ‘https://xxxx.xxxxxxx.ca’ has been blocked by Access to image at ‘https://tile.openstreetmap.org/{z}/{x}/{y}.png’ from origin ‘https://xxxx.xxxxxxx.ca’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.”

I changed my personal address above to xxxx.xxx…

Does bokeh have a way around this? like sending the Get to a proxy or something? I bet changing the Vendors (bokeh.tile_providers — Bokeh 2.4.2 Documentation) in a CustomJS could get around this, but Vendorsdoesnt appear to exist in my WMTSTileSource…

Minimal example here:

from bokeh.models import WMTSTileSource, Button, CustomJS
from bokeh.plotting import figure, show, output_notebook
from bokeh.tile_providers import *
from bokeh.layouts import row

TEST_tilesource = WMTSTileSource(url='https://tile.opentopomap.org/{z}/{x}/{y}.png',
                     snap_to_zoom=True)

output_notebook()
tile_provider = get_provider(TEST_tilesource)

p = figure(x_range=(-14000000, -6000000),
           y_range=(6000000, 7000000),
           #x_axis_type="mercator",
           #y_axis_type="mercator",
           width=500,
           height=500)

p.add_tile(tile_provider)


SwitchBasemap = Button(label="Switch Basemap", align='center')
SwitchBasemap.js_on_click(CustomJS(args=dict(wmts=p.renderers[0].tile_source), code="""
        console.log(wmts.url);
        wmts.url = "https://tile.openstreetmap.org/{z}/{x}/{y}.png";
        
        wmts.change.emit();
        console.log(wmts.url);
    """))
        

show(row(p,SwitchBasemap))

I don’t think anyone has ever asked about swapping out the tile provider before. I’d like to think there is a simple solution, but browsers also have security concerns/polices around loading external resources into HTML canvases, so it will require some investigation. A GitHub Issue with details woudl be appropriate.

In the mean time, my only suggestion is to try making entire separate plots in layout, and having the callback toggle the visibility of each, instead of setting the tile provider url.

1 Like

Just a nice feature for the user to swap basemaps without having to change anything in python and re-run. That work around works great for now though, good idea, thanks!