Back to the blog

Generating a global hillshade from SRTM data (DEM → WebP tiles)

Digital elevation models (DEM) represent the shape of the terrain. One of the most widely used representations in cartography is the hillshade, which simulates the shadows cast by the relief to give a sense of volume.

In this article, we will see how to generate a global or regional hillshade from SRTM data, then convert it into WebP raster tiles that a web map server can serve.

The method is inspired by the following project:
https://github.com/nst-guide/terrain

Today, much of the world topography used in web applications is generated from SRTM30 data. The same elevation data is also used to generate contour lines.

 

1. Downloading the topographic data

Terrain data mainly comes from:

  • SRTM (Shuttle Radar Topography Mission)

  • EU-DEM for Europe

In this guide, we will use SRTM GL1 (30 m resolution).

The data used to be available directly from NASA, but that service is no longer reachable. It is now available through OpenTopography.

Metadata:

https://portal.opentopography.org/datasetMetadata

To download a specific area only:

https://dwtkns.com/srtm30m/

Available resolutions

  • SRTM GL3: 90 m resolution

  • SRTM GL1: 30 m resolution (about 126 GB in total)

The data is stored on OpenTopography’s S3-compatible storage.

 

Installing the AWS CLI

To download the data from the S3 bucket:

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

Then go to the destination directory and run:

aws s3 cp s3://raster/SRTM_GL1/ . --recursive --endpoint-url https://opentopography.s3.sdsc.edu --no-sign-request

This command downloads:

  • all the SRTM TIF files

  • the global VRT file

The VRT file uses -32768 for areas without data (NoData).

 

Plan your own route

MapPlanner helps you calculate distances, elevation, duration and plan your hikes, runs and bike rides on an interactive map.

  • Automatic distance & elevation calculation
  • Topographic, satellite maps
  • GPX/KML export for your GPS
  • Real-time GPS tracking

2. Installing the required tools

SRTM data comes as GeoTIFF.
To use it in a web map application, you need to:

  1. reproject it

  2. turn it into raster tiles

  3. encode them as WebP

Several tools are needed.

 

Installing GDAL

GDAL is the reference library to handle raster and vector data.

sudo apt-get install gdal-bin

Installing rio-rgbify

rio-rgbify (developed by Mapbox) converts elevation data into raster tiles that map rendering engines can use.

git clone https://github.com/mapbox/rio-rgbify.git
cd rio-rgbify

One file needs a fix:

nano ./rio_rgbify/mbtiler.py

Replace the line that calls transform_bounds with:

w, s, e, n = transform_bounds(*[src_crs, "epsg:4326"] + bbox, densify_pts=2)

Then install the package globally.

sudo apt install python3-pip python3-setuptools
sudo python3 setup.py install

 

3. Building a global VRT

When the data is split across many GeoTIFF files, it is convenient to create a VRT (Virtual Raster).

A VRT acts as a virtual mosaic of all the raster files.

