GuidesGEOCODING APIS
Free geocoding APIs tested from the browser
We tested 11 free geocoding APIs from a browser on 26 October 2026: 10 send CORS headers and work with fetch() directly, only the US Census Geocoder needs a proxy, and 6 need no API key. For a JavaScript map app, use Photon for search as you type and Nominatim for lookups on submit, at most 1 request per second for your whole app. Keyed free tiers give 2,500 to 5,000 requests a day, and Mapbox 100,000 a month.
Every geocoder we tested
We ran each API on 26 October 2026 with curl and an Origin: https://example.com header from a German datacenter IP and a US residential IP, then in Chromium 147.0.7727.15 from http://127.0.0.1:8001. Every keyed API still sent Access-Control-Allow-Origin when we used a fake key, so all of them work from the browser once you have a real one.
| API | Key | CORS | Free limit | Use it for |
|---|---|---|---|---|
| Nominatim (OpenStreetMap) | None | Yes, ACAO * | 1 request/second for your whole app | Lookups on submit; autocomplete is forbidden |
| Photon (Komoot) | None | Yes, ACAO * | Fair use; heavy use is throttled | Search as you type on OpenStreetMap data |
| Open-Meteo Geocoding | None | Yes, ACAO * | Open-Meteo free terms, non-commercial | City and town names to coordinates |
| BigDataCloud reverse-geocode-client | None | Yes, ACAO * | Fair use; browser only, server calls get 402 | City and country for the user's GPS position |
| US Census Geocoder | None | No, use a proxy | Batch files up to 10,000 addresses | US street addresses |
| Géoplateforme (data.geopf.fr) | None | Yes, ACAO * | 50 requests/second per IP | French addresses, autocomplete allowed |
| Geoapify | Free key | Yes, ACAO * | 3,000 credits/day, 5 requests/second | Commercial use with attribution |
| LocationIQ | Free key | Yes, ACAO * | 5,000 requests/day, 2/second | Limited commercial use with a backlink |
| OpenCage | Free trial key | Yes, ACAO * | 2,500 requests/day, 1/second | Testing only on the free trial |
| Mapbox Geocoding v6 | Public pk. token | Yes, ACAO * | 100,000 requests/month | Map apps; temporary results only |
| Google Geocoding | Website-restricted key | Yes, on the web service | 10,000 events/month, then $5.00 per 1,000 | Use the Maps JavaScript API Geocoder in browsers |
Pick by what the user does. Typing into a search box: Photon. Submitting a full address: Nominatim. Choosing a city for a forecast: Open-Meteo. Sharing their GPS position: BigDataCloud. For more browser-ready endpoints, see our 70-API list of free public APIs.
Forward geocoding without a key
Photon (https://photon.komoot.io) is built for search as you type on OpenStreetMap data, and /reverse handles reverse geocoding. It needs no key and sends Access-Control-Allow-Origin: *, so call it directly. Its public API terms ask you to be fair: extensive usage gets throttled, and there is no availability guarantee.
For city and town names, Open-Meteo Geocoding (https://geocoding-api.open-meteo.com/v1/search) needs no key and sends Access-Control-Allow-Origin: *. It only matches place names: Museumstraat 1 Amsterdam returned no results. Open-Meteo's free terms apply, so non-commercial use and less than 10,000 calls per day. Pass the coordinates to one of the free weather APIs for a forecast.
const query = 'Rijksmuseum Amsterdam';
const params = new URLSearchParams({ q: query, limit: '5', lang: 'en' });
const response = await fetch(`https://photon.komoot.io/api/?${params}`);
const body = await response.json().catch(() => null);
if (!response.ok) {
throw new Error(`Photon failed: ${body?.message ?? response.status}`);
}
console.table(
body.features.map(({ properties, geometry }) => ({
name: properties.name,
city: properties.city,
country: properties.country,
lat: geometry.coordinates[1],
lon: geometry.coordinates[0],
})),
);Nominatim rules for browser apps
Nominatim (https://nominatim.openstreetmap.org) needs no key and sends Access-Control-Allow-Origin: *. The OpenStreetMap Foundation runs it, and the Nominatim usage policy sets the rules your app must follow:
- 1 request per second at most. The limit counts your whole website or app, summed over all its users, not each visitor.
- No autocomplete. Search as you type is strictly forbidden on the public server, so search on submit.
- Identify your app with a valid
RefererorUser-Agent. Browsers send theRefererfor you: Chromium sentReferer: http://127.0.0.1:8001/and got 200, while Node 22fetchwith noReferergot 403. - No bulk or systematic queries, cache what you get, and be able to switch to another service.
- Credit OpenStreetMap contributors; the data is under the ODbL.
The snippet below spaces requests 1 second apart and caches repeat queries. Spacing in one tab does not cap the total across all your users, so a busy app needs its own Nominatim instance or a keyed provider.
const cache = new Map();
let nextSlot = 0;
async function searchNominatim(query) {
const key = query.trim().toLowerCase();
if (cache.has(key)) return cache.get(key);
const wait = Math.max(0, nextSlot - Date.now());
nextSlot = Date.now() + wait + 1000;
await new Promise((resolve) => setTimeout(resolve, wait));
const params = new URLSearchParams({ q: query, format: 'jsonv2', limit: '5' });
const response = await fetch(`https://nominatim.openstreetmap.org/search?${params}`);
if (!response.ok) {
throw new Error(`Nominatim failed: ${response.status}`);
}
const places = (await response.json()).map(({ display_name, lat, lon }) => ({
display_name,
lat: Number(lat),
lon: Number(lon),
}));
cache.set(key, places);
return places;
}
// Call it when the user submits the form, never on each keystroke
console.table(await searchNominatim('Museumplein Amsterdam'));
console.table(await searchNominatim('Dam Square Amsterdam'));Reverse geocoding the user's position
BigDataCloud's https://api.bigdatacloud.net/data/reverse-geocode-client turns GPS coordinates into a city and region with no key and sends Access-Control-Allow-Origin: *. In Chromium, 52.36, 4.885 returned Amsterdam, Noord-Holland, Netherlands.
It is free and client-side only under its Fair Use Policy: calls must come from the browser with the device's current position from the HTML5 Geolocation API. Server-side calls get HTTP 402 "This endpoint does not support server-side operations", so don't proxy it. Without coordinates it returns a best-effort locality from the IP address; for that use case, compare the free IP geolocation APIs.
const position = await new Promise((resolve, reject) =>
navigator.geolocation.getCurrentPosition(resolve, reject, { timeout: 10000 }),
);
const params = new URLSearchParams({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
localityLanguage: 'en',
});
const response = await fetch(`https://api.bigdatacloud.net/data/reverse-geocode-client?${params}`);
const body = await response.json().catch(() => null);
if (!response.ok) {
throw new Error(`BigDataCloud failed: ${body?.description ?? response.status}`);
}
console.log(body.city || body.locality, body.principalSubdivision, body.countryName);Address geocoders for the US and France
The US Census Geocoder (https://geocoding.geo.census.gov/geocoder/) covers US addresses with no key. It takes a single address, coordinates, or a batch file of up to 10,000 addresses. It is the only geocoder here without CORS headers: Chromium blocked it with No 'Access-Control-Allow-Origin' header is present on the requested resource, while the same GET through https://proxy.cors.dev/ returned 200 JSON (680 bytes). See how the free CORS proxy works; run batch uploads from a backend.
For France, Géoplateforme (https://data.geopf.fr/geocodage/search) needs no key, sends Access-Control-Allow-Origin: *, and allows 50 requests per second from one IP address. Autocomplete is built in. The older api-adresse.data.gouv.fr/search still answered on 26 October 2026 with the same result, but its responses carry Deprecation and Sunset headers dated 31 January 2026, so move to data.geopf.fr.
Geocoders with a free key or token
- Geoapify: key in
apiKey=. 3,000 credits per day, up to 5 requests per second, no credit card, commercial use allowed with attribution. - LocationIQ: key in
key=. 5,000 requests per day at 2 per second, limited commercial use with a backlink. - OpenCage: key in
key=. Free trial of 2,500 requests per day at 1 per second, for testing, no credit card. - Mapbox Geocoding v6: public
pk.token inaccess_token=. Temporary geocoding is free up to 100,000 requests per month, default rate limit 1,000 per minute. Temporary results must not be cached or stored. Public tokens are made for client-side code; create your own token so you can add URL restrictions, which the default public token can't have. - Google: 10,000 free events per month, then $5.00 per 1,000. Google puts web service keys under IP address restrictions and website restrictions on client-side APIs, so in the browser use the Maps JavaScript API
Geocoderclass with a website-restricted key.
All five send CORS headers, so call them directly. The cors.dev free tier refuses URLs with key=, apiKey=, access_token= and similar parameters (HTTP 400, X-Cors-Error: credential_in_url).
Good questions.
Is there a free geocoding API with no API key?
Yes, 6 of the 11 we tested: Nominatim, Photon, Open-Meteo Geocoding, BigDataCloud reverse-geocode-client, the US Census Geocoder and Géoplateforme. All except the US Census Geocoder send Access-Control-Allow-Origin: *.
Can I use Nominatim for autocomplete?
No. The usage policy strictly forbids autocomplete on the public server. Use Photon, or Géoplateforme for French addresses, for search as you type.
How many requests per second can I send to Nominatim?
At most 1 per second, and that limit covers your whole website or app across all users. Busy apps should run their own instance or use a keyed provider.
Can I call the Google Geocoding API from the browser?
The Geocoding web service sends Access-Control-Allow-Origin: *, but its keys take IP address restrictions, not website restrictions. In a browser, use the Maps JavaScript API Geocoder with a website-restricted key.
Can I store geocoding results?
It depends on the provider. Nominatim asks you to cache results and credit OpenStreetMap under the ODbL, while Mapbox's free temporary geocoding (100,000 requests per month) forbids caching or storing results.
Why does the US Census geocoder fail with a CORS error?
It sends no Access-Control-Allow-Origin header, so Chromium blocks the response. Prefix the URL with https://proxy.cors.dev/ for single GET lookups.