Overpass
OpenStreetMap is a free, queryable map database. Its Overpass API (with the web IDE Overpass Turbo) lets you search every tagged feature (shops, fountains, benches, memorials, addresses, …) by tag and by area.
It is the tool of choice for geolocation by intersecting points of interest: when a challenge describes a place through several constraints (a fountain on a roundabout, a café near a named statue, a city where someone lived), translate each clue into an Overpass query and keep the location that satisfies all of them.
Overpass QL basics
[out:json][timeout:25];
// nodes with a tag inside a bounding box (south,west,north,east)
node["amenity"="fountain"](48.85,2.33,48.87,2.36);
out body;
// everything of a kind around a point (radius in meters)
node(around:200, 48.8566, 2.3522)["amenity"="cafe"];
out;
// inside a named administrative area
area["name"="Paris"]["admin_level"="8"]->.a;
node(area.a)["historic"="memorial"];
out;The real power is cross-finding: store one result in a named set (->.set) and search around it with around.<set>:<radius>. For example, all public benches within 30 m of a restaurant:
[out:json][timeout:25];
area["name"="Paris"]["admin_level"="8"]->.a;
node(area.a)["amenity"="restaurant"]->.restos; // step 1: restaurants, stored in set .restos
node(around.restos:30)["amenity"="bench"]; // step 2: benches within 30 m of any of them
out body;Querying from Python
import requests
query = """
[out:json][timeout:25];
area["name"="Paris"]["admin_level"="8"]->.searchArea;
node(area.searchArea)["amenity"="fountain"];
out body;
"""
r = requests.post("https://overpass-api.de/api/interpreter", data={"data": query})
for el in r.json()["elements"]:
tags = el.get("tags", {})
print(el["id"], el.get("lat"), el.get("lon"), tags.get("name", ""))Combine the results programmatically (for example keep only the fountains that have a café within 50 m) to pin down the single location that matches every clue.