gdalbuildvrt -vrtnodata -32768 SRTM_GL1_srtm.vrt SRTM_GL1_srtm/*.tif

Here:

  • -vrtnodata -32768 sets the NoData value

  • all the .tif files are combined into a single virtual raster

 

4. Reprojecting the data

For web use (with Mapbox GL or MapLibre in particular), the data must be projected to EPSG:3857 (Web Mercator).

SRTM data is in WGS84 (EPSG:4326):

gdalwarp -of VRT -r cubicspline -s_srs EPSG:4326 -t_srs EPSG:3857 -dstnodata 0 SRTM_GL1_srtm.vrt SRTM_GL1_srtm_3857.vrt

Explanation:

  • -of VRT: the output stays a virtual raster (no data is copied)

  • -r cubicspline: interpolation for a smoother result

  • -s_srs: source coordinate system

  • -t_srs: target projection

  • -dstnodata 0: value for empty areas

 

5. Generating the MBTiles raster tiles

The data must now be turned into pyramidal raster tiles.

rio rgbify generates an MBTiles file holding the tiles directly.

rio rgbify -b -10000 -i 0.1 --min-z 6 --max-z 12 -j 22 --format webp SRTM_GL1_srtm_3857.vrt data_hillshade_12.mbtiles

Main parameters:

  • --min-z 6: minimum zoom

  • --max-z 12: maximum zoom

  • -j 22: parallelism

  • --format webp: tile compression

  • -b and -i: elevation encoding parameters

 

6. Generating by region

To avoid overly heavy runs, the data can be generated region by region.

Each region produces an MBTiles file, and all the files can then be merged with tile-join (shipped with tippecanoe):

tile-join -pk -o europe.mbtiles *.mbtiles

Option:

  • -pk: stops the tool from dropping tiles larger than 500 kB

 

7. Performance and required resources

Generation time

  • North America:

    • 40 GB of RAM

    • 15 h of generation

    • 11 processes

  • Whole world:

    • 37 h

    • 12 processes

    • up to 200 GB of RAM

 

Disk space

For a global run:

  • final MBTiles: 182 GB

  • unpacked WebP: 208 GB

  • number of tiles: 8,940,823

 

8. Tileserver limits

A global MBTiles file is too large for tileserver to serve efficiently.

The solution is to extract the raster tiles into a file tree.

 

9. Unpacking the MBTiles into WebP tiles

Install mb-util.

git clone https://github.com/mapbox/mbutil.git
cd mbutil
sudo python3 setup.py install

Unpack the tiles:

mb-util data_hillshade_12.mbtiles tiles --image_format=webp

Resulting structure:

tiles/{z}/{x}/{y}.webp

 

10. Deploying the tiles to the server

Copy the tiles into:

/home/www/hillshade/data

Then create a TileJSON file.

nano /home/www/hillshade/data/data_hillshade_12.json

Content:

{
  "tiles": ["https://hillshade.example.com/data/{z}/{x}/{y}.webp"],
  "name": "SRTM Hillshade 30m WEBP",
  "format": "webp",
  "basename": "data_hillshade_12",
  "id": "data_hillshade_12",
  "description": "SRTM Hillshade 30m WEBP",
  "version": "1",
  "type": "baselayer",
  "minzoom": 6,
  "maxzoom": 12,
  "center": [2.8125, 46.779279304705625, 9],
  "attribution": "SRTM",
  "tilejson": "2.0.0"
}

This file describes:

  • the tile URL

  • the zoom levels

  • the metadata

 

11. Configuring the web server (Caddy)

Example Caddy configuration:

sudo nano /etc/caddy/Caddyfile

Configuration:

hillshade.example.com {
        root * /home/www/hillshade

        file_server

        header {
                Access-Control-Allow-Origin "*"
                Access-Control-Allow-Methods "POST, GET, OPTIONS, PUT, DELETE"
                Access-Control-Allow-Headers "*"

                X-Content-Type-Options nosniff
                X-XSS-Protection "1; mode=block;"
                X-Robots-Tag none
                X-Frame-Options SAMEORIGIN

                Cache-Control "public, max-age=5184000"
        }

        @blocked {
                path *.mbtiles
        }
        respond @blocked 403

        # encode gzip

        log {
                output file /var/log/caddy/maps_access.log
        }
}

This configuration:

  • serves the static tiles

  • enables browser caching

  • blocks direct access to .mbtiles files

 

12. Adding the source in Maputnik to check

In Maputnik, add a source of type:

Raster DEM

with the TileJSON URL, served by the domain declared in the Caddyfile:

https://hillshade.example.com/data/data_hillshade_12.json

The tiles can then be used for:

  • dynamic hillshading

  • relief rendering

  • terrain analysis

Related articles

What our Explorer users say

⭐⭐⭐⭐⭐

I planned a 5-mile running loop around my neighborhood in minutes. The distance and pace estimate were spot on for my morning run before work.

Sarah K. New runner
⭐⭐⭐⭐⭐

With the isochrone mode, I plan my hikes in no time! I instantly see how far I can go with my available time. GPS tracking keeps me on trail in the Rockies.

Jessica W. Passionate hiker
⭐⭐⭐⭐⭐

We prepared a 25-mile cycling loop with friends and exported the GPX track. Everyone followed the same route on their Garmin without getting lost. Perfect organization!

Mike R. Weekend cyclist
⭐⭐⭐⭐⭐

Before a hike in Shenandoah, I checked the elevation and duration. The route followed real trails, which saved me from unpleasant surprises. Very reliable!

Emily L. Beginner hiker
⭐⭐⭐⭐⭐

I wanted an easy walk for my kids. I set a short max distance and MapPlanner helped me create the perfect loop. We had a wonderful family afternoon.

David N. Family outing
⭐⭐⭐⭐⭐

I love planning my outings in advance. I saved several routes for the weekends. It saves me so much time compared to figuring it out on the go.

Karen G. Occasional hiker
⭐⭐⭐⭐⭐

By exploring the routes around my area, I discovered great trails I didn’t know about. MapPlanner opened new places for me to explore right in my backyard.

Chris P. Trail discovery
⭐⭐⭐⭐⭐

I keep track of my progress with the history feature. Comparing my running pace and distance over the months keeps me motivated and accountable.

Ashley T. Performance tracking
⭐⭐⭐⭐⭐

For our MTB group ride, we created the route and sent the GPX to everyone. Nobody got separated — the whole group stayed together from start to finish.

Brian B. Club activity
⭐⭐⭐⭐⭐

I love taking photos while hiking. MapPlanner automatically places my pictures on the map. It’s awesome to review the route and share it with friends.

Lauren F. Discovery outing
⭐⭐⭐⭐⭐

Depending on the activity, I switch the map style: topo for the mountains, street for the city, satellite to scout terrain. It makes route planning super intuitive.

Tyler S. Experienced hiker
⭐⭐⭐⭐⭐

MapPlanner now estimates my times based on my own pace. I know exactly how long my next run will take. Perfect for squeezing in a workout on a tight schedule.

Rachel J. Aspiring runner

Popular routes

Discover the most popular routes near you

Miles at the Meadow - 5k / 10K (2 loops)
pete.augrom
Running
Very easy

Miles at the Meadow - 5k / 10K (2 loops)

3.095mi
•
33m
•
5.63mph
Virginia - The Plains
Fusion Invitational High School 5K Course
nm8zkrv8hk
Running
Easy

Fusion Invitational High School 5K Course

3.201mi
•
34m
•
5.65mph
Colorado - Commerce City
ada
rajan
Running
Strenuous

ada

11.669mi
•
4h10m
•
2.8mph
New York - New York
Route 2 - Prayer Walk Connecting Churches (Ferguson)
SR St. Louis
Walk
Very easy

Route 2 - Prayer Walk Connecting Churches (Ferguson)

1.441mi
•
31m
Missouri - Ferguson
2026 HHHH 25mi Route
buschlive
Bike
Moderate

2026 HHHH 25mi Route

24.79mi
•
2h30m
•
9.92mph
Texas - Hutchins
Central park
Fibula
Running
Moderate

Central park

6.393mi
•
1h
•
6.39mph
New York - New York
Miles at the Meadow - 1 mile
pete.augrom
Running
Very easy

Miles at the Meadow - 1 mile

1.012mi
•
11m
•
5.52mph
Virginia - The Plains
Chincoteague National Wildlife Refuge
Gaynor
Bike
Very easy

Chincoteague National Wildlife Refuge

9.532mi
•
2h
•
4.77mph
Virginia - Chincoteague Island