The Strava heatmap as contextual map tiles with contextily

This document quickly demonstrates how to source form the Strava heatmap to obtain map tiles that can be easily integrated in any modern Python geo-data workflow.

In [13]:
# Display on the notebook
%matplotlib inline

# Import contextily
import contextily as ctx

Basic example

First we will set the link for the Strava tiles (taken from here):

In [10]:
src = ''

Then it's all a matter of using the Place API (or any other way that contextily allows) to get the map delivered to your notebook. Let's play with Liverpool (UK), for example:

In [11]:
lvl = ctx.Place('Liverpool', url=src)


A more sophisticated illustration

In [28]:
import geopandas as gpd
import numpy as np
import matplotlib.pyplot as plt
import rasterio as rio
from rasterio import mask
from rasterio.plot import show as rioshow
from shapely.geometry import mapping as shply2json

src = ''

Because contextily allows you to combine webtile maps with any other data you may have, you can easily build more sophisticated maps. In this case, we will recreate the London boroughs example with Strava data. Here is what we will attempt to replicate:

You can download the original borough data from here and a reprojected GeoJSON from here, which is what we will use:

In [15]:
brs = gpd.read_file('boroughs.geojson')

In order to render the images faster and not have to rely on the remote server to pull the tiles, we will first download them all at once and store them as a tiff raster file (keep in mind this might take a little bit to run):

In [29]:
raster_link = 'london.tiff'
minX, minY, maxX, maxY = brs.to_crs(epsg=4326).total_bounds
_ = ctx.bounds2raster(minX, minY, maxX, maxY, 12, raster_link, ll=True, url=src)
CPU times: user 2.69 s, sys: 292 ms, total: 2.98 s
Wall time: 41.5 s

Just to get a sense, this is what the entire area of London looks like through the lens of Strava data:

In [30]:
r_src =
f, ax = plt.subplots(1, figsize=(12, 12))
rioshow(, ax=ax)