Repository navigation
[BUG]: Access blocked for OpenStreetMap tiles #5562
Description
Activity
According to OSM's tile policy https://operations.osmfoundation.org/policies/tiles/ you have to either set "a valid HTTP User-Agent [header]" or "a valid HTTP Referer header", otherwise you might get throttled as above.
Plotly should allow to provide either of these so OSM people are happy.
I just tried running your example and didn't see an issue. Is the problem still happening for you?
I just tried running your example and didn't see an issue. Is the problem still happening for you?
For us the issue happens every 50% of times a map is rendered, I'd say. Only some of the tiles in view would be replaced by the error. Perhaps it's a usage thing that regular testing wouldn't bring up?
Either way, I took a look at the obfuscated frontend code, and it seems like the referrer is passed along when creating the Request object, but the browser ignores the argument and sets it toabout:client. At least, that's the case for us when rendering it in a new iframe (using Viktor). Why this is the case I do not know, but that's why OpenStreetMap is saying the referer header is missing.I just tried running your example and didn't see an issue. Is the problem still happening for you?
The problem occurs randomly, about once in two.
I took a look at the source code, but I couldn't find where do you either have a function that generates that image, or call a function that does it. @elpamplina said that at some point there's a browser involved?
I have found that the JS core does try to get the referrer, but the worker created by the Python wrapper cannot give it to it (probably because being a background instance created by the wrapper it has no real reference).
You can find the referrer in the line 176742 in the unobfuscated core library:
https://github.com/plotly/plotly.js/blob/a6663c92620c222b0fd9b01495c724bbde4ab5d3/dist/plotly.jsvar getReferrer = isWorker() ? function() { return self.worker && self.worker.referrer; } : function() { return (window$1.location.protocol === "blob:" ? window$1.parent : window$1).location.href; };We would have to look for the reason why some tiles are loaded and others not because different OSM servers will have different referrer policies, and it randomly coincides that at some point they all accept it.
I think the best solution is for the wrapper to support a referrer attribute, so that it can be passed to the core JS and thus comply with the policy.
For instance:map=dict( style="open-street-map", center=dict(lat=lat, lon=lon), zoom=16, referrer="https://example.com" ),I do not have the precise knowledge of how wrapper works to do it myself.
We would have to look for the reason why some tiles are loaded and others not because different OSM servers will have different referrer policies, and it randomly coincides that at some point they all accept it.
It's something that the OSM tile server does, it only replaces some of the tiles with the one with the error, so users can find the issue by themselves and act accordingly without flatly refusing to serve tiles.
- added a commit that references this issue
on Apr 10, 2026 The calls to the tile server go through the maplibre library, which is where that code reference comes from in the bundle. That library does try to add the referrer properly, but something is breaking between that point and the rendering of the image. The image rendering is done with Kaleido, which uses a headless version of Chrome. It's possible the headers are being lost during that process.
I was wondering if this could be connected with openmaptiles returning phishing error
any solution?
I'm working on a fix. The change needs to be made in both Kaleido and plotly.py. Choreographer communicates with headless Chrome and the instructions for that come from Kaleido. Kaleido isn't set up yet to pass in headers, so that work needs to be done. Then plotly.py needs to be updated to allow for passing in headers. We'll add a default header for
Referrer, but users can update that if they want. This is all a plan and could change, but I ran some tests locally and the tiles stopped showing the issue.I'm working on a fix. The change needs to be made in both Kaleido and plotly.py. Choreographer communicates with headless Chrome and the instructions for that come from Kaleido. Kaleido isn't set up yet to pass in headers, so that work needs to be done. Then plotly.py needs to be updated to allow for passing in headers. We'll add a default header for
Referrer, but users can update that if they want. This is all a plan and could change, but I ran some tests locally and the tiles stopped showing the issue.Many many thanks for the effort. Greatly appreciated.
☺️ For reference, the header that needs to be added is "Referer" for web apps or "X-Requested-With" for non-web apps (source). Since Kaleido runs Choreographer under the hood and that uses headless Chrome, no "Referer" header is being included in requests, so we'll (likely) be adding "X-Requested-With" for requests originating from plotly.py.
Is anyone able to reproduce this today? I'm having trouble triggering the issue.
Is anyone able to reproduce this today? I'm having trouble triggering the issue.
There're no issues in my logs since 2026-04-30. It seems something changed last week. New OSM policies? 🤔
Perhaps. I'll still move forward with the change, which did fix the problem when I could still get it to happen. Thanks for checking.
Many thanks, Cameron!


Description
Generating a map from OpenStreetMap, some tiles are filled with the error message: "403r Access blocked. Referer is required by tile usage policý of OpenStreetMap's volunteer-run servers: osm.wiki/Blocked"
This occurs randomly about half the times, on one or more tiles.
Screenshots/Video
Steps to reproduce
Python code:
Generated with:
plotly 6.6.0
kaleido 1.2.0