Using OSM Data
An overview of using OpenStreetMap data in your applications
Building applications with map data
What is OpenStreetMap?
OpenStreetMap is a free database of labelled map data with over 9 billion labelled features. It’s used to power navigation apps, search for nearby restaurants and shops, finding campsites near National Parks, and infinitely more use cases.
Most of the web maps you see online are built entirely from OpenStreetMap data. One rule of thumb is if you can see it in person, it’s labelled on OpenStreetMap. The above picture shows a map of downtown San Francisco, where the following were extracted from OSM’s database:
- Highway, roads, and bridges
- Building outlines
- Coastline and parks
Finding the correct tags
Each feature in OpenStreetMap is tagged, often 10+ times. Each tag is a key and value combination in the form key=value
.
For example, the above features could be tagged:
highway=primary
,highway=residential
,man_made=bridge
building=*
natural=coastline
,leisure=park
We use *
(asterisk) to signal any value should be accepted. This is especially useful for buildings,
where building=yes
and building=house
could both be drawn as buildings, and names, to filter out
unnamed items for labelling.
Finding the right combination of tags for the features you want to download starts with searching the TagInfo website for your target feature.
To help users find the right tag inside your application, you can embed an OpenStreetMap tag search in your map. This lets users search “National Park” and get served potential OSM tags that are relevant to their query.
Download features as GeoJSON
Once you’ve identified the right tags, you can download the features in an area.
One type of feature you might want to download from OSM is hiking trails near a user. We
can get a list of walking paths by exporting from OpenStreetMap with the
tag highway=path
and filter for named hiking trails
by also asking for
name=*
.
We can download features by hitting the OSM extract API with our tags highway=path&name=*
.
Here’s an example searching in Australia’s state of Tasmania:
curl --get 'https://osm.buntinglabs.com/v1/osm/extract' \
--data "tags=highway%3Dpath%26name%3D*" \
--data "api_key=demo" \
--data "bbox=142.987061,-43.874138,149.370117,-39.104489"
This will give us a GeoJSON FeatureCollection, which has an array of features.
Here’s a sample with the capital of Tunisia:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "Tunis"
},
"geometry": {
"type": "Point",
"coordinates": [10.181667, 36.806389]
}
},
// ... more features
]
}
features
is an array of the downloaded features. Here’s one of those features from our hiking trail extract,
the “Wilson Bight Track” hiking trail in Tasmania, Australia:
{
"type": "Feature",
"properties": {
"highway": "path",
"name": "Wilson Bight Track",
"operator": "Parks and Wildlife",
"source": "GPS",
"surface": "sand"
},
"geometry": {
"type": "MultiLineString",
"coordinates": [[
[146.1334686279297, -43.51723861694336],
[146.1333770751953, -43.51741027832031],
[146.13339233398438, -43.51757049560547],
[146.13345336914062, -43.51802444458008],
[146.13352966308594, -43.518333435058594],
[146.13360595703125, -43.51850128173828],
[146.12998962402344, -43.51995086669922],
[146.12889099121094, -43.52079772949219]
]]
}
}
This feature, like all features in our API, comes formatted as a GeoJSON. GeoJSON is
a common JSON-derived geospatial feature format. Each feature object denotes an individual point, area, or line
on the Earth’s surface. It comes with a number of properties
as a JSON dictionary. Keys are typically lowercase
and describe the geometry’s purpose on the map. The geometry contains coordinates in (longitude, latitude) order.
Mapping the features
If you are downloading these features to a browser, we recommend using the MapLibre project because it’s free and open source.
Here’s an example of rendering our downloaded features in the map. This could be useful for dynamically rendering features near a user.
Building the map
First, we’ll create a map. You can follow the MapLibre quickstart here.
// Create the map
var map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [146.1333770751953, -43.51741027832031],
zoom: 5
});
Adding our hiking trails
We can insert the hiking trail GeoJSON we downloaded above directly as a GeoJSON source
:
map.on('load', function () {
// Show the hiking trail on top of the map
map.addSource('hiking_trails', {
'type': 'geojson',
'data': {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"highway": "path",
"name": "Wilson Bight Track",
"operator": "Parks and Wildlife",
"source": "GPS",
"surface": "sand"
},
"geometry": {
"type": "MultiLineString",
"coordinates": [[
[146.1334686279297, -43.51723861694336],
[146.1333770751953, -43.51741027832031],
[146.13339233398438, -43.51757049560547],
[146.13345336914062, -43.51802444458008],
[146.13352966308594, -43.518333435058594],
[146.13360595703125, -43.51850128173828],
[146.12998962402344, -43.51995086669922],
[146.12889099121094, -43.52079772949219]
]]
}
}]
}
});
// Draw it as a line
map.addLayer({
'id': 'hiking_trails_as_line',
'type': 'line',
'source': 'hiking_trails',
'layout': {},
'paint': {
'line-color': '#00008B',
'line-opacity': 0.8
}
});
});
Finally, because MapLibre doesn’t render it automatically, we’ll draw it as a line.
Attribution
Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.