Skip to content
GuidesBlogPlaygroundDashboard

Place Search

Search across all features by name and location with Plaza's search API.

POST /api/v1/search

Full-text search across every named entity in OpenStreetMap — parks, restaurants, bus stops, peaks, rivers, monuments. Results are BM25-ranked and filterable by geometry or proximity.

FieldTypeDefaultDescription
qstringRequired. Search query.
limitint20Max results (1–1,000).
formatstringgeojsonResponse format: json, geojson, csv. See Streaming & Response Formats.
cursorstringCursor for pagination (from previous response headers).
withinobjectGeoJSON Polygon geometry. Only return results inside this area.
aroundobjectGeoJSON Point geometry for proximity search. Requires radius.
radiusnumberSearch radius in meters (used with around).
output[precision]int7Coordinate decimal precision (1–15).
output[fields]stringComma-separated property fields to include.
output[include]stringExtra computed fields: bbox, distance, center.
output[sort]stringSort by: distance, name, osm_id.

Geocoding finds addresses. Search finds named entities.

Use caseEndpoint
”123 Main St, Portland OR”/geocode
”coffee shops in Portland”/search
”Eiffel Tower”/search
”48.8584, 2.2945”/geocode/reverse
”pizza near me”/search with around+radius
”10 Downing Street, London”/geocode
”Big Ben”/search

Street addresses go to geocoding. Place names, categories, and descriptive queries go to search.

Terminal window
curl -X POST https://plaza.fyi/api/v1/search \
-H "Content-Type: application/json" \
-H "x-api-key: $PLAZA_API_KEY" \
-d '{"q": "central park", "within": {"type": "Polygon", "coordinates": [[[-74.05, 40.7], [-73.9, 40.7], [-73.9, 40.85], [-74.05, 40.85], [-74.05, 40.7]]]}}'
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-73.9654, 40.7829]
},
"properties": {
"@type": "relation",
"@id": 175905,
"name": "Central Park",
"score": 24.7,
"source": "place"
}
}
]
}

score is the BM25 relevance score (higher is better, not comparable across queries). source indicates the matching index (place or tag).

Terminal window
curl -X POST https://plaza.fyi/api/v1/search \
-H "Content-Type: application/json" \
-H "x-api-key: $PLAZA_API_KEY" \
-d '{"q": "The Crown", "within": {"type": "Polygon", "coordinates": [[[-0.5, 51.3], [0.3, 51.3], [0.3, 51.7], [-0.5, 51.7], [-0.5, 51.3]]]}}'
Terminal window
curl -X POST https://plaza.fyi/api/v1/search \
-H "Content-Type: application/json" \
-H "x-api-key: $PLAZA_API_KEY" \
-d '{"q": "museum", "around": {"type": "Point", "coordinates": [2.3522, 48.8566]}, "radius": 5000}'

For tag-based filtering, use the /features endpoint with tag query parameters, or write a PlazaQL query.

import Plaza from "@plazafyi/sdk";
const client = new Plaza();
// Find ramen restaurants in Manhattan
const results = await client.v1.search({
q: "ramen",
within: {
type: "Polygon",
coordinates: [[[-74.02, 40.7], [-73.9, 40.7], [-73.9, 40.8], [-74.02, 40.8], [-74.02, 40.7]]],
},
limit: 20,
});
for (const feature of results.features) {
console.log(`${feature.properties.name} (score: ${feature.properties.score})`);
}
import plaza
client = plaza.Client()
# Find train stations in Germany
results = client.v1.search(
q="Hauptbahnhof",
within={
"type": "Polygon",
"coordinates": [[[5.9, 47.3], [15.0, 47.3], [15.0, 55.1], [5.9, 55.1], [5.9, 47.3]]],
},
limit=50,
)
for feature in results.features:
print(f"{feature.properties['name']}{feature.properties['score']:.1f}")
results, err := client.V1.Search(ctx, &plaza.SearchParams{
Q: "brewery",
Within: &plaza.GeoJSONPolygon{
Type: "Polygon",
Coordinates: [][][]float64{{{-123.0, 37.0}, {-122.0, 37.0}, {-122.0, 38.5}, {-123.0, 38.5}, {-123.0, 37.0}}},
},
Limit: plaza.F(20),
})
if err != nil {
panic(err)
}
for _, f := range results.Features {
fmt.Printf("%s (score: %.1f)\n", f.Properties.Name, f.Properties.Score)
}

