Skip to content

Figure.tilemap/pygmt.datasets.tile_map: Set User-Agent to avoid blocked access to OSM tile server - #4816

Merged
seisman merged 10 commits into
mainfrom
tilemap/header
Aug 12, 2026
Merged

Figure.tilemap/pygmt.datasets.tile_map: Set User-Agent to avoid blocked access to OSM tile server#4816
seisman merged 10 commits into
mainfrom
tilemap/header

Conversation

@seisman

@seisman seisman commented Aug 11, 2026

Copy link
Copy Markdown
Member

Not sure why it worked before, but it turns out that now we need to set "User-Agent" when requesting tiles from the OSM tile server.

This PR sets the default User-Agent to something like PyGMT/v0.19.0 (+https://www.pygmt.org) and allows custom headers.

Reference:

Closes #4815.

Preview:

@seisman seisman changed the title WIP: Figure.tilemap/pygmt.datasets.tile_map: Pass correct headers following OSM tile policy Figure.tilemap/pygmt.datasets.tile_map: Set User-Agent to avoid blocked access to OSM tile server Aug 11, 2026
@seisman seisman added the bug Something isn't working label Aug 11, 2026
@seisman
seisman marked this pull request as ready for review August 11, 2026 14:19
@seisman seisman added the needs review This PR has higher priority and needs review. label Aug 11, 2026
@seisman

seisman commented Aug 11, 2026

Copy link
Copy Markdown
Member Author

Ping @GenericMappingTools/pygmt-maintainers for reviewing this PR.

Related but slightly off-topic:
Considering that the Figure.tilemap method is used in the PyGMT paper and it doesn't work now, I think we should make a new release, maybe v0.19.1?

@yvonnefroehlich

yvonnefroehlich commented Aug 11, 2026

Copy link
Copy Markdown
Member

Not sure why it worked before, but it turns out that now we need to set "User-Agent" when requesting tiles from the OSM tile server.

This seems to be a quite new issue: In PR #4809 merged on Sunday the tile maps gallery example looks good (https://pygmt-dev--4809.org.readthedocs.build/en/4809/gallery/maps/tilemaps.html), but in #4805 merged on Monday it fails and shows the reported issue (https://pygmt-dev--4805.org.readthedocs.build/en/4805/gallery/maps/tilemaps.html) .

$ git log
commit 1c6346bf2a55fd3db519d3ca2b066644dd6e750c (HEAD -> main, origin/main, origin/HEAD)
Author: Dongdong Tian <seisman.info@gmail.com>
Date:   Tue Aug 11 16:38:51 2026 +0800

    Update the URL links to the GMT documentation (#4814)

commit a0fd47979b1fd0c5dcea9e66f206b4a219ef3679 (gmt/url)
Author: Yvonne Fröhlich <94163266+yvonnefroehlich@users.noreply.github.com>
Date:   Mon Aug 10 11:29:55 2026 +0200

    DOC/website: Use card layout for presentations (#4805)

    Co-authored-by: Dongdong Tian <seisman.info@gmail.com>

commit 9505baa5de1dfa487dc53bc118f1a08770735fad
Author: Dongdong Tian <seisman.info@gmail.com>
Date:   Sun Aug 9 18:52:45 2026 +0800

    README: Use absolute URLs for PyGMT logos (#4809)

Looking at the wikipedia pages for openstreetmap there are quite recent updates, https://wiki.openstreetmap.org/w/index.php?title=Blocked_tiles&action=history and https://wiki.openstreetmap.org/w/index.php?title=Referer&action=history.


This PR sets the default User-Agent to something like PyGMT/v0.19.0 (+https://www.pygmt.org) and allows custom headers.

With the changes in this PR the tile maps gallery example seems to work again, including when building the documentation locally.

I am wondering if our weekly Link-Checks on Sundays can catch this. Maybe we should add a note to the release checklist to manually check this gallery example shortly before making a new release.


Related but slightly off-topic:
Considering that the Figure.tilemap method is used in the PyGMT paper and it doesn't work now, I think we should make a new release, maybe v0.19.1?

I am afraid yes. This issue affects all PyGMT versions, i.e. using a lower version does not work as an (unelegant) workaround. Thus, the Figure.tilemap method is currently not working at all, and it's likely multiple users will face this issue (so far I see no reports on the forum). It's almost one and a half months until the end of September, which is the considered time range for the release of v0.20.0.

@weiji14 weiji14 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I've scanned through contextily's code/issues and found geopandas/contextily#75, and it seems they should have set a user-agent header of some sort already since 2019? Maybe the contextily- header is getting rate-limited 😅 so ok to set a custom PyGMT one, but I hope this doesn't get rate-limited too (if so, we'll know PyGMT's fig.tilemap is getting used a lot 😆).

Related but slightly off-topic:
Considering that the Figure.tilemap method is used in the PyGMT paper and it doesn't work now, I think we should make a new release, maybe v0.19.1?

I am afraid yes. This issue affects all PyGMT versions, i.e. using a lower version does not work as an (unelegant) workaround. Thus, the Figure.tilemap method is currently not working at all, and it's likely multiple users will face this issue (so far I see no reports on the forum). It's almost one and a half months until the end of September, which is the considered time range for the release of v0.20.0.

It's only not working for OpenStreetMap tiles, but should be ok for other tilemap providers. That said, yeah a v0.19.1 would probably be good in this case.

Comment thread pygmt/datasets/tile_map.py Outdated
"wait": wait,
"max_retries": max_retries,
"zoom_adjust": zoom_adjust,
"headers": headers,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to bump to contextily>=1.7 in pyproject.toml, ref geopandas/contextily#266 and https://github.com/geopandas/contextily/releases/tag/v1.7.0

@seisman seisman Aug 12, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contextily 1.7 was released in November 2025, less than a year ago. It would be good if we could still support old versions.

It seems that we only need to pass the User-Agent header when using OSM (need to verify it). Perhaps we can continue supporting older versions of contextily in general, and require contextily>=1.7 only when OSM is used (i.e., checking if source is openstreetmap)?

Edit: Done in 0473d49.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's good to set the User-Agent header even if using a non-openstreetmap source, the changes look good to me.

Comment thread pygmt/datasets/tile_map.py Outdated
@seisman seisman mentioned this pull request Aug 12, 2026
36 tasks
@seisman

seisman commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

This issue affects all PyGMT versions, i.e. using a lower version does not work as an (unelegant) workaround.

Actually, a simple workaround is to use a different OSM tile server, e.g., the German one: https://tile.openstreetmap.de/{z}/{x}/{y}.png. In other words, perhaps we don't have to release v0.19.1?

@yvonnefroehlich

yvonnefroehlich commented Aug 12, 2026

Copy link
Copy Markdown
Member

This issue affects all PyGMT versions, i.e. using a lower version does not work as an (unelegant) workaround.

Actually, a simple workaround is to use a different OSM tile server, e.g., the German one: https://tile.openstreetmap.de/{z}/{x}/{y}.png.

That's interesting. Did not check this yesterday night; only looked at tiles beside OSM and these seem to work.

# Please note, not all zoom levels are always available.
zoom=14,
# Use tiles from OpenStreetMap tile server
source="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates PyGMT’s tilemap functionality to comply with OpenStreetMap tile usage policy by sending a User-Agent header with tile requests, and exposes a new headers parameter so callers can pass custom HTTP headers through to contextily.

Changes:

  • Add a headers parameter to Figure.tilemap and pygmt.datasets.load_tile_map, forwarding it to contextily.
  • Set a default User-Agent header (PyGMT version + project URL) for tile requests when supported by contextily.
  • Update the tilemaps gallery example and docstrings accordingly.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
pygmt/src/tilemap.py Adds headers parameter and documents header behavior for Figure.tilemap.
pygmt/datasets/tile_map.py Implements headers passthrough and default User-Agent injection (version-gated on contextily).
examples/gallery/maps/tilemaps.py Updates documentation example source URL and formatting in the gallery example.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread pygmt/datasets/tile_map.py
Comment thread pygmt/src/tilemap.py
Comment thread pygmt/datasets/tile_map.py
Comment on lines +188 to +190
if headers is None:
headers = {"User-Agent": f"PyGMT/{_pygmt_version} (+https://www.pygmt.org)"}
contextily_kwargs["headers"] = headers
seisman and others added 3 commits August 12, 2026 16:09
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Comment thread pygmt/datasets/tile_map.py Outdated
HTTP headers to include with requests to the tile server. This can be useful
for authentication or to set a custom User-Agent. When supported by
``contextily`` (>=1.7.0), PyGMT sets a default ``User-Agent`` header like
``PyGMT/v0.19.0 (+https://www.pygmt.org)``.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to state v0.19.0 here, or can we just use PyGMT/vX.Y.Z (+https://...)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in e575bf2

@weiji14 weiji14 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @seisman, looks reasonable to me, maybe get @yvonnefroehlich to have another quick look too before merging.

@yvonnefroehlich

yvonnefroehlich commented Aug 12, 2026

Copy link
Copy Markdown
Member

In other words, perhaps we don't have to release v0.19.1?

This workaround is a nice trick!
As I am away from my laptop this morning, I did not check yet if this works for every region and if the tiles are exactly identical. Maybe partly there are some differences (font size, position, language) regarding the text labels for cities, etc.
Waiting until September would allow us to account for similar issues that may come up in the next days? Not sure if the other OSM providers or other providers will have such blocking in the future also, but maybe setting a User-Agent works for them also to avoid blocking.

@seisman seisman removed the needs review This PR has higher priority and needs review. label Aug 12, 2026
@seisman
seisman merged commit 007ab98 into main Aug 12, 2026
20 of 23 checks passed
@seisman
seisman deleted the tilemap/header branch August 12, 2026 08:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Access blocked - App is not following OpenStreetMap tile usage policy

4 participants