Build a Park Bench Finder App

Show visitors exactly where they can sit in any park using live OpenStreetMap data. This is the simplest possible MapLark query - a single API call returns all benches in a bounding box as GeoJSON points, ready to place on any map.

type=nodeamenity=benchbounding boxPython

What you'll build

A function that queries the MapLark API for benches in a given area and returns their coordinates as an array of [lon, lat] pairs. You can pass these directly to any map library (Leaflet, Mapbox, Google Maps) to render pin markers. The same pattern works for any point-type OSM feature - bins, bike racks, drinking fountains, ATMs - just change the tags parameter.

Prerequisites

Run these commands on a Bash terminal.

Python
pip install osmfeatures

Script

View full source code: test_park_bench_finder.py

Python
"""
App idea: show benches on a park map so visitors know where to rest.

Djurgården is Stockholm's main recreational island; it has many benches.

API call: ``type=node&tags=amenity=bench``
"""

from osmfeatures import OSMFeature, OSMFeatureCollection, OSMFeaturesClient

DJURGARDEN_BBOX = "18.090,59.320,18.170,59.345"


def test_park_bench_finder(client: OSMFeaturesClient):
    data = client.query(bbox=DJURGARDEN_BBOX, type="node", tags="amenity=bench", limit=200)
    assert isinstance(data, OSMFeatureCollection)
    assert len(data["features"]) > 0, "Expected bench nodes in Djurgården"

    # All features must be Point nodes with the correct tag
    for f in data["features"]:
        assert isinstance(f, OSMFeature)
        assert f.osm_type == "node"
        assert f["geometry"]["type"] == "Point"
        assert f.tags.get("amenity") == "bench"
        # Nodes are already points - no centroid needed
        assert f.centroid is None

    # Extract lon/lat to demonstrate placing map markers
    bench_coords = [f["geometry"]["coordinates"] for f in data["features"]]
    assert all(len(c) == 2 for c in bench_coords)

    lons = [c[0] for c in bench_coords]
    lats = [c[1] for c in bench_coords]
    # Sanity-check all coordinates fall inside Stockholm
    assert all(17.5 < lon < 18.5 for lon in lons)
    assert all(59.0 < lat < 60.0 for lat in lats)

    print(f"\n[bench finder] {len(bench_coords)} benches found in Djurgården")

How it works

The query uses three parameters to narrow results to exactly the features you need. All three are passed as URL query parameters to GET /v2/osm_features.

ParameterValueWhat it does
bboxmin_lon,min_lat,max_lon,max_latSpatial anchor - restricts results to a rectangular area. Required when using tag filters.
typenodeReturns only point-type OSM features. Benches are always nodes, so this keeps the response lean.
tagsamenity=benchExact tag match using OSM's native key=value schema. Only features with this exact tag are returned.
limit200Maximum features to return per page. Use X-Has-More and X-Next-Cursor (or SDK meta) to paginate.
Node geometry: Point nodes never include a centroid in their properties - the geometry.coordinates is already the pin location. The centroid field only appears on non-point features (ways, polygons, relations) as a convenience for placing map markers without computing a centroid yourself.

Adapt it

The same one-liner pattern works for any OSM amenity node. Swap the tags value to find other point features in any area:

Tags valueWhat you get
amenity=waste_basketPublic bins / litter baskets
amenity=bicycle_parkingBike parking spots
amenity=drinking_waterPublic drinking fountains
amenity=atmATM machines
tourism=viewpointScenic viewpoints
natural=treeIndividual mapped trees

Try it live

Paste your API key into the Authorize button and run this query against real Stockholm data.