
Download World Cities Database
Cities, towns, villages, and hamlets by country
Download a world cities database built from OpenStreetMap, with country-specific files ready for research, data products, and location-based applications.
The files are packaged as NDJSON for efficient processing, with one GeoJSON record per line. Each record includes names, address hierarchy, population when available, centroid coordinates, bounding boxes, OSM identifiers, and optional administrative boundary links.
Use the identifiers with the Geoapify Place Details API for richer geometry, or keep the files offline for your own analysis pipeline.
Quick answer: Geoapify's World Cities Database is a free, country-based download of localities compiled from OpenStreetMap.
- Coverage: cities, towns, villages, and hamlets, grouped by country.
- Format: ZIP archives with NDJSON files inside; each line is a GeoJSON record.
- Fields: names, address hierarchy, coordinates, bounding boxes, OSM identifiers, population when available, and optional boundary links.
- Use cases: offline locality data for GIS analysis, data products, search indexes, maps, and location-based applications.
Global Cities and Settlements Dataset
We ship the data as country-specific archives using the ISO alpha-2 code. Typical filenames look like us.zip for the United States, ca.zip for Canada, or de.zip for Germany.
Inside each archive you’ll find up to four newline-delimited JSON files, one per settlement tier:
place-city.ndjsonplace-town.ndjsonplace-village.ndjsonplace-hamlet.ndjson
Download only the country and granularity you need - no planet-scale unzip just to work with one area.
Download Files by Country
The download directory groups the settlement files by country. Choose a ZIP archive, then process the NDJSON file for the settlement level you need.
Direct country archive examples:
- United States:
https://www.geoapify.com/data-share/localities/us.zip - Canada:
https://www.geoapify.com/data-share/localities/ca.zip - Germany:
https://www.geoapify.com/data-share/localities/de.zip
We use NDJSON (newline-delimited JSON), which allows you to read large files line by line. Each line contains one GeoJSON record, so you can stream the data efficiently while keeping the geometry and properties in a standard geospatial format.
How we compile the settlement data
We curate the records directly from OpenStreetMap with two complementary passes:
- Settlements (
place=*) – we pick up every feature tagged as city, town, village, or hamlet. - Administrative boundaries – we add polygons tagged as boundary=administrative when they reference the same settlement level (through
linked_place,border_type, orplacetags) or clearly represent municipal areas via theiradmin_level.
This approach gives you both the populated place features and the boundaries that frame them.
Heads-up: When we import boundaries we first try to attach them to the matching populated place. If the boundary exists on its own (no
place=*partner), we still include it and setinferred_typeto the settlement level it represents—city,town,village, orhamlet. That flag tells you how to categorise the record even though the original OSM feature is tagged only asboundary=administrative. Some areas in OSM remain mapped this way, so you may encounter boundary-only rows until local mappers add the corresponding place nodes or ways.
City, Town, Village, and Hamlet Schema
Each GeoJSON record in the download follows the same schema so you can switch between countries without remapping columns:
name,other_names, anddisplay_namecapture the primary and alternate labels for the place.addressprovides the nested administrative hierarchy such as county, state, ISO codes, and country code.populationcontains the crowd-sourced population value when it exists in OSM.osm_type,osm_id, andtypeidentify the original OpenStreetMap feature and its settlement level.locationandbboxstore the centroid coordinates and bounding box in[lon, lat]order.borderlinks to the matching administrative geometry (single object or array) andinferred_typeflags inferred settlement levels when only a boundary is available.
The table below summarises every field:
| Field | Description |
|---|---|
| name | The name of the place, e.g., "North Vancouver," "Aachen," "Edmonton." |
| other_names | A dictionary of alternate names in various languages and official names where applicable. |
| display_name | The full display name, including location details such as regional districts, states, and countries. |
| address | Information about the location, including city name, county, state, country, country code, etc. |
| population | The population of the place. |
| osm_type | The data type in the OpenStreetMap database (e.g., "relation", "node" or "way"). |
| osm_id | The unique identifier in the OpenStreetMap database for the place. |
| type | The place classification provided by OSM, such as city, town, village, or administrative. |
| location | The geographical coordinates of the place as [longitude, latitude]. |
| bbox | The bounding box [minLon, minLat, maxLon, maxLat] describing the geographic extent of the place. |
| border | Optional matching boundary=administrative feature(s) linked to the place. Depending on the source it can be a single object or an array of objects with the same fields as the top-level record. |
| inferred_type | When only an administrative boundary exists, this field indicates the settlement level we inferred for the place. |
Here’s what a single record looks like. It shows the US city "Worcester" with the border block that mirrors the same fields for the administrative outline:
- "Worcester"
- {} 4 keys▶
- "Worcester, Worcester County, Massachusetts, United States"
- {} 6 keys▶
- 206518
- "node"
- 158851900
- "city"
- [] 2 items▶
- [] 4 items▶
- -71.9618877
- 42.1025621
- -71.6418877
- 42.4225621
- [] 2 items▶
Border property explanation
The border field lets you work with both the populated place (place=*) and its matching boundary=administrative geometry without extra lookups. Each entry in border mirrors the top-level schema—name, identifiers, coordinates, and bounding box—so you can reuse the same parsing logic. Depending on the data available in OSM, border can be a single object or an array of objects. When the dataset only has an administrative relation for a settlement, the inferred_type property shows which settlement level we mapped it to.
Below is a sample of U.S. records that illustrates how population, bounding boxes, and administrative borders are bundled together.
| name | state | population | osm_type/id | location | border |
|---|---|---|---|---|---|
| Wooster | Ohio | 27,232 | node / 154340168 | [-81.9397733, 40.7980976] | relation / 183148 |
| Worcester | Massachusetts | 206,518 | node / 158851900 | [-71.8018877, 42.2625621] | relation / 1844209 |
| Wrangell | Alaska | 2,127 | node / 150917119 | [-132.3829431, 56.4706022] | relation / 2605235 |
| Yakima | Washington | 96,968 | node / 3413361438 | [-120.510842, 46.601557] | relation / 237752 |
| Yonkers | New York | 211,569 | node / 158846316 | [-73.8987469, 40.9312099] | relation / 174494 |
Code Samples
Use these examples to connect the download files with common processing tasks: reading NDJSON, filtering places by administrative fields, checking duplicate records, and retrieving the source OpenStreetMap geometry.
Get the original OSM object and its geometry
To retrieve the original OSM object and its geometry, use the Geoapify Place Details API. You'll need the unique identifiers from the dataset, such as osm_id and osm_type, to make requests to the API.
Here is a URL example:
https://api.geoapify.com/v2/place-details?osm_id=62422&osm_type=r&apiKey=YOUR_API_KEYCompare duplicate city records
Sometimes duplicates appear when multiple OpenStreetMap objects reference the same place. For example, one entry may represent the city boundary, while another describes the city center:
{"name":"Berlin","population":3769962,"osm_type":"relation","osm_id":62422,"type":"administrative","location":[13.3888599,52.5170365],"bbox":[13.088345,52.3382448,13.7611609,52.6755087]}
{"name":"Berlin","population":3769962,"osm_type":"node","osm_id":240109189,"type":"city","location":[13.3888599,52.5170365],"bbox":[13.2288599,52.3570365,13.5488599,52.6770365]}The first row corresponds to OSM relation 62422, and the second row corresponds to OSM node 240109189.
Filter cities by U.S. state
Use address fields to find all places within one administrative location. Here is a Python code sample for selecting all cities in California:
cities_in_california = [city for city in data if city['address']['state'] == 'California']Read an NDJSON file in Python
Here's a Python example using pandas and an alternative method with json for reading NDJSON files.
Using pandas:
import pandas as pd
# Read an NDJSON file line by line
data = pd.read_json('place-city.ndjson', lines=True)Using json:
import json
data = []
# Read an NDJSON file one line at a time
with open("place-city.ndjson") as f:
for line in f:
data.append(json.loads(line))Both methods achieve the same result, allowing you to read NDJSON files into a Python data structure for further processing.
Read an NDJSON file in JavaScript
You can use the readline module to read NDJSON files line by line in Node.js:
const readline = require('readline');
const fs = require('fs');
const data = [];
const readStream = readline.createInterface({
input: fs.createReadStream('place-village.ndjson')
});
readStream.on('line', (line) => {
data.push(JSON.parse(line));
});
readStream.on('close', () => {
console.log(data); // Process the data as needed
});Copyright and License
The data contained in this dataset is compiled from the OpenStreetMap (OSM) database and is subject to the copyright terms and conditions of OSM contributors.
OpenStreetMap® is open data, licensed under the Open Data Commons Open Database License (ODbL) by the OpenStreetMap Foundation (OSMF).
You are free to copy, distribute, transmit, and adapt the data, as long as you credit OpenStreetMap and its contributors. If you alter or build upon our data, you may distribute the result only under the same license.
Learn More
Continue with practical examples for preparing, enriching, and visualizing the settlement files. These guides show how to turn the download into analysis-ready data, map layers, and broader OpenStreetMap workflows.

