Migrating from Google Maps Platform

By the end of this guide, you'll have replaced your Google Maps API calls with Plaza equivalents. Most projects can switch in an afternoon.

Why people switch

Cost. Google charges per request across a maze of SKUs with unpredictable pricing. Plaza has a free tier (10K calls/month) and flat usage-based billing after that. No surprise bills.

Data freedom. Google's ToS prohibit caching results or using them outside Google Maps. Plaza serves OpenStreetMap data under ODbL -- cache it, redistribute it, build whatever you want.

Things Google can't do. Isochrone polygons, Overpass QL for complex spatial queries, streaming millions of features, and cross-feature queries that chain geocoding + routing + search in a single call. Google has no equivalent to any of these.

API mapping

Google Maps API Plaza equivalent Method
Places Nearby Search /api/v1/nearby?lat=...&lng=...&radius=... GET
Places Text Search /api/v1/search?q=... GET
Place Details /api/v1/elements/:type/:id GET
Geocoding /api/v1/geocode?q=... GET
Reverse Geocoding /api/v1/geocode/reverse?lat=...&lng=... GET
Directions /api/v1/route POST
Distance Matrix /api/v1/matrix POST
(no equivalent) /api/v1/isochrone?lat=...&lng=...&time=... GET
(no equivalent) /api/v1/overpass (Overpass QL) POST
(no equivalent) /api/v1/sparql (SPARQL) POST

Auth change

Google uses a query parameter (key=API_KEY) or OAuth. Plaza uses a header.

# Google
curl "https://maps.googleapis.com/maps/api/geocode/json?address=Berlin&key=GOOGLE_KEY"
# Plaza
curl "https://plaza.fyi/api/v1/geocode?q=Berlin" \
-H "x-api-key: pk_live_YOUR_KEY"

Get your Plaza key from the dashboard.

Code changes

Geocoding

Python -- Google:

import googlemaps
gmaps = googlemaps.Client(key="GOOGLE_KEY")
result = gmaps.geocode("1600 Amphitheatre Parkway, Mountain View")
lat = result[0]["geometry"]["location"]["lat"]
lng = result[0]["geometry"]["location"]["lng"]

Python -- Plaza:

import requests
resp = requests.get(
"https://plaza.fyi/api/v1/geocode",
params={"q": "1600 Amphitheatre Parkway, Mountain View"},
headers={"x-api-key": "pk_live_YOUR_KEY"}
)
data = resp.json()
lat = data["results"][0]["lat"]
lng = data["results"][0]["lng"]

Nearby search

JavaScript -- Google:

const { Client } = require("@googlemaps/google-maps-services-js");
const client = new Client({});
const resp = await client.placesNearby({
params: {
location: { lat: 48.8584, lng: 2.2945 },
radius: 500,
type: "cafe",
key: "GOOGLE_KEY"
}
});
const places = resp.data.results;

JavaScript -- Plaza:

const resp = await fetch(
"https://plaza.fyi/api/v1/nearby?lat=48.8584&lng=2.2945&radius=500&tags=amenity%3Dcafe",
{ headers: { "x-api-key": "pk_live_YOUR_KEY" } }
);
const data = await resp.json();
const places = data.features;

Directions

curl -- Google:

curl "https://maps.googleapis.com/maps/api/directions/json?\
origin=48.8566,2.3522&destination=48.8849,2.3350&key=GOOGLE_KEY"

curl -- Plaza:

curl -X POST "https://plaza.fyi/api/v1/route" \
-H "x-api-key: pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"origin": {"lat": 48.8566, "lng": 2.3522}, "destination": {"lat": 48.8849, "lng": 2.3350}}'

Reverse geocoding

Python -- Google:

result = gmaps.reverse_geocode((48.8584, 2.2945))
address = result[0]["formatted_address"]

Python -- Plaza:

resp = requests.get(
"https://plaza.fyi/api/v1/geocode/reverse",
params={"lat": 48.8584, "lng": 2.2945},
headers={"x-api-key": "pk_live_YOUR_KEY"}
)
address = resp.json()["display_name"]

Things that work differently

Tags, not place types. Google has its own taxonomy (restaurant, cafe, hospital). Plaza uses OpenStreetMap tags (amenity=restaurant, amenity=cafe, amenity=hospital). The mapping is usually obvious, but check the OSM wiki for the full list.

GeoJSON responses. Plaza returns standard GeoJSON. If you're using Leaflet or MapLibre, the output plugs in without transformation. Google has its own response format that always needs parsing.

Streaming. Queries returning 1,000+ features stream as newline-delimited JSON. Google paginates with next_page_token and caps at 60 results. See the streaming guide.

Overpass QL. For anything beyond simple searches, Plaza supports a real query language. Find all pubs in London with outdoor seating that serve food? One Overpass query. With Google, it's paginated requests with client-side filtering.

No map tiles. Plaza is a data API. Pair it with MapLibre GL JS and a tile provider for map rendering.

Gotchas

Coordinate order. Google sometimes uses lat,lng strings, sometimes {lat, lng} objects depending on the API. Plaza uses separate lat and lng parameters (GET) or {"lat": ..., "lng": ...} objects (POST). GeoJSON coordinates are always [lng, lat] per the spec.

No next_page_token. Plaza uses cursor-based pagination. Pass the cursor value from the response to get the next page.

Rate limit headers. Google returns 429 without much context. Plaza includes x-ratelimit-remaining and x-ratelimit-reset on every response so you can throttle proactively.

OSM IDs can change. In practice they rarely do, but don't treat them as permanent identifiers the way you might with Google's place_id. If you need a durable reference, store coordinates or tags.