---
name: geonames-gazetteer-ingestion
description: "How to get GeoNames Gazetteer Dumps data into a pandas DataFrame and Parquet: access, the request, the format, limits, quirks and terms."
---

# Load GeoNames cities into pandas and Parquet

Source entry: https://signal-lab-jet.vercel.app/datasets/geonames-gazetteer
Provider: https://download.geonames.org/export/dump/
Checked against the provider's documentation: 2026-11-01

## Access
- No account or key. The cities15000 ZIP is a public download.
- The full worldwide and country extracts use the same tab-delimited geoname schema.

## Request
```bash
curl -O 'https://download.geonames.org/export/dump/cities15000.zip'
```

## Format
ZIP containing headerless, tab-delimited UTF-8 text. Gazetteer columns cover ID, names, latitude, longitude, feature class and code, country and administrative codes, population, elevation, DEM, timezone and modification date.

## Load into pandas and Parquet
Needs Python 3 with requests, pandas and pyarrow.
```python
"""GeoNames cities with population over 15,000 or capitals -> pandas -> Parquet."""
import io
import zipfile
import requests
import pandas as pd

URL = "https://download.geonames.org/export/dump/cities15000.zip"
COLUMNS = [
    "geonameid", "name", "asciiname", "alternatenames", "latitude", "longitude",
    "feature_class", "feature_code", "country_code", "cc2", "admin1_code",
    "admin2_code", "admin3_code", "admin4_code", "population", "elevation",
    "dem", "timezone", "modification_date"
]
r = requests.get(URL, headers={"User-Agent": "SignalLabCheck/1.0"}, timeout=60)
r.raise_for_status()
with zipfile.ZipFile(io.BytesIO(r.content)) as archive:
    df = pd.read_csv(archive.open("cities15000.txt"), sep="\t", names=COLUMNS,
                     header=None, low_memory=False)
df["modification_date"] = pd.to_datetime(df["modification_date"])
df.to_parquet("geonames_cities15000.parquet", index=False)
print(len(df), "places", df["country_code"].nunique(), "country codes",
      "latest modification", df["modification_date"].max().date().isoformat())
```
Run by us on 2026-11-01 (python 3.13.5 | pandas 3.1.0 | pyarrow 26.0.0 | requests 2.34.2). Result: 34195 places 243 country codes latest modification 2026-10-31

## Limits
- Download rate limit: Not stated.
- The checked allCountries ZIP was 403 MB compressed; cities15000 was 3.2 MB compressed.
- Dated change files describe the previous day's modifications and deletions.

## Quirks
- The text files have no header row; supply the readme's column order explicitly.
- Use alternateNamesV2.zip when language codes and validity dates are needed; the older alternateNames.zip is marked obsolete.
- The alternatenames column in the main geoname table is a shortened convenience field and does not replace the language-aware alternate-name table.

## Terms and attribution
- The data is licensed under Creative Commons Attribution 4.0 and commercial use is allowed.
- Credit GeoNames with a link or another reference.
- The provider supplies the data as is without accuracy, timeliness or completeness warranties.
- Terms page: https://www.geonames.org/export/#terms

## Sources
- https://download.geonames.org/export/dump/readme.txt: "This work is licensed under a Creative Commons Attribution 4.0 License,"
- https://download.geonames.org/export/dump/readme.txt: "allCountries.zip         : all countries combined in one file, see 'geoname' table for columns"
- https://www.geonames.org/export/: "GeoNames data is free, the data is available without costs."
- https://www.geonames.org/export/: "You should give credit to GeoNames when using data or web services with a link or another reference to GeoNames."

## Help improve this skill
Missing a source, or see something to improve? Call the MCP tool suggest_source or feedback (or POST /api/suggest or /api/feedback). Reviewed ideas: https://signal-lab-jet.vercel.app/agent-suggestions

Information for educational purposes only. Free tiers, limits and licenses belong to the providers and may change; check the provider's own terms before using the data.
