Donate using PayPal

CycleStreets API (v2)

  • Details for:
  • API overview
  • Obtain API key
  • Usage policy
  • Uptime policy

Photomap locations

The photomap locations API retrieves photos of categorised cycling-related infrastructure from a specified geographical area which have been submitted by users. The same data is visible on our Photomap.

As well as this call, a single-location equivalent is available as the photomap.location call.

Each location has various metadata attached to it, such as a caption, a category (e.g. cycleparking/obstruction/etc.), a metacategory (e.g. good/bad), date/time, location, and more.

You can retrieve arbitrary metadata fields added to a location using additionalMetadata. This could be useful for auditing and similar uses.

Note that each location has a license (e.g. Creative Commons, Public Domain, No reproduction permitted, etc.) as specified by the contributor. You are required to respect the specified license. Also, CycleStreets naturally has a database right in the collective dataset.

Not all locations have a photo attached to them. Such 'placeholders', however, do contain the other metadata.

The data is optimised to give an even spread within a map view when there would be too many to show at the current zoom level. To do this, it breaks the visible map into a 10x10 grid and chooses one photo from each grid cell.

Example

Example which returns problem cycle parking locations in an area of Cambridge.

(In this example, a limit of only 3 locations has been set, to avoid a long example on this page, but normally a limit of perhaps 150 would be appropriate for web viewing.)

https://api.cyclestreets.net/v2/photomap.locations?category=cycleparking&metacategory=bad&limit=3&fields=id,hasPhoto,thumbnailUrl,license,caption&bbox=0.1456,52.1990,0.1487,52.2006
https://api.cyclestreets.net/v2/photomap.locations?category=cycleparking&metacategory=bad&limit=3&fields=id,hasPhoto,thumbnailUrl,license,caption&boundary=[[0.145246,52.199900],[0.146663,52.200873],[0.148401,52.200189],[0.147156,52.198808],[0.145246,52.199900]]

Result:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "properties": {
                "id": 10289,
                "hasPhoto": "yes",
                "thumbnailUrl": "https://www.cyclestreets.net/location/10289/cyclestreets10289-size200.jpg",
                "license": "cc-by-sa",
                "caption": "Complete lack of cycle parking on the highway forces cyclists to do this sort of thing. The pavement is totally blocked."
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    0.146092,
                    52.199314
                ]
            }
        },
        {
            "type": "Feature",
            "properties": {
                "id": 23583,
                "hasPhoto": "no",
                "thumbnailUrl": null,
                "license": "publicdomain",
                "caption": "A lot of residents in side streets off Mill Road use bicycles as their primary means of transport. Converting a few car parking spaces into bicycle parking would be enormously helpful, since current bicycle parking provisions are virtually non-existent."
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    0.147658,
                    52.200581
                ]
            }
        },
        {
            "type": "Feature",
            "properties": {
                "id": 53500,
                "hasPhoto": "yes",
                "thumbnailUrl": "https://www.cyclestreets.net/location/53500/cyclestreets53500-size200.jpg",
                "license": "publicdomain",
                "caption": "No home for bikes on a street dominated by car storage."
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    0.14748,
                    52.1996
                ]
            }
        }
    ]
}

Request parameters - required

You must supply either a bounding box or an exact boundary:

bbox csv string of longitude/latitudes: w,s,e,n
A bounding box string as w,s,e,n in which the locations must reside. Locations will be spread evenly around this bounding box.

or

boundary string

A boundary string in which the locations must reside.

The order for each location pair is longitude,latitude.

Request parameters - optional

It is strongly recommended to specify a fields list, so that clients receive exactly the data they need.

fields string, comma-separated list of fields from the list below,
  default id,latitude,longitude,caption,hasPhoto,thumbnailUrl,username,licenseName

Controls what information is returned for each location. It is strongly recommended to send this, so that clients receive exactly the data they need.

Available fields are listed below.

If fields is not supplied, the default is used, which represents a sensible and useful set of fields.

The fields id,latitude,longitude,caption are always returned.