Plaza indexes billions of features. Here are some examples with the search endpoint and PlazaQL.

Terminal window
# Waterfalls in Iceland — "foss" is Icelandic for waterfall
curl -X POST https://plaza.fyi/api/v1/search \
-H "Content-Type: application/json" \
-H "x-api-key: $PLAZA_API_KEY" \
-d '{"q": "foss", "within": {"type": "Polygon", "coordinates": [[[-24.5, 63.3], [-13.5, 63.3], [-13.5, 66.6], [-24.5, 66.6], [-24.5, 63.3]]]}}'
Terminal window
# Every "Devil's" anything in the US — Devil's Tower, Devil's Backbone, Devil's Punchbowl...
curl -X POST https://plaza.fyi/api/v1/search \
-H "Content-Type: application/json" \
-H "x-api-key: $PLAZA_API_KEY" \
-d '{"q": "Devil", "within": {"type": "Polygon", "coordinates": [[[-125.0, 24.5], [-66.9, 24.5], [-66.9, 49.4], [-125.0, 49.4], [-125.0, 24.5]]]}, "limit": 100}'

The search endpoint finds things by name. PlazaQL finds things by what they are — their OSM tags. This is where it gets interesting.

// Vending machines that sell pizza (yes, these exist in Japan and Italy)
search(node, amenity: "vending_machine", vending: "pizza");
// Roads you can't walk on — no sidewalk, no pedestrian access
search(way, highway: "primary", foot: "no", sidewalk: "none")
.bbox(south: 40.7, west: -74.0, north: 40.8, east: -73.9);
// Drinking fountains within a 10-minute walk in Rome
$walkable = isochrone(center: point(41.9028, 12.4964), time: 600, mode: "foot");
search(node, amenity: "drinking_water").within(geometry: $walkable);
// Every haunted castle in the UK (OSM actually tags these)
$uk = boundary(name: "United Kingdom");
search(historic: "castle", ghost: *).within(geometry: $uk);
// Pubs older than the United States
$england = boundary(name: "England");
search(amenity: "pub", start_date: ~"^1[0-6]")
.within(geometry: $england);
// Subway stations you can transfer between in Manhattan
$manhattan = boundary(name: "Manhattan");
$stations = search(node, railway: "station", station: "subway")
.within(geometry: $manhattan);
$$.transfers = search(relation, route: "subway")
.has_member($stations.first());
// EV chargers along an LA-to-SF road trip
$r = route(origin: point(34.0522, -118.2437), destination: point(37.7749, -122.4194), mode: "auto");
search(amenity: "charging_station")
.around(distance: 2000, geometry: $r)
.sort(distance($r));
// Buildings with rooftop solar panels in San Francisco
$sf = boundary(name: "San Francisco");
search(way, building: *, generator__source: "solar")
.within(geometry: $sf);
// Unpaved roads in Colorado — for off-roading or bikepacking
$colorado = boundary(name: "Colorado");
search(way, highway: *, surface: "unpaved")
.within(geometry: $colorado);
// Fire stations you can reach in under 15 minutes
$iso = isochrone(center: point(40.7128, -74.0060), time: 900, mode: "auto");
search(amenity: "fire_station").within(geometry: $iso);
// Cave entrances in the Appalachians
search(natural: "cave_entrance")
.bbox(south: 34.0, west: -84.0, north: 40.0, east: -78.0);
// Biergartens in Bavaria (the real ones, not the American kind)
$bavaria = boundary(name: "Bayern");
search(amenity: "biergarten").within(geometry: $bavaria);
// Lighthouses you can actually visit
search(man_made: "lighthouse", tourism: *)
.bbox(south: 42.0, west: -124.8, north: 46.3, east: -123.5);

See the PlazaQL guide for the full query language reference.

Plaza uses BM25 (same algorithm as Elasticsearch) considering term frequency, inverse document frequency, and field length. The name field is weighted highest, followed by alt_name, old_name, and tag values.

Search results work as input for other Plaza endpoints:

# Find a park
parks = client.v1.search(q="Golden Gate Park", limit=1)
park = parks.features[0]
# Search nearby using the park's coordinates
coords = park.geometry.coordinates
nearby = client.v1.search(
q="coffee",
around={"type": "Point", "coordinates": coords},
radius=1000,
)