Skip to content

Migration Guide for Stamen Map Tile Users

Stadia Maps has partnered with Stamen Design to host their iconic map styles. If you are currently accessing Stamen map tiles via the Fastly CDN or a Stamen domain, you'll need to make a few (small!) changes to keep on using these maps after August 31, 2023. After this point, we will start progressive brownouts before the old URLs stop working entirely on October 31, 2023.

The typical migration for a web-based map should take about ten minutes. In most cases you'll only need to touch 2 or 3 lines of code. Let's dive in!

Create a Stadia Maps account

We've set up an onboarding flow specifically for Stamen users to make the migration as easy as possible. No credit card is required to create an account, and we offer a free tier for non-commercial users. Commercial and higher-volume plans start at just $20/month. If you have any questions about pricing or aren't sure which plan you need, contact us via email at

Create an Account

The onboarding flow will walk you through setting up domain authentication or an API key. After entering your domain or generating an API key, you're ready to migrate! If you are using the Stamen URLs directly, proceed to our URL-based migration steps. Otherwise, find your framework under the framework/library migration steps.

Toner Hybrid Deprecation Notice

Note that the Toner Hybrid style is deprecated. You can recreate this by combining the lines and labels layer groups. Additionally, you may find that you can achieve the same (or better) by migrating your application to vector styles.

URL-based migration steps

Switch your tile URLs

If you are using the URLs directly (for example, in Leaflet via an L.tileLayer), find your style in the table below and copy the new URL format string. Leaflet users can copy this directly into the L.TileLayer URL configuration. Other map renderers typically use a similar URL format.

Style URLs

What do {x}, {y}, {z}, and {r} mean?

The {x}, {y}, and {z} placeholders represent x, y, and zoom following the standard slippy map tilename convention. This format is used by most popular libraries. Note that our tile numbering uses the XYZ scheme, not TMS.

The {r} placeholder is used for HiDPI ("retina") display suppoort. Popular web map renderers like Leaflet understand this placeholder. If your renderer does not understand this (e.g., MapLibre GL JS or QGIS), you can either remove the placeholder to get raw 256x256 PNGs, or replace it with @2x for 2x scaled images.

Here is a translation table of the primary map styles with all cartographic layers present. Simply change your URLs in Leaflet, OpenLayers, or your other raster map renderer of choice.


If you'd like to use an API key instead of domain auth, simply append ?api_key=YOUR-API-KEY to the URLs above.

Stamen identifier Stadia URL format Notes
watercolor{z}/{x}/{y}.jpg JPEG only; not available in @2x resolution

Layer Group URLs

We also have a migration path for Stamen's "flavors" containing a subset of the cartographic layers in the full style.

Stamen identifier Stadia URL format Notes
toner-background{z}/{x}/{y}{r}.png Includes only background layers (water, landcover, etc.) and lines (roads, borders, etc.)
toner-lines{z}/{x}/{y}{r}.png Includes only line layers (road, borders, etc.)
toner-labels{z}/{x}/{y}{r}.png Includes only label layers (places, road names, etc.)
toner-hybrid Deprecated. You can recreate toner-hybrid by combining the labels and lines layer groups or using vector styles
terrain-background{z}/{x}/{y}{r}.png Includes only background layers (water, landcover, hillshading, etc.)
terrain-lines{z}/{x}/{y}{r}.png Includes only line layers (road, borders, etc.)
terrain-labels{z}/{x}/{y}{r}.png Includes only label layers (places, road names, etc.)

Updating attribution

Finally, you'll need to update your attribution to include Stadia Maps and (for all styles except Watercolor) OpenMapTiles. In HTML, the full attribution looks like this.

&copy; <a href="" target="_blank">Stadia Maps</a>
&copy; <a href="" target="_blank">Stamen Design</a>
&copy; <a href="" target="_blank">OpenMapTiles</a>
&copy; <a href="" target="_blank">OpenStreetMap</a>

Leaflet example: Bringing it all together

Here's an example of how to update a Toner Lite map to the new URL in Leaflet.

