--- title: Migrating from Nominatim | Plaza Docs description: Upgrade from Nominatim to Plaza for faster geocoding, structured responses, and additional APIs. --- Plaza includes the same OpenStreetMap data as Nominatim — plus curated open datasets, custom data support, and a full suite of geospatial APIs beyond geocoding. ## What changes | | Nominatim | Plaza | | ----------------- | -------------------------- | ---------------------------------------------- | | Rate limit | 1 req/sec (absolute) | 10–10,000 req/min depending on plan | | Response format | Custom JSON/XML | GeoJSON | | Data source | OpenStreetMap | OpenStreetMap + curated datasets + custom data | | Reverse geocoding | Yes | Yes | | Autocomplete | No | Yes | | Batch geocoding | No | Yes | | Routing | No | Yes | | Feature search | No | Yes | | Auth | None (IP-based rate limit) | API key | ## API mapping | Nominatim endpoint | Nominatim path | Plaza endpoint | | ------------------ | -------------------- | ------------------------------------------------------------------- | | Search | `/search?q=` | `POST /geocode` with `{"q": "..."}` | | Reverse | `/reverse?lat=&lon=` | `POST /geocode/reverse` with `{"geometry": {"type": "Point", ...}}` | | Lookup | `/lookup?osm_ids=` | `GET /features/:type/:id` | All Plaza endpoints are under `https://plaza.fyi/api/v1`. ## Auth Nominatim rate-limits by IP with no auth. Plaza uses an API key: Terminal window ``` curl -H "x-api-key: pk_live_abc123" \ "https://plaza.fyi/api/v1/geocode?q=Berlin" ``` Sign up at [plaza.fyi](https://plaza.fyi) for a free key. No credit card required. ## Response comparison ### Nominatim ``` [ { "place_id": 279641937, "licence": "Data © OpenStreetMap contributors, ODbL 1.0.", "osm_type": "relation", "osm_id": 62422, "lat": "52.5170365", "lon": "13.3888599", "display_name": "Berlin, Germany", "class": "boundary", "type": "administrative", "importance": 0.8544, "address": { "city": "Berlin", "state": "Berlin", "ISO3166-2-lvl4": "DE-BE", "country": "Germany", "country_code": "de" }, "boundingbox": ["52.338", "52.675", "13.089", "13.761"] } ] ``` ### Plaza ``` { "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Point", "coordinates": [13.3889, 52.5170] }, "properties": { "osm_id": 62422, "osm_type": "relation", "name": "Berlin", "city": "Berlin", "state": "Berlin", "country": "Germany", "country_code": "de", "confidence": 0.98 } } ] } ``` Key differences: - **GeoJSON standard.** No more parsing `lat`/`lon` strings into numbers. - **Coordinates in the geometry**, not separate top-level fields. - **No `display_name`.** Address components are structured properties. - **No `licence` field per response.** The data is still open (ODbL) — see Plaza’s attribution docs. ## Parameter mapping ### Forward geocoding | Nominatim parameter | Plaza parameter | Notes | | ------------------- | --------------- | ---------------------------------------- | | `q` | `q` | Same | | `limit` | `limit` | Same (Plaza max: 1,000) | | `countrycodes` | `country_code` | Single country, not comma-separated | | `viewbox` | `within` | GeoJSON Polygon geometry | | `bounded=1` | Use `within` | Plaza always bounds when `within` is set | | `accept-language` | `lang` | BCP 47 tag | | `format` | — | Always GeoJSON | | `addressdetails=1` | — | Always included | | `extratags=1` | — | Always included | ### Reverse geocoding | Nominatim parameter | Plaza parameter | Notes | | ------------------- | --------------- | -------------------------------------------------- | | `lat` | `lat` | Same | | `lon` | `lng` | Note: `lng`, not `lon` | | `zoom` | — | Not needed. Plaza returns the most specific match. | ## Code migration ### Before (Nominatim) ``` import httpx import time def geocode_nominatim(query): time.sleep(1) # Required: 1 req/sec limit response = httpx.get( "https://nominatim.openstreetmap.org/search", params={ "q": query, "format": "jsonv2", "limit": 5, "addressdetails": 1, }, headers={"User-Agent": "MyApp/1.0"}, ) results = response.json() for r in results: print(f"{r['display_name']}: {r['lat']}, {r['lon']}") ``` ### After (Plaza) ``` import plaza client = plaza.Client() def geocode_plaza(query): results = client.v1.geocode.forward(q=query, limit=5) for f in results.features: coords = f.geometry.coordinates print(f"{f.properties['name']}: {coords[1]}, {coords[0]}") ``` No sleep. No user-agent requirement. No parsing `lat`/`lon` strings. ### Batch geocoding ``` # Nominatim: 100 addresses = 100 seconds minimum for address in addresses: geocode_nominatim(address) time.sleep(1) ``` Plaza supports batch geocoding in a single request: ``` results = client.v1.geocode.batch(addresses=[ "1600 Pennsylvania Ave NW, Washington DC", "10 Downing Street, London", "Élysée Palace, Paris", ]) # Returns a list of FeatureCollections, one per address ``` ## What else you get **Routing.** Turn-by-turn directions with distance and duration. ``` route = client.v1.route( origin={"type": "Point", "coordinates": [13.388, 52.517]}, destination={"type": "Point", "coordinates": [13.397, 52.529]}, mode="bicycle", ) ``` **Isochrones.** “Everywhere reachable within 10 minutes on foot.” ``` iso = client.v1.isochrone( location={"type": "Point", "coordinates": [13.388, 52.517]}, mode="foot", time="300,600,900", ) ``` **Feature search.** Find features by tag, bounding box, or proximity — not just addresses. ``` cafes = client.v1.features.nearby( location={"type": "Point", "coordinates": [13.388, 52.517]}, radius=500, tags={"amenity": "cafe"}, ) ``` **Distance matrix.** Calculate travel times between multiple origins and destinations. ``` matrix = client.v1.matrix( origins=[ {"type": "Point", "coordinates": [13.388, 52.517]}, {"type": "Point", "coordinates": [13.405, 52.520]}, ], destinations=[ {"type": "Point", "coordinates": [13.397, 52.529]}, {"type": "Point", "coordinates": [13.412, 52.523]}, ], mode="auto", ) ``` **PlazaQL.** Plaza’s purpose-built query language for geospatial data — expressive, type-safe, and without public server limits. ## Rate limits Nominatim: 1 req/sec (60/min). Plaza’s free tier: 10 req/min with instant upgrades: | Plan | Requests/min | Monthly included | Price | | -------- | ------------ | ------------------------ | ------- | | Free | 10 | 500 std/day + 10 prm/day | $0 | | Pro 100K | 300 | 100,000 | $50/mo | | Pro 300K | 1,000 | 300,000 | $150/mo | | Pro 1M | 2,000 | 1,000,000 | $500/mo | Self-hosting Nominatim requires 64GB+ RAM and 1TB+ SSD for the full planet. Plaza eliminates that infrastructure.