When the data is returned in the geojson format, the values for latitude,longitude appear only in the /geometry/coordinates field rather than being duplicated in the properties list.

Fields are returned in the ordering specified by the caller, which can be useful when using format=csv.

Unrecognised fieldnames are simply ignored rather than an error being thrown.

category string
Filter to locations with the specified category, e.g. cycleparking. The values for category [see examples] can be found using the photomap.categories API call.
metacategory string
Filter to locations with the specified metacategory, e.g. bad. The values for metacategory [see examples] can be found using the photomap.categories API call.
limit int, max 400
Maximum number of locations returned. It is strongly recommended to use this parameter. A value of 25 is recommended for mobile apps, and 150 for desktop apps. Photos will be spread evenly around the viewport where possible. There is a limit of 400.
suppressplaceholders int (0|1), default 0
Suppress locations that have no attached image. Recommended for mobile apps.
thumbnailsize int 60|120|150|180|200|250|300|350|400|425|450|500|640|800|1000|1200|1500|1800|2000 (default 425)
The thumbnail size used in the thumbnail URLs shown within the data. At present, only the stated sizes are supported; however we plan to remove this limitation shortly; for now, if you require another size, please let us know and we will add it as a supported size. If an unsupported size is specified, the default (425) is currently returned.
iconset string cyclestreets|camcycle (default cyclestreets)
Specifies the style of the icons.
iconformat string svg|png|@2x.png (default svg)
Format of icons, if specifying iconProperties/iconLocation/iconUrl in the fields list. For retina displays, use a value containing @2x. (Please note that the camcycle iconset supports only png and the API will respond with an error if a different format is requested.)
urlprefix string
If set, this will prefix the supplied string to URL-related fields. Currently only iconProperties->iconUrl and iconProperties->shadowUrl is affected but other fields will have support for this in due course.
selectedid int
If supplied, this location ID will be included as an extra result, if it exists, irrespective of the bounding box or any other conditions, and is additional to the limit if set. This parameter is useful if, after adding a location using photomap.add, you wish to show the map again with the just-uploaded item shown, or if you wish to start the map at a certain location. If it does not exist, this will not cause an error to be thrown.
since int
If supplied as a Unixtime value, this will limit locations to be at least this time.
tags string
Limit to a specific tag. Currently only a single tag is supported.
username string
If supplied, locations will be limited to those contributed by this username. If the username does not exist, no results will be returned but no error will be thrown.
format string, default geojson

Sets the output format. Not normally required except in the use-case of requiring an export. The appropriate HTTP headers will be sent. Available values are:

  • geojson: GeoJSON output (see example) (default)
  • csv: CSV text. If set to this, the specified fields order will be respected.
datetime string

If specified, the datetime field (if requested in the fields list) will be converted from unixtime (the default output format) to a formatted version; the available output formats are:

  • friendly A friendly format suitable for showing on a webpage, e.g. '6:55pm, 4th October 2013'; this is equivalent to date ('g:ia, jS F Y', $date) in PHP
  • friendlydate A friendly date format suitable for showing on a webpage, e.g. '4th October, 2013'; this is equivalent to date ('jS F, Y', $date) in PHP
  • sqldatetime SQL DATETIME format (i.e. simplified ISO 8601 format): YYYY-MM-DD HH:MM:SS
  • unixtime Unixtime (the default)

Fields available

The available fields are as follows:

