Maplark

From OpenStreetMap Wiki
Jump to navigation Jump to search
View on OSM Apps Catalog  
MapLark
v · d 
Status: Active

Commercial API service providing planet-scale OpenStreetMap feature queries as GeoJSON

Features
Feature Value
Map Display
?
Routing
?
Navigating
?
Tracking
?
Monitoring
?
Editing
?
Rendering
?
Accessibility
?

MapLark is a hosted OSM Features API. It queries OpenStreetMap data by tags and spatial filters, and returns full geometries and tags as GeoJSON, FlatGeobuf, GeoParquet or CSV. The database is PostGIS over a planet-scale import, refreshed weekly. Geometries are unclipped, so the output suits analysis as well as display.

MapLark is a commercial service with a generous free tier that is free forever. The data is OpenStreetMap, licensed under the ODbL; public uses must credit "© OpenStreetMap contributors".

Main features

  • Tag filters in one tags string, with AND, OR, NOT, grouping, numeric comparisons and regular expressions
  • Spatial filters: a bounding box, a radius around a point, or the interior of an OSM way or relation
  • Element and geometry selection: nodes, ways and relations; lines or polygons; length and area limits
  • Lookup by OSM ID for known elements
  • Density grids for heatmaps, returned as GeoJSON bins
  • Counts before download: size a query first, with totals and grouped counts
  • Routing on the OSM walk and bike network: reach areas, paths and optimized tours
  • Output formats: GeoJSON, FlatGeobuf, GeoParquet and CSV, selected with the Accept header

Endpoints

Method and path Purpose
GET /v3/osm_features Features by tags and a spatial filter
GET /v2/osm_features/count Match count and grouped counts
GET /v2/osm_features/density Feature density as grid bins
POST /v1/routes/isochrone Walk or bike reach area from an origin
POST /v1/routes/path Walk or bike path through stops in the given order
POST /v1/routes/optimized_path Walk or bike tour through stops, ordered for shortest length
POST /v1/places/search Places in a box or radius, filtered by tags and opening hours
POST /v1/places/nearby Places ranked nearest-first from a point
GET /v1/places/{osm_type}/{osm_id} One place by its OSM ID

The paginated /v2/osm_features, /v2/osm_features/cost and /v2/osm_features/stats are deprecated. Use /v3/osm_features and /v2/osm_features/count.

Interactive reference docs

Querying

Every request needs an API key, sent as a bearer token:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.maplark.com/v3/osm_features?bbox=18.05,59.33,18.10,59.36&type=way&way_shape=polygon&tags=building"

Spatial filters

  • bbox=min_lon,min_lat,max_lon,max_lat
  • location=lat,lng&radius=metres
  • within=relation/155790 (or way/): only features inside that OSM polygon
  • osm_ids=111,222 for direct lookup; this cannot be combined with a spatial filter or tag filter

A tag filter needs a spatial filter. Bounding-box and radius sizes are capped per tier.

Element type and geometry

type takes node, way, relation, or a comma-separated list. Omitting it returns all three. way_shape is line, polygon or all. Nodes are always points, so type=node ignores way_shape.

Length and area filters apply to line and polygon geometries: min_length_m, max_length_m, min_area_m2, max_area_m2.

Tag filters

The tags parameter takes a boolean expression in one string. Clauses separated by , are ANDed, alternatives separated by | are ORed, parentheses group, and ! negates a clause. Repeating tags also ANDs.

Form Matches
key the key is present
key=value the key has this value
key!=value the key is absent or has another value
key>n, >=, <, <= numeric comparison (encode > as %3E)
key~regex, key!~regex case-sensitive regular expression; must be double-quoted

Examples:

  • Cafes or bakeries: tags=amenity=cafe|amenity=bakery
  • Cycle-permitted lines: tags=highway=cycleway|bicycle
  • Shops that are not supermarkets: tags=shop,!shop=supermarket
  • Grouped OR: tags=(amenity=cafe,wheelchair=yes)|shop=bakery
  • Peaks above 500 m: tags=natural=peak&tags=ele%3E500

Quote values that contain ,, | or &: name="Ben, Jerry's". A regex cannot use an index, so combine it with an indexed tag.

The older or_tags and not_tags parameters are deprecated in favour of tags.

Density

/v2/osm_features/density returns GeoJSON points at snapped grid cells, each with properties.count. It takes the same filters as /v3/osm_features, plus cell_deg (default 0.1). A positive tag filter is required. Empty cells are omitted, and truncated is true when more occupied cells exist than limit.

https://api.maplark.com/v2/osm_features/density?bbox=-26,33,52,72&type=node&tags=place&cell_deg=0.1