Cities, Towns, Villages and Hamlets dataset: How to Use for Data Analysis

JavaScript Heatmap Example: A Step-by-Step Tutorial to Build Heatmaps with MapLibre GL

3 Ways to Get OpenStreetMap(OSM) Data
Frequently Asked Questions
Is this world cities database free to download?
Yes. You can download the country archives from the Geoapify localities download directory. The data is compiled from OpenStreetMap, so follow the OpenStreetMap attribution and ODbL license requirements.
What countries are included?
The dataset is organized by ISO alpha-2 country code, for example us.zip, ca.zip, and de.zip. If a record cannot be confidently assigned to a country from the source data, it may appear in no-country.zip.
What file format does the database use?
The downloads use NDJSON, with one GeoJSON record per line. This makes the files easier to stream, filter, and process than one large JSON array.
How is this different from a geocoding API?
This database is an offline download for working with city, town, village, and hamlet records in your own storage or analysis pipeline. A Geocoding API is better when you need live address search, place lookup, ranking, formatted results, and API-managed updates.
Does the database include population data?
Yes, when population is available in OpenStreetMap. The population field is crowd-sourced, so treat it as useful reference data rather than an official census source.
Does the dataset include city boundaries?
The border field links a populated place to matching boundary=administrative geometry when it is available in OpenStreetMap. Some places have only a point, some have a boundary relation, and some may include both.
Can I use the data commercially?
OpenStreetMap data is licensed under the Open Database License (ODbL). Commercial use is possible, but you must provide proper attribution and follow ODbL share-alike requirements for adapted databases.
Why are there duplicate rows for some cities?
OpenStreetMap can represent the same place with several objects, such as a city center node and an administrative boundary relation. We include these records so you can decide whether to use the populated place, the boundary, or both. See the code samples section for a Berlin example with OSM links.
How can I view place names in another language?
The NDJSON files store the native OpenStreetMap labels. To get localized names, call the Geoapify Place Details API with the record's osm_id and osm_type, and pass a lang parameter such as lang=es or lang=ja.
How frequently is this dataset updated?
Cities, towns, villages, and hamlets are relatively stable, but OpenStreetMap changes over time. Re-download the latest country archive when you need a refreshed copy, and contact us if you find an issue that should be corrected.