(These are shown grouped for clarity; the groupings themselves are not part of the API itself.)

  • Core fields:
    • id: The unique identifier of the location, which will be numeric
    • latitude: Latitude of the location
    • longitude: Longitude of the location
    • caption: Caption (as plain text)
  • Image/video fields:
    • hasPhoto: Whether the location has a photo (boolean true/false)
    • thumbnailUrl: Full URL of the image (thumbnail size)
    • thumbnailLocation: Location of the image (thumbnail size)
    • imageUrl: Full URL of original image file
    • imageLocation: Location of image file (for local use)
    • hasVideo: Whether the location has a video (boolean true/false)
    • videoFormats: Video formats, and their URLs, as an associative array. If not a video, or no videos available, this will be an empty array.
    • type: Type (photo/video/placeholder)
  • Icon (categorisation) fields:
    • iconProperties: Icon details, as an array of icon properties, suitable for direct use in Leaflet.js or adaptable to other libraries
    • iconLocation: Location of category icon image file
    • iconUrl: Full URL of category icon image file
  • Categorisation fields:
    • categoryId: The category identifier (which will match category=... if set) (e.g. 'obstructions')
    • categoryName: Category name (e.g. 'Obstruction')
    • categoryPlural: Category name, pluralised (e.g. 'Obstructions')
    • categoryDescription: Category description (e.g. 'A narrow place, difficult for cycles to pass.')
    • metacategoryId: The metacategory identifier (which will match metacategory=... if set) (e.g. 'bad')
    • metacategoryName: Metacategory name (e.g. 'Problem')
    • metacategoryDescription: Metacategory description (e.g. 'A problem that needs to be fixed')
    • categoryLink: Location of category/metacategory page
  • Date/time field:
    • datetime: Time when the photo was taken; the format of this can be set using datetime=... as documented above
  • User/credit/licensing fields:
    • username: Username of the user who submitted the location
    • usernameWithImportingHtml: Username of the user who submitted the location, with importing details, as HTML
    • userProfileUrl: URL of the user profile of the user who submitted the location
    • credit: Credit (e.g. username of Flickr user, if image imported); often empty
    • creditUrl: URL relating to credit (e.g. Flickr user page, if image imported); often empty
    • sourceUrl: URL of source image (if imported, e.g. from Flickr)
    • license: License identifer
    • licenseName: License name
    • licenseUrl: License URL
    • editRights: Indicates whether the user has edit rights; not yet implemented
  • Social field:
    • likes: The number of submitted 'Likes'
  • URL fields:
    • url: Full URL of location page on the CycleStreets website
    • shortlink: Shortlink URL of location page on the CycleStreets website
    • apiUrl: URL of API URL of the location
    • dayLink: Location of link to photos taken the same day of the year
  • Geography fields:
    • zoom: Map zoom of the location at the time of saving
    • basemap: Basemap (as identifier) used at the time of saving
    • areaName: Name of the Local Authority
    • areaSubdomain: Area subdomain on CycleStreets website
    • areaCountry: Area country
    • photomapletLocation: Location of maplet image; subject to change
    • nearbyStreets: Nearby streets; currently disabled, pending performance work
  • Detail fields:
    • bearing: Bearing
    • bearingString: Bearing, as a string, with the first letter capitalised (e.g. 'North west')
    • azimuth: Azimuth
    • elevation: Elevation
    • elevationString: Elevation, as a string (e.g. '2m above ground')
    • proximity: Proximity
  • Caption (more) fields:
    • captionHtml: Caption, as HTML
    • title: Title, currently emulated from the start of the caption
  • Pagination fields:
    • previous: Previous image, numerically
    • next: Next image, numerically
  • Grouping fields:
    • tags: Tags, as an array
    • galleryMembershipHtml: Gallery membership, as HTML; not yet implemented
  • Extensible metadata field:
    • additionalMetadata: A special field which acts as an expandable container - see the section below which explains its handling.

The additionalMetadata field

Sometimes, a client application may wish to capture from users additional metadata that is not currently supported in the standard list of fields. For instance, a client may wish to capture the number of cycle parking spaces at a location, or land ownership details.

In this circumstance, data can be submitted and retrieved using the additionalMetadata field. The data is stored in this field as key/value string pairs, and is not indexed in the sense of being searchable by a key or value.

You can limit the specific key fields you want returned by specifying the field(s) as additionalMetadata[subfield1,subfield2,...].

When using format=csv, and including fields=additionalMetadata, you must specify the required subfield(s) as fields=additionalMetadata[subfield1,subfield2,...], as otherwise the CSV output could potentially contain an inconsistent number of columns.

additionalMetadata Example 1: The following example includes the additionalMetadata field.