Counts

/v2/osm_features/count returns the match total without fetching rows, and group_by returns grouped counts. Use it to size a query before running it.

Response headers

  • X-Returned: number of features in the response
  • X-Has-More: true when the response was cut below your tier's maximum
  • X-Query-Hint: advice on making the query cheaper, when relevant

A match set larger than the tier maximum returns HTTP 400 result_too_large with no partial body.

Routing

The routing endpoints run on the OSM street network. Walking uses the network in both directions. Cycling honours OSM oneway tags. Set the mode with travelMode in the request body: WALK (default) or BICYCLE. Each request body also takes an optional search_buffer_m, which widens the corridor of highways fetched around the request points.

POST /v1/routes/isochrone

Returns the area reachable from one origin within a budget. The budget is either a distance or a time, and exactly one must be given:

  • max_distance_m: reach in metres
  • duration_s: reach in seconds, converted at 1.4 m/s walking or 4.2 m/s cycling

The response is a Polygon or MultiPolygon: a buffered union of the reachable edges, so the blocks inside the reach are holes.

{"origin": {"lon": 18.063, "lat": 59.334}, "duration_s": 600, "travelMode": "BICYCLE"}

POST /v1/routes/path

Returns the walking or cycling route through stops in the order given. It takes 2 to 250 stops. Two stops is a single shortest path. The response is a LineString.

POST /v1/routes/optimized_path

Orders the visit points into a short tour. It takes a start point and 1 to 249 stops; the start must not repeat in stops. Ordering uses nearest-neighbour followed by 2-opt improvement, then a shortest path is computed for each leg. Set loop to true (default) to return to the start, or false for an open route.

Ordering is a heuristic, so the result is short but not guaranteed optimal.

Places

The Places endpoints find points of interest by OSM tag and report their opening hours. A place is a node, or a closed way or relation that carries tags. Polygon places are returned as a point at their centroid. Line-only ways are not places.

Tag filters work as in /v3/osm_features. Each entry in tags is a boolean expression, such as amenity=cafe|amenity=bar.

POST /v1/places/search

Finds places in a bounding box, or in a radius around a point. Use either bbox, or location with radius, not both.

{"location": {"lat": 59.334, "lng": 18.063}, "radius": 500, "tags": ["amenity=cafe|amenity=bar"], "limit": 50}

Parameters:

  • bbox: min_lon,min_lat,max_lon,max_lat
  • location and radius: centre as {"lat", "lng"}, radius in metres
  • tags: list of tag expressions, combined with AND
  • limit: default 100, up to your tier's maximum
  • openNow: return only places known to be open now
  • asOf: evaluate opening hours at this time instead of the current time

The response is a GeoJSON FeatureCollection. Each place with an opening_hours tag has properties.openNow set to true or false. Places without parseable hours have no openNow field, and metadata.evaluated_at gives the time used.

With openNow, places with missing or unparseable hours are excluded, and limit is capped at 1,000. A naive asOf (no offset) is read as local time at the search location. Both openNow and asOf require an opening_hours tag on the place.

POST /v1/places/nearby

Ranks places from a point by straight-line distance, nearest first. It requires tags. radius defaults to 1000 metres.

{"location": {"lat": 59.334, "lng": 18.063}, "radius": 1000, "tags": ["amenity=pharmacy"], "limit": 20}

The response contains items. Each item has a feature and a distance_m, sorted by distance_m. It also reports status and evaluated_at.

The openNow, asOf and limit parameters work as in search. With openNow, the response also reports input_count (places scanned) and kept_count (places known open).

GET /v1/places/{osm_type}/{osm_id}

