Lookup

Find the time zone at any latitude and longitude, on land or at sea. The answer carries the same timezone block as Retrieve a time zone, so one call gives you the local time, the UTC offset and the next clock change.

At a glance

GET /v1/lookup?lat=48.8566&lon=2.3522
Parameter Required Description
lat yes Latitude in decimal degrees, from -90 to 90, like 40.7128.
lon yes Longitude in decimal degrees, from -180 to 180, like -74.006. lng works too; send only one.
at no Compute the times at this moment instead of now: an ISO 8601 datetime or a Unix timestamp.

Coordinates are rounded to 6 decimals, about 11 cm. Exponents, like the 5e-7 some languages write for small numbers, are read. Commas and spaces inside a number are rejected with a 422.

A datetime in at without an offset is read as UTC, not as local time at the point. Add Z or an offset, as in the example below.


Example — the local time at a delivery address

A courier app has the drop-off point's coordinates and needs the customer's local time:

curl "https://api.timezone.io/v1/lookup?lat=48.8566&lon=2.3522&at=2026-01-15T12:00:00Z" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
{
    "data": {
        "query": { "latitude": 48.8566, "longitude": 2.3522 },
        "kind": "land",
        "timezone": {
            "iana": "Europe/Paris",
            "display_name": "Paris",
            "observes_dst": true,
            "is_mainland": true,
            "coordinates": { "latitude": 48.86666, "longitude": 2.33333 },
            "country": { "code": "FR", "name": "France" },
            "current": {
                "datetime": "2026-01-15T13:00:00+01:00",
                "utc_datetime": "2026-01-15T12:00:00Z",
                "utc_offset": "+01:00",
                "utc_offset_seconds": 3600,
                "abbreviation": "CET",
                "name": "Central European Standard Time",
                "is_dst": false
            },
            "standard": {
                "utc_offset": "+01:00",
                "utc_offset_seconds": 3600,
                "abbreviation": "CET",
                "name": "Central European Standard Time"
            },
            "dst": {
                "savings_seconds": 3600,
                "next_transition": {
                    "type": "spring_forward",
                    "at": "2026-03-29T01:00:00Z",
                    "utc_offset_after": "+02:00",
                    "abbreviation_after": "CEST",
                    "clock_change_seconds": 3600
                }
            },
            "links": {
                "self": "https://api.timezone.io/v1/timezones/Europe/Paris",
                "country": "https://api.timezone.io/v1/countries/FR",
                "abbreviation": "https://api.timezone.io/v1/abbreviations/central-european-standard-time",
                "web": "https://timezone.io/iana/Europe/Paris"
            }
        },
        "alternatives": []
    },
    "meta": {
        "tzdb_version": "2026d",
        "generated_at": "2026-09-27T09:00:00+00:00",
        "boundaries": {
            "version": "2026d",
            "attribution": "Contains information from timezone-boundary-builder (https://github.com/evansiroky/timezone-boundary-builder), made available under the Open Database License (ODbL) 1.0 (https://opendatacommons.org/licenses/odbl/1-0/). Boundary data © OpenStreetMap contributors (https://www.openstreetmap.org/copyright)."
        }
    }
}

Where zones overlap

Where two zones' boundaries overlap, you get every zone: the one with the smallest area comes first, and the others are listed in alternatives with "reason": "overlap". Most overlaps are disputed areas. A few are narrow slivers along borders and coasts in the source data, where two maps don't quite meet; the widest is about 1 km. In three areas the smallest zone is not the administering authority's clock, so we put that authority's zone first: Xinjiang (Asia/Shanghai, +08, before Asia/Urumqi), Abkhazia (Europe/Moscow before Asia/Tbilisi) and Kalapani (Asia/Kolkata before Asia/Kathmandu). Ürümqi:

curl "https://api.timezone.io/v1/lookup?lat=43.8256&lon=87.6168" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
{
    "data": {
        "query": { "latitude": 43.8256, "longitude": 87.6168 },
        "kind": "land",
        "timezone": {
            "iana": "Asia/Shanghai",
            "display_name": "Shanghai",
            "observes_dst": false,
            "country": { "code": "CN", "name": "China" },
            "current": {
                "utc_offset": "+08:00",
                "abbreviation": "CST",
                "is_dst": false,
                "…": "…"
            },
            "…": "the full block, as above"
        },
        "alternatives": [
            {
                "reason": "overlap",
                "timezone": {
                    "iana": "Asia/Urumqi",
                    "display_name": "Urumqi",
                    "country": { "code": "CN", "name": "China" },
                    "current": {
                        "utc_offset": "+06:00",
                        "abbreviation": "+06",
                        "is_dst": false
                    },
                    "observes_dst": false,
                    "links": {
                        "self": "https://api.timezone.io/v1/timezones/Asia/Urumqi"
                    }
                }
            }
        ]
    }
}

The primary follows China's official UTC+08:00 time. Some residents also use local Xinjiang Time (UTC+06:00), returned as an alternative. Show both when it matters.

At sea

Outside any country's territorial waters (12 nautical miles from the coast), the answer is a nautical zone: Etc/GMT or Etc/GMT±N, each 15° of longitude wide, centred on multiples of 15°, except Etc/GMT+12 and Etc/GMT-12, which are 7.5° wide and meet at the 180th meridian. kind is "ocean", country and the links are null, and so are coordinates.latitude and .longitude.