- L.tileLayer('https://stamen-tiles-{s}{z}/{x}/{y}{r}.png', {
+ L.tileLayer('{z}/{x}/{y}{r}.png', {
    maxZoom: 19,
-    attribution: 'Map tiles by <a href="">Stamen Design</a>, Data by &copy; <a href="">OpenStreetMap</a> under <a href="">ODbL<a/>',
+    attribution: '&copy; <a href="" target="_blank">Stadia Maps</a> <a href="" target="_blank">&copy; Stamen Design</a> &copy; <a href="" target="_blank">OpenMapTiles</a> &copy; <a href="" target="_blank">OpenStreetMap</a>',

Migration steps for other integrations

We are working with major plugins and library authors to transition to the new URLs, and will update this guide as updates are available. Send us an email if you have any questions.


We are working to prepare a pull request to update the URLs for the Stamen map styles. In the meantime, you can update your code to directly call the new URLs, along with your API key.

Here is an example script:

import geopandas
import geodatasets
import contextily as cx

df = geopandas.read_file(geodatasets.get_path("nybb"))
ax = df.plot(figsize=(10, 10), alpha=0.5, edgecolor="k")

-   cx.add_basemap(ax,, source=cx.providers.Stamen.Terrain)
+   cx.add_basemap(ax,, source='{z}/{x}/{y}{r}.png?api_key=YOUR-API-KEY')


folium has built in references for some tile styles, however, the new Stamen URLs are not available. To access these, you can utilize the xyzservices library.

If you use Domain Authentication, you can simply reference the appropriate style and you should be all set. If you are using API keys, you will also need to append the api_key variable to the URL.

The code below is for Stamen Toner and uses the API key authentication method:

import folium
import xyzservices.providers as xyz

m = folium.Map(location=[39.7684, -86.1581], zoom_start=12)

#Add the Stadia Maps Stamen Toner provider details via xyzservices
tile_provider = xyz.Stadia.StamenToner

#Update the URL to include the API key placeholder
tile_provider["url"] = tile_provider["url"] + "?api_key={api_key}"

#Create the folium TileLayer, specifying the API key



The team behind GeoLayers have recorded a video demonstrating how to continue using the Stamen map styles with Stadia Maps.

Licensing for Commercial Use

Please contact for licensing information and a quote if you are using our maps for commercial use. For non-commercial (including academic) use, no special permission or licensing is necessary for these projects. See our FAQ for details.


As of ggmap version 4.0.0, it's (still!) easy to use the Stamen basemaps. You can check your current version by typing the following code into your R console.


If it is less than 4.0.0, you'll need to upgrade.

Using Stamen Watercolor? Follow these steps first!

There is currently a bug in the released version of ggmap with the Stamen Watercolor style.

If you are using this style, follow these steps before proceeding:

  1. Remove the existing version of ggmap from your environment.

  2. Install the devtools package in your R environment.

  3. Install the patched version from GitHub.


Next, before you draw any plots, you need to register your API key.

register_stadiamaps("YOUR-API-KEY-HERE", write = TRUE)

For a one-off visualization in an ephemeral environment, or if you are working on a shared computer, omit the write argument. In other cases, we recommend leaving it. This saves the API key to your .Renviron file (usually in your home directory), which is automatically loaded when starting most new R sessions. This way you don't need to keep keys in your source code.

Then, it's just a matter of changing a few lines of code! First, any Stamen styles have slightly different names. Stamen styles will have all - characters replaced with an _. Additionally, you'll need to add a stamen_ prefix. Bringing it all together, toner-lite would become stamen_toner_lite. You can find the style identifiers on each of our map styles pages.

If you were using the get_stamenmap function, this has been renamed to get_stadiamap. Other functions like qmplot remain unchanged, but don't forget to update the parameters with the new style identifiers. Here are some examples.

Updating get_stamenmap usage
- get_stamenmap(bbox, zoom = 5, maptype = "toner-lite") %>% ggmap()
+ get_stadiamap(bbox, zoom = 5, maptype = "stamen_toner_lite") %>% ggmap()
Updating qmplot usage
- qmplot(lon, lat, data = earthquakes, maptype = "toner-lite", geom = "density2d", color = I("red"))
+ qmplot(lon, lat, data = earthquakes, maptype = "stamen_toner_lite", geom = "density2d", color = I("red"))

Knight Lab StoryMapJS

If you have an existing storymap, you'll need to follow the directions on their updated basemap page. After signing up for your account, follow the instructions to add an API key and select your preferred style.

Leaflet in R

If you are using the R implementation of Leaflet or a tool that builds on it like Shiny Apps, update to the latest version of Leaflet Providers and use the new provider name. Everything has been migrated under the Stadia provider, and we've added a Stamen prefix. For example, Stamen.Terrain becomes Stadia.StamenTerrain.


leaflet()  |>
  setView(lng = -71.0589, lat = 42.3601, zoom = 12) |>
  addTiles() |>

Note that this approach works inside RStudio, for localhost development, and with domain-based auth. If you are deploying in a situation where you can't use domain auth, you'll need to use an API key. You can do this with the addTiles method and a URL template directly like so:


map <- leaflet() %>%
    urlTemplate = "{variant}/{z}/{x}/{y}{r}.png?api_key={apikey}",
    attribution = paste('&copy; <a href="" target="_blank">Stadia Maps</a> ' ,
                            '&copy; <a href="" target="_blank">Stamen Design</a> ' ,
                            '&copy; <a href="" target="_blank">OpenMapTiles</a> ' ,
                            '&copy; <a href="" target="_blank">OpenStreetMap</a>'),
    options = tileOptions(variant='stamen_toner_lite', apikey = 'YOUR-API-KEY')
    )  %>%
fitBounds(lng1 = -86.1581, lat1 = 39.7684, lng2 = -87.1581, lat2 = 40.7684)


Leaflet providers

Leaflet Providers has support for the Stamen Styles from Stadia Maps since version 2.0.0. If you are using Leaflet Providers directly, you will need to change your style name slightly. The styles have all moved under the Stadia provider, and the style name has been prefixed with Stamen. For example:

- L.tileLayer.provider('Stamen.Watercolor').addTo(map);
+ L.tileLayer.provider('Stadia.StamenWatercolor').addTo(map);

You can see the full list of available style identifiers on the Leaflet Providers preview site.

Little Navmap

Little Navmap has a patch ready that will include the Stamen style URLs. If you are seeing warning tiles, you can follow the steps in this GitHub issue to resolve the issue today. The next release will include a permanent fix.

Maps Marker Pro

Maps Marker Pro supports Stadia Maps since version 4.27. You can upgrade to get access to the new Stadia-hosted styles by Stamen. Maps Marker has a full walkthrough of the setup process on their website.

Mapster WP Maps

In order to utilize the new Stamen map tiles, you will need to add a Custom Style JSON to your instance. You can follow our guide to accomplish this.


If you were previously using the Stamen source in your application, update to the StadiaMaps source instead after upgrading OpenLayers v8.0.0 or higher.

Here is an example of switching a map that had the Stamen Watercolor style and the terrain labels layer.

 import Map from 'ol/Map.js';
-import Stamen from 'ol/source/Stamen.js';
+import StadiaMaps from 'ol/source/StadiaMaps.js';
 import TileLayer from 'ol/layer/Tile.js';
 import View from 'ol/View.js';

 const map = new Map({
   layers: [
     new TileLayer({
-      source: new Stamen({
-        layer: 'watercolor',
+      source: new StadiaMaps({
+        layer: 'stamen_watercolor',
+        // apiKey: 'OPTIONAL' (we suggest domain-based auth)
     new TileLayer({
-      source: new Stamen({
-        layer: 'terrain-labels',
+      source: new StadiaMaps({
+        layer: 'stamen_terrain_labels',
+        // apiKey: 'OPTIONAL' (we suggest domain-based auth)

Still using an older version? No worries. You can reference the tiles directly by URL in an XYZ source. Our OpenLayers tutorial shows you how.

xyzservices compatible libraries

If you are using a xyzservices compatible Python environment, you can reference the new Stamen tile URLs easily. A full list for Stadia Maps can be found in their docs.

After you specify the provider and variant, you should be all set if you are using Domain Authentication.

If you need to utilize an API key, you must modify the base URL to include the key. We'll use Stamen Toner in the example below:

provider = xyz.Stadia.StamenToner(api_key="<insert api_key here>")
provider["url"] = provider["url"] + "?api_key={api_key}"  # adding API key placeholder

We're here to help

At Stadia Maps, real human support is part of our DNA. If you have any questions or need further assistance with your migration, send us an email.