# Location search

Three lookups for a birthplace field: from a name to coordinates and the time zone, from coordinates to the nearest place, and from a point and a date to the offset the clocks kept that day. All three answer from the GeoNames geographical database and the IANA time zone database.

## Search by name

```http
GET /v1/geo/search?q=Kiev&lang=uk&limit=5 HTTP/1.1
X-Api-Key: aw_live_...
```

- `q`: required, the name or its beginning, in any of our languages and scripts. Case, accents and punctuation do not matter: `krakow` finds Kraków, `St. Petersburg` finds Saint Petersburg, `Kiev` and `Київ` find Kyiv.
- Text after the first comma narrows by region or country instead of matching the name: `Springfield, Illinois`, `Springfield, MA`, `Paris, US`.
- `lang`: optional, one of the 21 site languages. Names the place, region and country in that language where the data has the name. Matching covers every language whatever you pass.
- `limit`: 1 to 50, 10 by default.
- `country`: optional, ISO 3166-1 alpha-2 codes, comma separated, up to 20: `country=UA,PL`.

```json
{
  "query": "Kiev",
  "lang": "uk",
  "count": 1,
  "results": [
    {
      "id": 703448,
      "name": "Київ",
      "originalName": "Kyiv",
      "admin1": "Місто Київ",
      "admin1Code": "12",
      "countryCode": "UA",
      "country": "Україна",
      "latitude": 50.4547,
      "longitude": 30.5238,
      "timezone": "Europe/Kyiv",
      "population": 2952301,
      "featureCode": "PPLC",
      "matchedName": "Kiev",
      "exact": true
    }
  ],
  "note": "Populated places of 1000 people or more and administrative seats. A smaller place is absent, not misspelled.",
  "dataset": { "source": "GeoNames cities1000", "licence": "CC BY 4.0", "downloaded": "2026-11-07", "count": 171800 },
  "attribution": { "source": "GeoNames", "licence": "CC BY 4.0", "notice": "..." }
}
```

- `id` is the GeoNames identifier: stable, safe to store.
- `originalName` appears only when `name` is a translation.
- `matchedName` is the form your query matched, for example the older `Kiev`; `exact` says whether it matched the whole name or only its beginning.
- `featureCode` is the GeoNames class: `PPLC` a capital, `PPLA` the seat of a first-level region, `PPLX` a section of a city.

Results are ranked by population, and a whole-name match counts ten times its size: an ambiguous name such as Springfield lists every town of that name largest first, and `kyi` puts Kyiv above a village called Kyi.

Pass `latitude`, `longitude` and `timezone` from the result straight into a chart. `timezone` takes the zone name, and the API works out the offset for the birth date itself.

## Nearest place to a point

```http
GET /v1/geo/reverse?lat=49.8397&lon=24.0297&lang=en HTTP/1.1
X-Api-Key: aw_live_...
```

```json
{
  "latitude": 49.8397,
  "longitude": 24.0297,
  "timezone": "Europe/Kyiv",
  "nautical": false,
  "place": { "id": 702550, "name": "Lviv", "countryCode": "UA", "timezone": "Europe/Kyiv", "featureCode": "PPLA", "distanceKm": 0.5 }
}
```

`timezone` is the zone of the point itself, which near a border can differ from the place's. The search is by great-circle distance and works across the 180th meridian and at the poles. At sea `nautical` is `true` and the zone is the nautical hour band, for example `Etc/GMT+2`, which is UTC-2: the sign in these names is inverted by convention. `place.distanceKm` tells you how far land is.

## Offset on a date

```http
GET /v1/geo/timezone?lat=50.45&lon=30.52&date=1990-05-15&time=15:30 HTTP/1.1
X-Api-Key: aw_live_...
```

```json
{ "timezone": "Europe/Kyiv", "date": "1990-05-15", "time": "15:30", "utcOffset": 4, "utcOffsetText": "+04:00", "standardOffset": 3, "isDst": true, "nautical": false }
```

The offset comes from the time zone database for that date, never from a fixed table: Kyiv answers +2 in January, +3 in July and +4 in May 1990, when it kept Moscow summer time. `date` is today by default, `time` is 12:00 and matters only on the day clocks change: an hour that was skipped resolves to the offset from before the change, an hour that happened twice to its first occurrence. Before 1970 the database is not reliable everywhere; if you know what the local clock read, send `timezoneOffset` to the chart.

## Without a key, for widgets

```http
GET /v1/public/geo/search?q=Kiev&lang=uk&limit=5 HTTP/1.1
```

The same search answers without a key for a birthplace field on a public page. It counts against the public limit of 30 requests an hour per visitor address, so send the request when the visitor pauses typing rather than on every key. The answer may be cached for a day. Reverse lookup and the offset on a date need a key; for a browser, use a publishable key limited to `geo/*`.

## What is covered

About 172 000 places: every populated place of 1000 people or more, plus seats of administrative regions. A smaller village is absent rather than misspelled, so offer the nearest town or let the user enter coordinates. Names are the ones GeoNames carries in our languages; where a language has no name, the GeoNames name is returned.

## Attribution

Place data is from [GeoNames](https://www.geonames.org/) under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). If you show these names or coordinates to your users, carry the same credit: it comes in every answer as `attribution`.

## Price

`/v1/geo/search`, `/v1/geo/reverse` and `/v1/geo/timezone` cost 5 credits each.

The keyless search spends no credits and has the public limit instead.
