Where’s My Data? How to Retrieve Mapillary Images to Use in External Tools
Mapillary is a powerful platform for capturing, uploading, and viewing your own street-level imagery. While our web platform allows you to explore photos from your own activities as well as those of other contributors, it doesn’t enable you to perform more advanced custom functions and analyses. For this, there are other tools, and you can get a copy of your data on Mapillary to use with those. For example:
- As a map editor, you may want to get your tracks in order to project them on OpenStreetMap, share on Twitter, show in a meetup group, or otherwise share the data.
- As an aid worker or NGO employee, you may be interested in not only the photos but new routes you’ve mapped in previously uncharted areas.
- As a GIS analyst, you may want to work with the locations of your images and sequences in software such as ArcGIS or QGIS, in order to compare them against other data.
- As a content or product manager, you may want to acquire map data for your own platform, using the Mapillary points and linestrings as new data.
- As an engaged citizen, you may want to map a trail or road where you’re biking, hiking, or otherwise pursuing an outdoor activity or challenge that you’d like to map for public use.
Does one of these scenarios sound like you? Maybe you have an entirely different motivation and role, but nonetheless, our data is here for you in a widespread format called GeoJSON
, which you can retrieve using our API. In this tutorial, we will demonstrate how easy this is and guide you through the process, step by step.
Access the Mapillary API
In order to access any Mapillary data you will need to access the Mapillary API. To start using the Mapillary API, you need an access token called a client_id
. It can be generated after signing up with just few clicks. The client_id
is generated by registering an application. You can manage your applications in your settings page. To get started, make sure you’re logged in to your account, then follow the steps below.
- The first step in getting your
client_id
is to visit your settings page. - Next, you will register an application. You can name the application “API access” or anything else you like. For the company name and website, callback URL, and description, you can enter anything you like.
- Then, click register and your application will be created.
- To retrieve your
client_id
, simply click the clipboard icon beside it under your new application listing. - You can now access the API. Keep this
client_id
at hand as we go forward.
Now that we’ve solved that, it’s time to learn about the Mapillary API. In our API, we use what are called geographic data resources. These come in the form of a GeoJSON containing geographic data points and linestrings. A single resource can be represented by a GeoJSON Feature
, whereas a collection of resources can be represented by a GeoJSON FeatureCollection
. Unless explicitly stated otherwise, our spatial data uses WGS84 (or EPSG:4326) as the reference coordinate system. Coordinates follow the order longitude
, latitude
(i.e. x
, y
).
Search images
In the first example, we’ll assume that you want to find all geographic data for the images near your local university. In my case, I’m going to find the University of Washington in Seattle by visiting OpenStreetMap and searching its name. Next, I right-click on the university, choose Directions from here
, and see the coordinates in the form of latitude, longitude
reading 47.6537, -122.3079
.
Remember, however, that the Mapillary API requires longitude, latitude
as the order of the input, and so we will need to keep track of this as -122.3079, 47.6537
. This ordering is a standard for GeoJSON files.
You can also get the location by searching on mapillary.com/app, then checking the URL. My URL for the search in the image below is:
https://www.mapillary.com/app/?lat=47.64980300061276&lng=-122.303852&z=19.836305450776447&focus=map
Next, let’s look into the API call we want to make. Because we’re searching for an image, we can reference the Search images
section of our API documentation. Here we can see a list of several filters.
URL Parameter | Type | Description |
---|---|---|
bbox | number[] | Filter by the bounding box, given as minx,miny,maxx,maxy . |
closeto | number[] | Filter by a location that images are close to, given as longitude,latitude . |
end_time | Date | Filter images that were captured before end_time . |
lookat | number[] | Filter images that images are taken in the direction of the specified location (and therefore that location is likely to be visible in the images), given as longitude,latitude . |
radius | number | Filter images within the radius around the closeto location (default 100 meters). |
start_time | Date | Filter images that were captured since start_time . |
userkeys | Key[] | Filter images captured by users, given as userkeys, |
usernames | string[] | Filter images captured_by users, given as usernames. |
Judging by our task, it looks like closeto
fits our need. We’ll start with the standard Search images
API call, but enter your personal client_id
in place of <YOUR_CLIENT_ID>
, removing the <
and >
symbols as well:
https://a.mapillary.com/v3/images?client_id=<YOUR_CLIENT_ID>
Next, we need to add our filter, closeto
. We do this with an &
symbol and the filter name, plus the filter content. For the coordinates of the University of Washington, we need to add &closeto=-122.3079,47.6537
with no spaces. The complete call will look like this:
https://a.mapillary.com/v3/images?client_id=<YOUR_CLIENT_ID>&closeto=-122.3079,47.6537
If I go to this URL, I see the following on my screen, which is an empty GeoJSON:
{"type":"FeatureCollection","features":[]}
This means there are no images near the location I searched! The problem is that we didn’t specify a radius, so the default was used as seen in the table above in the description of what radius
does: Filter images within the radius around the closeto location (default 100 meters).
So now we know that there are no images within 100 meters of our exact point. Let’s change the radius to 200 meters, and try to cast a wider net. We need to add &radius=200
to our API call:
https://a.mapillary.com/v3/images?client_id=<YOUR_CLIENT_ID>&closeto=-122.3079,47.6537&radius=200
Going to this URL again, we get a much longer response with a list of images:
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"ca":137.79929128546348,"camera_make":"samsung","captured_at":"2016-01-17T13:05:47.540Z","key":"hYZH6voFh0VpQ-G3iz1TOQ","pano":false,"user_key":"KtBC-RdGZ5_HU6J4Hhvnmw","username":"natfoot"},"geometry":{"type":"Point","coordinates":[-122.3092632,47.6523645]}},…
Above we see just a part of the return. You can use jsonlint.com to make it more “pretty” for viewing, and see how it is structured:
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"ca": 137.79929128546348,
"camera_make": "samsung",
"captured_at": "2016-01-17T13:05:47.540Z",
"key": "hYZH6voFh0VpQ-G3iz1TOQ",
"pano": false,
"user_key": "KtBC-RdGZ5_HU6J4Hhvnmw",
"username": "natfoot"
},
"geometry": {
"type": "Point",
"coordinates": [-122.3092632, 47.6523645]
}
}, ...
Overall, what you see here is a GeoJSON, where each point is a "
type
"
:
"
Feature
"
and has several properties, including the type of camera, a unique identifier key, and the date of capture. It also has a geometry, specifying the type and the coordinates. You can save this page as mydata.geojson
and load it into QGIS as well as ArcGIS Online. You can also use a tool such as Ogre to convert it to an Esri Shapefile, and use it in ArcGIS Desktop and ArcGIS Pro.
Similar to the above search, we can also trying to find all areas inside a specific box. Let’s say, for example, that we want to find all photos on the campus of the University of Montana. We will need to tell the API to search in a box which we call a bounding box or bbox
in the API. In order to search in a bbox
, we need the geographic coordinates of the lower left and top right corners of that box. You can find these by using the same method on OpenStreetMap, just right-clicking at those two different locations. You can also use a tool like geojson.io to draw a box or place two points, and get their locations from the codebox.
For the University of Montana, the lower left corner of the bbox
is at -113.9893770218955,46.8569923487781
and the top right corner is at -113.9800214767456,46.86501800079085
(to be very, very precise). Don’t worry about dropping a few digits if you aren’t trying to be so exact.
Our API call will start similarly to the closeto
search, but instead we simply add &bbox=-113.9893770218955,46.8569923487781,-113.9800214767456,46.86501800079085
to the end of the starting URL, like this:
https://a.mapillary.com/v3/images?client_id=<YOUR_CLIENT_ID>&bbox=-113.9893770218955,46.8569923487781,-113.9800214767456,
46.86501800079085
Visiting this URL will give us a very large return, so let’s try limiting the number of results to only three points. We need to add &per_page=3
, like below:
https://a.mapillary.com/v3/images?client_id=<YOUR_CLIENT_ID>&bbox=-113.9893770218955,46.8569923487781,-113.9800214767456,46.86501800079085&per_page=3
And the result will show only three points, just like we asked. We can also apply more filters, such as &start_time=2016-03-28
and &end_time=2017-03-28
to get results during a year’s span, or filter by username, such as &usernames=chrisbeddow
to show only results from one user. Multiple users can also be searched, just make a list separated by commas: &usernames=chrisbeddow,gyllen,yourusername,somebodyelse
.
Search sequences
Now that we’ve learned to search images and return points, let’s take a look at linestrings. You can take a look at our documentation on sequence search. The entire search function works almost the same as with image points, except that we just start with a different initial API call:
https://a.mapillary.com/v3/sequences?client_id=<YOUR_CLIENT_ID>
For now, sequences only allow searching by bbox
, closeto
, and userkeys
, but not usernames
or any date filters. For doing a sequence search, let’s take a look at a bbox
around -105.0960087776184,40.567301351105996,-105.07731914520264,40.57799340275122
this time, which is the Colorado State University. Our initial API call will look like this:
https://a.mapillary.com/v3/sequences?client_id=<YOUR_CLIENT_ID>&bbox=-105.0960087776184,40.567301351105996,-105.07731914520264,40.57799340275122
This is searching for sequences, which we call the linestrings made by a series of Mapillary photos. On our map, we can see sequences as green lines through the Colorado State University campus, so our bbox
will capture the information about just those sequences:
A first look at the results yields something like this:
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"camera_make": "LGE",
"captured_at": "2017-04-11T13:42:42.000Z",
"coordinateProperties": {
"cas": [101.5182113647461, 101.44711303710938, 103.955810546875, 109.72040557861328, 115.09485626220703, 111.78319549560547, 88.27569580078125, 64.84099578857422, 32.65742874145508],
"image_keys": ["Mtx4RcyRRKqOCqhgkaLwfw", "wS6ChqIzk2teolDUTnfdWQ", "1WtVK9Vs45FOm_tWsIDCuw", "iBjc5dA2-1kHaCSSePgOvA", "dAsROF04dHMupXVK2iS1ng", "TRB8EM9UtnkjYQCSPlgPNw", "aq5RFJWvpyiHHw6wFCc50w", "n2-cKpdAb-u1sZ8iOredQw", "aCx9C95QqwgHSoaXJXEMbQ"]
},
"created_at": "2017-04-11T12:50:21.216Z",
"key": "ur0cP2qglE9cgWrusMxcYA",
"pano": false,
"user_key": "kSl7O486_cNpmNWltxHL9g"
},
"geometry": {
"type": "LineString",
"coordinates": [
[-0.770169119999991, 53.0460004],
[-0.770247019999942, 53.04598555],
[-0.770333390000019, 53.04596919],
[-0.770433749999938, 53.04594586],
[-0.770539950000057, 53.04591025],
[-0.770744349999973, 53.04582071],
[-0.770949250000058, 53.04574412],
[-0.771169490000034, 53.04575033],
[-0.771366550000039, 53.04583692]
]
}
}
Here we see another GeoJSON, but in a linestring format. The properties are structured similarly, but now include multiple of cas
: camera angles which correspond to the multiple image_keys
that form the waypoints along the line, with their coordinates stored in the geometry, also corresponding in order.
Just like with the points GeoJSON, this one can be saved to disk and used in other applications. Overall, you can get very creative by combining your searches with certain filters, showing only particular geographical areas, choosing unique times of year or even times of day with ISO format. Any API call has a limit of 10,000 returned items, while you’ll need to start using pagination even when you reach over 1000 items.
We also have some examples to help you find inspiration, more of which can be seen in our blog post about the Mapillary API v3. Overall, you should now be well acquainted with how to retrieve point and linestring data form the Mapillary API. If you still have questions, even better! Send us an email or check out our Slack channels at OSM-US and the Spatial Community to get in touch.
Happy mapping!
/Chris