curl "https://api.timezone.io/v1/lookup?lat=30&lon=-40" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
{
    "data": {
        "query": { "latitude": 30, "longitude": -40 },
        "kind": "ocean",
        "timezone": {
            "iana": "Etc/GMT+3",
            "display_name": "UTC-03:00 (international waters)",
            "observes_dst": false,
            "coordinates": { "latitude": null, "longitude": null },
            "country": null,
            "current": {
                "utc_offset": "-03:00",
                "abbreviation": "-03",
                "name": null,
                "…": "…"
            },
            "links": {
                "self": null,
                "country": null,
                "abbreviation": null,
                "web": null
            },
            "…": "…"
        },
        "alternatives": []
    }
}

The sign in these zone identifiers is inverted: Etc/GMT+3 is three hours behind UTC. That's an old Unix convention. Read current.utc_offset, which always uses the usual sign. Ships often keep another time in practice; this is the zone the map gives.

The same nautical zones cover the part of Antarctica no country claims, roughly 90°W to 150°W. South of 60°S, at sea or on that land, the label reads like UTC-08:00 (Antarctica) instead of "international waters". kind is still "ocean".

Response fields

Field Description
query.latitude, .longitude The point that was looked up, rounded to 6 decimals. 180 stays 180.
kind land (a country's territory, including territorial waters) or ocean (a nautical zone: international waters, and unclaimed Antarctica).
timezone The zone at the point, in the shape of Retrieve a time zone, computed at at.
alternatives Other zones for the same point, each with a reason. Empty for almost every point.
alternatives[].reason overlap: another zone's boundary also contains the point. antimeridian: the zone across the 180° line, when you send exactly lon=180 or -180.
alternatives[].timezone A short time-zone row, with current computed at at.
meta.boundaries Which boundary release answered (version), and the credit its licence asks for (attribution).

Borders and edge cases

  • On a border. A point exactly on a border belongs to the zone east of it, or north of it on an east–west border. At 6 decimals that strip is about 11 cm wide.
  • The 180th meridian. lon=180 and lon=-180 are both valid and never wrapped. Each answers for its own side, and lists the zone on the other side as an antimeridian alternative when it differs.
  • The poles. lat=90 returns Etc/GMT at every longitude, by convention. lat=-90 returns Antarctica/McMurdo, the zone that covers the South Pole.
  • The country is the zone's. timezone.country is the country the zone belongs to, not the country at your point. Northern Vietnam uses Asia/Bangkok, so its country is Thailand.
  • The coordinates are the zone's. timezone.coordinates is the zone's reference city; your point is in query.
  • Borders are today's. at moves the clock rules (past or future offsets and daylight saving), not the borders.
  • Maps can be wrong. Borders come from OpenStreetMap, and some communities near a border keep their neighbour's time.
  • Overlaps. Every zone whose boundary contains the point is returned; the smallest comes first, except in Xinjiang, Abkhazia and Kalapani, where the administering authority's zone does (see "Where zones overlap").

Caching

A point's zone only changes when meta.boundaries.version changes, a few times a year. You may cache the zone for a point and compute times yourself; call again when the version changes, or when you need our live current block.

Data and method

Boundaries come from timezone-boundary-builder's timezones-with-oceans release (the version is in meta.boundaries.version), which is built from OpenStreetMap. At launch that is release 2026d, file https://github.com/evansiroky/timezone-boundary-builder/releases/download/2026d/timezones-with-oceans.geojson.zip, sha256 e391c92c7b90339c3afe8558082b4532b8d9afc9daad68da31f4569a1ca61034. Later releases are checked against the sha256 digest GitHub publishes for them. We re-encode the data without loss, fill its gaps and index it:

  • coordinates × 10⁶ as 32-bit integers, with no simplification and no clipping;
  • a 1° grid of candidate zones, and 0.02° latitude bands of edges;
  • an even-odd ray-crossing test toward the east, where a point on an edge belongs to the zone east or north of it;
  • where zones overlap, every zone is returned, smallest area first. Area is the spherical area R²/2 · Σ(λ₂ − λ₁)(2 + sin φ₁ + sin φ₂) of each zone's outer rings minus its holes, with R = 6,371,008.8 m; equal areas are ordered by zone identifier. The index stores these areas. Three areas are the exception, listed above under "Where zones overlap": there the zone whose time is actually kept comes first;
  • the source can leave gaps between zones. A gap at least a millionth of a degree wide is filled from the neighbouring zone that shares the longest border with it, and we refuse to publish if a gap is wider than 1,000 millionths of a degree (about 110 m), which would mean a zone is missing (release 2026d has no such gap). Narrower slivers remain where a land border meets the edge of an ocean zone and the ocean zone's copy of that border was rounded a few centimetres away from it; no polygon drawn on the millionth-of-a-degree grid can close them, so we check, for every such sliver, that the nautical zone for its longitude is the zone next to it, and refuse to publish otherwise. A point in one of them gets that nautical zone.

Contains information from timezone-boundary-builder (https://github.com/evansiroky/timezone-boundary-builder), made available under the Open Database License (ODbL) 1.0. Boundary data © OpenStreetMap contributors.