The browser's geolocation gives you raw coordinates, but users want a place name. Going from 48.85, 2.35 to "Paris" is reverse geocoding, and for the city level it's one request.
Nearest cities to a point
curl "https://countries.dev/cities/near?lat=48.85&lng=2.35&limit=3"[
{ "name": "Paris", "countryCode": "FR", "population": 2138551, "timezone": "Europe/Paris", "distanceKm": 0.4 },
{ "name": "Paris 05 Panthéon", "countryCode": "FR", "distanceKm": 0.6 }
]Results are ordered by distance, and each one carries distanceKm so you can tell "in the city" from "near it".
Pair it with the browser
navigator.geolocation hands you the coordinates; this turns them into a label:
navigator.geolocation.getCurrentPosition(async ({ coords }) => {
const [city] = await fetch(
`https://countries.dev/cities/near?lat=${coords.latitude}&lng=${coords.longitude}&limit=1`,
).then((r) => r.json());
console.log(`${city.name}, ${city.countryCode}`); // Paris, FR
});No key, and the permissive CORS headers mean you can call it straight from the browser.
Just need the country?
If all you want is the visitor's country and you don't have coordinates, skip geolocation entirely and resolve it from their IP — see getting a user's country from their IP.
Written by
Dov Azencot
At
Wed Jun 24 2026