Cities, behind an HTTP GET.
Geomelon is a read-only REST API holding 2,000,000+ cities, 203 countries, every administrative region under them, and their names in 50 languages.
You've written this seed script before. It scrapes something, it half-works, the encoding is wrong for two countries, and eighteen months later nobody remembers where the data came from. This is that, maintained.
Lat/lon you can get anywhere. What you can't easily get is the fact that a Hungarian user searching for Vienna types Bécs. Send preferredLanguages=hu,de,en and the API walks the list until it finds a name that exists.
Countries and regions carry the same. Ask for one preferred name and you get one; ask for the translations endpoint and you get the whole set to index on.
There is no write path. Nothing to secure, nothing to migrate, no data of yours living somewhere else.
GET /cities/searchName, country, region, population range. Sort and paginate.
GET /cities/{id}One city, country and region already joined on.
GET /cities/{id}/translationsEvery recorded name for that city.
GET /cities/{id}/settlement-typesAdministrative classification with descriptions.
GET /cities/byCoordinates/closestNearest cities to a point, distance in km included.
GET /cities/byCoordinates/largestMost populous cities near a point.
GET /cities/distanceKilometres between two cities.
GET /countriesPrefix search on name, or filter by telephone code.
GET /countries/{id}ISO code, dialling code, trunk prefix, driving side, plate code, head of state and government, regions inline.
GET /countries/{id}/translationsCountry name in every language it has one.
GET /countries/{id}/regionsRegions with ISO 3166-2 codes and population.
GET /regionsAll regions, optionally scoped to a country.
GET /regions/{id}Region with parent country inlined.
GET /regions/{id}/translationsLocalised region names.
GET /languagesEvery language held, with a count of cities covered.
GET /languages/{id}One language by UUID.
Country name, ISO code, flag emoji and dialling code are already there. Rendering a result row costs you one request, not three.
Typed, zero dependencies, both of them. TypeScript ships CJS and ESM; Python is standard library only, 3.8 through 3.14, ships py.typed.
$ npm install geomelon import { GeomelonClient } from "geomelon"; const client = new GeomelonClient({ apiKey: process.env.RAPIDAPI_KEY }); const cities = await client.cities.search({ name: "barc", countryCode: "ES", minPopulation: 50000, preferredLanguages: "ca,es,en", sort: "population_desc", }); const nearby = await client.cities.byCoordinatesClosest({ lat: 41.3825, lon: 2.1769, });
$ pip install geomelon from geomelon import GeomelonClient, GeomelonError client = GeomelonClient(api_key=os.environ["RAPIDAPI_KEY"]) cities = client.cities.search( name="barc", country_code="ES", preferred_languages="ca,es,en", ) # snake_case in, camelCase mapped for you. # unknown response fields are ignored, so API # additions never break an installed client. except GeomelonError as err: if err.is_rate_limited: backoff()
$ npm install geomelon-react // free endpoint underneath — no key, no backend proxy import { useCityAutocomplete } from "geomelon-react"; const { results, loading, error } = useCityAutocomplete({ countryIso: "at", lang: "hu", query, }); // 150ms debounce, in-flight cancellation, typed errors. // or take the finished combobox, ARIA + keyboard, no CSS: <CityAutocomplete countryIso="at" lang="hu" onSelect={setCity} />
$ npx geomelon-mcp # 21 tools over stdio or HTTP { "mcpServers": { "geomelon": { "command": "npx", "args": ["-y", "geomelon-mcp"], "env": { "GEOMELON_API_KEY": "YOUR_RAPIDAPI_KEY" } } } } // compound tools — country_overview, compare_cities, // city_context — collapse several round-trips into one. // drop env for keyless. hosted: https://mcp.geomelon.dev/mcp
Language we don't ship? The OpenAPI 3.0 spec is at geomelon.dev/openapi.json — openapi-generator covers 60+ targets.
City autocomplete is what most people actually came for, so it costs nothing and needs no account. Everything else is behind a key.
free · no key · no signup
Access-Control-Allow-Origin: *, call it from the browserst. finds St. John'scurl https://oneshot.geomelon.dev/at/hu/becCoverage table
keyed · billed via RapidAPI
client.cities.search({ countryCode: "DE",
minPopulation: 500000 })
Get API key
Five clients, plus the dataset itself if you'd rather hold the data than call it.
TypeScript client. Typed, zero deps, dual CJS/ESM, Node 18+.
npm install geomelonPython client. Stdlib only, dataclasses, full type hints.
pip install geomelonHeadless autocomplete hook plus a finished ARIA combobox.
npm install geomelon-reactMCP server, stdio or HTTP, 21 tools. Runs keyless too.
npx geomelon-mcpn8n community node. Every resource as a workflow step.
Settings → Community NodesThe city dataset on Hugging Face for analysis or training.
load_dataset("geomelon/cities")It's the production endpoint, unauthenticated, and it stays free. Try to break it. When you need population filters, coordinates or region data, the key takes about a minute.