The effect of this is that those subfields which do exist in the data are returned, or where no metadata is available the value is null.

https://api.cyclestreets.net/v2/photomap.locations?category=cycleparking&fields=id,latitude,longitude,caption,additionalMetadata,datetime,shortlink&bbox=-0.489,51.28,0.236,51.686&limit=3&datetime=sqldatetime

Result:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "properties": {
                "id": 57141,
                "caption": "Cycle parking needed",
                "additionalMetadata": {
                    "landtype": "highway"
                },
                "datetime": "2014-03-18 13:33:55",
                "shortlink": "http://cycle.st/p57141"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    0.077049,
                    51.620388
                ]
            }
        },
        {
            "type": "Feature",
            "properties": {
                "id": 56208,
                "caption": "12 stands needed",
                "additionalMetadata": null,
                "datetime": "2014-01-16 18:06:39",
                "shortlink": "http://cycle.st/p56208"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -0.003292,
                    51.462429
                ]
            }
        },
        {
            "type": "Feature",
            "properties": {
                "id": 57143,
                "caption": "test",
                "additionalMetadata": {
                    "landtype": "highway",
                    "capacity": "2"
                },
                "datetime": "2013-04-25 10:02:10",
                "shortlink": "http://cycle.st/p57143"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -0.163186,
                    51.523872
                ]
            }
        }
    ]
}

additionalMetadata Example 2: This example includes the additionalMetadata field but specifying the required subfields that the client believes are likely to be present (e.g. because the application commonly adds locations with such subfields).

The effect of this is to promote the subfields to be real fields, but capitalised to avoid the potential for clashes with standard fields. If a subfield is not present in a record, its key will still be present in the result, but set to NULL as the value.

https://api.cyclestreets.net/v2/photomap.locations?category=cycleparking&fields=id,latitude,longitude,caption,additionalMetadata[landtype,capacity],datetime,shortlink&bbox=-0.489,51.28,0.236,51.686&limit=3&datetime=sqldatetime

Result:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "properties": {
                "id": 58827,
                "caption": "Incredible there is now such a large amount of space, but no cycle parking. A sign of a modern city is the presence of plenty of cycle parking at a station.",
                "Landtype": "highway",
                "Capacity": "200",
                "datetime": "2014-05-16 17:58:40",
                "shortlink": "http://cycle.st/p58827"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -0.123687,
                    51.53035
                ]
            }
        },
        {
            "type": "Feature",
            "properties": {
                "id": 30754,
                "caption": "The supermarket have provided good cycle parking outside their store, but as this picture clearly shows they need to provide more!",
                "Landtype": false,
                "Capacity": false,
                "datetime": "2011-03-12 17:04:53",
                "shortlink": "http://cycle.st/p30754"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -0.399704,
                    51.658985
                ]
            }
        },
        {
            "type": "Feature",
            "properties": {
                "id": 39233,
                "caption": "Segregated cycle lanes in both directions along King Henry's Drive",
                "Landtype": false,
                "Capacity": false,
                "datetime": "2012-06-10 13:48:02",
                "shortlink": "http://cycle.st/p39233"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -0.024977,
                    51.352341
                ]
            }
        }
    ]
}

Response

GeoJSON feature list as per example above. Geometry types will always be Point.

(If format has been specified, the relevant format will be returned instead.)

Example with no locations in an area:

{
    "type": "FeatureCollection",
    "features": [

    ]
}

Error response

JSON object containing an error key and a text string.

Even if format=... is specified, the error response will still be a JSON object, as shown below.

Example errors (text string will vary):

{
    "error": "Neither a bbox nor a detailed boundary have been supplied."
}
{
    "error": "The category is not valid"
}

We welcome your feedback, especially to report bugs or give us route feedback.

My comments relate to: *






Your comments: *
URL of page: * https://portsmouth.cyclestreets.net/api/v2/photomap.locations/
How did you find out about CycleStreets?:
Your name:
Our ref: Please leave blank - anti-spam measure

* Items marked with an asterisk [*] are required fields and must be fully completed.