Error 403 when using local files - referer missing - can I use User Agent and what should it contain

Unfortunately OSMF is operating on a shoestring budget.

Also, as far as I know this specific problem has no obvious technical solutions, except ones that overall make things worse.

If they missed one, feel free to describe workable one.

I am not your therapist.

For practical solutions I will be hosting them at localhost (serving html at localhost is not so hard though extra step is annoying) or replacing tile servers with understanding that it only pospones problem until others do the same.

I just did it with some of my tools, some now use German map style.

OSM carto devs are unrelated to the issue here, this is more operational and hosting issue, and specific design of map style has a very limited, if any, impact

What SLA do you have with them?

You don’t have a SLA with database contributors yet feel entitled to criticise their changesets.

Highlight a reason why those who attempt to write code for OSM are above having their practises questioned

If you can suggest a way that pages at file:// can supply the information the tile usage policy requires, we would welcome that.

A page or app sending a generic browser user-agent with no referer (or x-requested-with) is violating the tile usage policy. That has been part of the policy since the early 2010s. We will not be removing that requirement.

We are doing a brownout where we send error tiles on a % requests because we know some pages have inadvertently set a referrer-policy that causes them to not follow the policy. There was no other way to contact them because their referrer policy was blocking the information we would need to contact them.

@pnorman

If (what I assume) your (=OWG) cache settings in fastly VSL would allow to disregard query params in a tile url, maybe there is a chance to e.g. set a user-agent via query param and have that checked in VSL (and e.g. blocked if that localhost app using file:// is behaving badly)?

E.g. tilelayer url: http://tile.openstreetmap.org/{z}/{x}/{y}.png?user-agent=my-fancy-localhost-app-with-a-unique-user-agent or something similar

Maybe it would be a better idea if anyone using file:// is just putting in some effort and use e.g. a add header plugin for leaflet tilelayer like this one (untested): GitHub - jaq316/leaflet-header: Custom headers on Leaflet TileLayer · GitHub

Ok, just tested this and it is working: Bildschirmaufzeichnung vom 16.04.2026, 18:16:32 - Embed

So please do the following: add the GitHub - jaq316/leaflet-header: Custom headers on Leaflet TileLayer · GitHub plugin to your leaflet map (or another one that will let you add custom headers to a tile request), use a custom X-Requested-With header like this:

<script>
	const map = L.map('map').setView([51.505, -0.09], 13);
	const tiles = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
		maxZoom: 19,
		attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
	},
	[
	{ header: 'X-Requested-With', value: 'my-fancy-app-called-via-file' }
	],
	null
	).addTo(map);
</script>

(but please come up with a better - and unique - name for your app)

and you will not run into those 403 errors while displaying the leaflet map in a file:// html page.

For the past few months I am also having this issue, so far only noticed it with overpass turbo. Always a few 403r tiles on the map view.
I just now looked up why is this happening.

In my case I’m getting error tiles because my Firefox is configured to only send referers for the same origin, to improve web browsing privacy. Generally websites have no business knowing my search engine, or the other sites from where I followed their link, because virtually any other site would abuse this information for their gains, at the expense of the visitors.

I understand that for OSM tiles this is actually a legitimate use. And I would trust OSM with using this feature respectfully. But I dont seem to be able to allow this selectively, so it will stay this way.
Do you know about a solution for those who access map services with privacy enhancing features enabled to not send referers?

Well, in about:config reverting network.http.referer.XOriginPolicy to 0 but setting network.http.referer.spoofSource to true (both documented here) seems to have convinced the tile servers. Though its a bit misleading to the operators, because this way the referer contains the tile URL, not the actual referring site.

I wouldnt recommend anyone do this, because this really weird operation makes your browser rather uniquely fingerprintable by most sites. So in the end this would be worse for both the users and the operators.
Probably its just better to keep a separate browser profile for OSM with lax privacy settings. At least thats now less cumbersome since Firefox implemented a better profile manager menu.

Still, a different solution would be much better.


Edit: from a user privacy point of view, it might be better actually to have network.http.referer.XOriginPolicy as 0, network.http.referer.spoofSource as true, and network.http.referer.trimmingPolicy as 2, to better blend in with the average user, in case omitting the referrer is the unusual thing nowadays. This way external resources will load with the referer set to the external resource URL, but trimmed to the domain name, without path and query parameters.

Is the X-Requested-With header documented anywhere? (from OSM side)

I’m currently trying to fix a local map that is made on OpenLayers and sending X-Requested-With triggers preflight requests that the OSM servers do not approve.

X-Requested-With is a crutch for apps that do not send a referrer. Main goal is as always to have a distinct, unique user identifiable that is also contactable (so maybe it’s a good idea to add a X-Contact-Email header as well).

As browsers do not send referrers when loading external assets into a local html file accessed via file://, this was used as a crutch but you’ll need the second crutch in disabling cors in your browser for that file.

I reread the usage policy:

Send a valid HTTP User-Agent that clearly identifies your application (or a platform X-Requested-With app ID where set automatically).

Okay, that’s documented. However, it’s useless because OSM servers don’t respond correctly to preflight requests.

Code example: osm-openlayer-x-requested-with-demo/index.html at master · deevroman/osm-openlayer-x-requested-with-demo · GitHub it doesn’t work when opened via file://

Maybe it is fixable but first step would be specifying what exactly was requested, what exactly was answer and what would be expected one

This is what I’m talking about: Preflight request - Glossary | MDN

My browser is attempting to fulfill the following request:

curl 'https://tile.openstreetmap.org/10/617/321.png' \
  -X OPTIONS \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:151.0) Gecko/20100101 Firefox/151.0' \
  -H 'Accept: */*' \
  -H 'Accept-Language: ru,en-US;q=0.9,en;q=0.8' \
  -H 'Accept-Encoding: gzip, deflate, br, zstd' \
  -H 'Access-Control-Request-Method: GET' \
  -H 'Access-Control-Request-Headers: x-requested-with' \
  -H 'Origin: null' \
  -H 'Connection: keep-alive' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: cross-site' \
  -H 'Priority: u=4'

But it receives a blocked tile (?!) in response. OPTIONS requests are expected to receive only response headers in response, without any body.


Moreover, if you make a request with Accept: image/*, you will get access-control-allow-headers: x-requested-with

There’s likely a configuration error in the order in which rules are applied, and the server is rejecting any request with Accept: */*. However, this is incorrect for OPTIONS requests; the browser correctly sends Accept: */*, because it does not try to obtain an image.