Reloads one place by the ID that search or nearby returned, for example GET /v1/places/node/123. osm_type is node, way or relation. The response contains the feature, the timezone (IANA name of the place's zone, taken from its coordinates) and evaluated_at.

An unknown or non-place ID returns HTTP 404. A bad type or a non-positive ID returns HTTP 400.

MCP server

The MCP server lets AI assistants such as Claude, Cursor and GitHub Copilot call MapLark tools directly from a chat, so the assistant gets live OSM data instead of inventing places, distances or opening hours.

Tool calls count against the same API key as the HTTP API.

Connecting

There are two ways to connect:

  • Hosted HTTP server: point the client at https://api.maplark.com/mcp and send your key as Authorization: Bearer. Nothing to install.
  • Local stdio server: run the server on your own machine with uv, and set your key as MAPLARK_API_KEY. This suits custom agents and offline development.

The server is open source. Its code is in the osmfeatures-py repository.

Tools

Group Tools What it does
Geocode geocode Place name to lon/lat and a bounding box. Called first when the user names a city or neighbourhood.
Places places_search, places_nearby, places_details Places by OSM tag in a box or radius, nearest-first ranking from a point, and full detail for one OSM ID.
Routes routes_isochrone, routes_path, routes_optimized_path Reach areas, given-order paths and tours on the OSM network.
Generic OSM query Any tagged feature, such as buildings, cycleways or parks. One complete response; no cursor.
Counts and density count, density Totals or grouped counts, and occupied grid cells for heatmaps.
Local (no HTTP) nearest_within, filter_open, point_in_polygon, points_in_polygon Joins and filters over results the agent already fetched. These run in the server and make no further API calls.
Draw and export preview_map, export_geojson Render one or more result collections on a map, or return raw GeoJSON.

Tags are plain OSM tags, such as amenity=restaurant, cuisine=italian or amenity=charging_station. There is no proprietary category tree, and the assistant can use tag names it already knows.

Example prompts

The assistant chooses the tags, the area and the next tool. Typical chains:

  • "Open cafes by distance and cuisine near me": geocode, then places_nearby
  • "Vegan restaurants open after 6pm on a walk from the station to the old town": geocode, routes_path, places_search, filter_open, nearest_within, preview_map
  • "Open cafes within a 10-minute bike ride": geocode, routes_isochrone, places_search, points_in_polygon
  • "Suggest a bar crawl in a city": geocode, places_search, routes_optimized_path with loop=true
  • "How many amenities are in Sweden, by type?": geocode, then count with group_by=amenity
  • "Draw a heatmap of amenities in Stockholm": geocode, density, preview_map

Local tools

Local joins in the server make no API calls, because they use results the agent already has.

Free tools

MapLark also hosts a free OSM Listing Checker, which helps improve business SEO. It grades how complete and current a business listing is on OpenStreetMap, and links each finding to the OSM element. Complete, up-to-date listings are more likely to be found in search and maps. The tool needs no API key.

Comparison with Overpass API

The Overpass API is a free public service for querying OSM data. It runs on community-operated servers, with fair-use rate limits and no service-level agreement. Its query language, Overpass QL, is more expressive than MapLark's: it can combine sets, recurse through relations, and select by area in one query. Overpass can also be self-hosted, which needs its own database and maintenance.

MapLark is a hosted API that runs on managed PostGIS infrastructure. The main differences are:

Topic Overpass API MapLark
Cost Free on public servers Generous free tier, free forever
Service levels Shared community servers, fair-use limits Per-key rate limits and monthly usage limits
Query language Overpass QL, with set operations, recursion and area queries Query parameters with a boolean tag string; no recursion or set operations in a single request
Output JSON, XML, CSV, GeoJSON via tooling GeoJSON, FlatGeobuf, GeoParquet, CSV, selected by Accept
Spatial filters Bounding box, around (radius), area by name or ID Bounding box, radius, or an OSM way or relation as a polygon
Extras Raw element access Density grids, counts, places and routing endpoints
Self-hosting Possible; open source server Not available

The tag model is the same in both: queries select OSM elements by the tags mappers already use, such as amenity=cafe or building. Existing Overpass queries that use simple tag selection can usually be rewritten as tag strings. Queries that depend on Overpass QL features, such as recursion or joining sets of elements, need several MapLark requests and client-side code.

Measured performance

MapLark published timings of the same two queries against its production API and the public overpass-api.de instance. The data was captured on 2026-08-08 in one session. The element counts reported for each query were compared between the two services before timing.

Query Source Runs (ms) Elements
Buildings in a bounding box (building=yes, ways with polygon geometry) MapLark 826, 767, 760, 744 532
Overpass 1400, 9430, 9280 (failed) 531
Query Source Runs (ms) Elements
Cafes within 1.5 km (amenity=cafe) MapLark 688, 541, 551 231
Overpass 1038, 10203, 8120 (failed) 233

The MapLark timings stayed in a narrow band. Overpass runs ranged from about 1 s to over 10 s, and some runs failed. The element counts differ by one or two between services, so the two sets of results are not identical.

These are single-session samples, and public Overpass load changes from hour to hour. The blog post lists the curl commands for repeating the comparison. To run Overpass queries on a map, open Overpass Ultra, a browser map that runs Overpass QL queries.

Choosing between them

  • Use Overpass for ad-hoc exploration, one-off analysis, or when you need Overpass QL and the free access is enough.
  • Use MapLark for production applications that need predictable latency, GeoJSON or columnar output, counts and heatmaps, or routing in the same service.

See also