A small, stable JSON API for the things this site computes: the time now in any zone, conversions between zones, and daylight-saving transitions. No SDK, no sign-up for light use; a free key when you need more than 60 requests a minute.
Authentication
Anonymous requests are allowed and limited per IP. For a higher limit, create a key in your account and send it as a bearer token:
Authorization: Bearer tz_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys are stored hashed; we cannot show a key again after creation — revoke and create a new one if lost. A request with a revoked or malformed key is rejected with 401 invalid_key rather than silently falling back to anonymous, so you notice.
Rate limits
60 requests per minute per IP without a key; 600 per minute per key. Every response carries x-ratelimit-limit, x-ratelimit-remaining and x-ratelimit-reset (seconds until the window resets). Over the limit you get 429 with a retry-after header. Cache /v1/timezones on your side — it changes only when the IANA database does — and compute between calls to /v1/now rather than polling it.
Zone identifiers
Every endpoint that takes a zone accepts an IANA name (America/New_York), a legacy alias (Asia/Calcutta), or a common abbreviation (EST, IST, GMT). Abbreviations are ambiguous — IST is India, Ireland and Israel — so they resolve to the zone people usually mean (India for IST, New York for EST). Use IANA names in anything automated.
Endpoints
GET/v1/timezones
The full catalogue: every zone with its alternative name, abbreviation, country, main cities and current offset.
Request
curl "https://api.timezones.in/v1/timezones"
Response 200
[
{
"name": "Asia/Kolkata",
"alternativeName": "India Time",
"abbreviation": "IST",
"countryCode": "IN",
"countryName": "India",
"continentCode": "AS",
"mainCities": ["Mumbai", "Delhi", "Bengaluru", "Kolkata"],
"rawOffsetInMinutes": 330,
"currentTimeOffsetInMinutes": 330,
"currentTimeFormat": "+05:30 India Time - Mumbai, Delhi"
},
…
]GET/v1/timezones/:name
One zone with the time now and its next offset change (null when the zone never changes).
| Parameter | In | Meaning |
|---|---|---|
| name | path | IANA name, alias or abbreviation. Slashes may be sent as-is or URL-encoded. |
Request
curl "https://api.timezones.in/v1/timezones/Europe/London"
Response 200
{
"name": "Europe/London",
"alternativeName": "United Kingdom Time",
"abbreviation": "GMT",
"countryCode": "GB",
"mainCities": ["London", "Birmingham", "Glasgow"],
"now": {
"zone": "Europe/London",
"iso": "2026-09-06T14:05:12.000+01:00",
"offsetMinutes": 60,
"offset": "+01:00",
"abbreviation": "BST",
"isDST": true,
"epochMs": 1788699912000
},
"nextTransition": {
"at": "2026-10-25T01:00:00.000Z",
"localBefore": "2026-10-25T01:59",
"localAfter": "2026-10-25T01:00",
"offsetBeforeMinutes": 60,
"offsetAfterMinutes": 0,
"direction": "back",
"abbreviationBefore": "BST",
"abbreviationAfter": "GMT"
}
}GET/v1/now
Current time in up to 50 zones in one call.
| Parameter | In | Meaning |
|---|---|---|
| zones | query | Comma-separated zone identifiers. Default UTC. Maximum 50. |
Request
curl "https://api.timezones.in/v1/now?zones=Asia/Kolkata,America/New_York"
Response 200
{
"utc": "2026-09-06T13:05:12.000Z",
"zones": [
{ "zone": "Asia/Kolkata", "iso": "2026-09-06T18:35:12.000+05:30", "offsetMinutes": 330, "offset": "+05:30", "abbreviation": "IST", "isDST": false, "epochMs": 1788699912000, "offsetLabel": "UTC+5:30" },
{ "zone": "America/New_York", "iso": "2026-09-06T09:05:12.000-04:00", "offsetMinutes": -240, "offset": "-04:00", "abbreviation": "EDT", "isDST": true, "epochMs": 1788699912000, "offsetLabel": "UTC-4" }
]
}GET/v1/convert
Convert a wall-clock time in one zone to another. Omit `at` for right now.
| Parameter | In | Meaning |
|---|---|---|
| from | query | Source zone. |
| to | query | Target zone. |
| at | query | Optional local date-time in the source zone, ISO 8601 without an offset, e.g. 2026-03-10T09:30. |
Request
curl "https://api.timezones.in/v1/convert?from=Asia/Kolkata&to=Europe/London&at=2026-03-10T09:30"
Response 200
{
"from": { "zone": "Asia/Kolkata", "iso": "2026-03-10T09:30:00.000+05:30", "offset": "+05:30", "abbreviation": "IST" },
"to": { "zone": "Europe/London", "iso": "2026-03-10T04:00:00.000+00:00", "offset": "+00:00", "abbreviation": "GMT" },
"differenceMinutes": -330
}GET/v1/transitions/:zone
The next N UTC-offset changes for a zone, to the minute. Empty list for zones without daylight saving.
| Parameter | In | Meaning |
|---|---|---|
| zone | path | Zone identifier. |
| count | query | How many transitions to return. 1–10, default 2. |
Request
curl "https://api.timezones.in/v1/transitions/America/New_York?count=2"
Response 200
{
"zone": "America/New_York",
"transitions": [
{ "at": "2026-11-01T06:00:00.000Z", "localBefore": "2026-11-01T01:59", "localAfter": "2026-11-01T01:00", "offsetBeforeMinutes": -240, "offsetAfterMinutes": -300, "direction": "back", "abbreviationBefore": "EDT", "abbreviationAfter": "EST" },
{ "at": "2027-03-14T07:00:00.000Z", "localBefore": "2027-03-14T01:59", "localAfter": "2027-03-14T03:00", "offsetBeforeMinutes": -300, "offsetAfterMinutes": -240, "direction": "forward", "abbreviationBefore": "EST", "abbreviationAfter": "EDT" }
]
}Errors
| Status | error | When |
|---|---|---|
| 400 | unknown_zone | A zone identifier could not be resolved. The body lists the offending values where there are several. |
| 400 | bad_request | `at` is not a valid ISO 8601 date-time. |
| 400 | validation | A parameter is missing or the wrong shape. |
| 401 | invalid_key | An Authorization header is present but the key is malformed or revoked. |
| 404 | unknown_zone | Path zone (/v1/timezones/:name, /v1/transitions/:zone) does not exist. |
| 429 | — | Rate limit exceeded. Wait `retry-after` seconds. |
| 503 | unavailable | The API is restarting. Retry after a few seconds. |
Error bodies are always { "error": "<code>", "message": "<human-readable>" }.
Examples
JavaScript
const res = await fetch("https://api.timezones.in/v1/convert?from=Asia/Kolkata&to=America/New_York&at=2026-01-15T09:00", {
headers: { Authorization: "Bearer tz_…" }, // optional
});
const { to, differenceMinutes } = await res.json();
console.log(to.iso, differenceMinutes); // "2026-01-14T22:30:00.000-05:00" -630Python
import requests
r = requests.get("https://api.timezones.in/v1/now", params={"zones": "Asia/Kolkata,Europe/London"},
headers={"Authorization": "Bearer tz_…"})
for z in r.json()["zones"]:
print(z["zone"], z["iso"], z["abbreviation"])Data and accuracy
Zone rules come from the IANA tz database through ICU and are updated with each release; the catalogue (names, cities) comes from @vvo/tzdb. Transitions are computed to the minute. Governments change rules at short notice, so do not rely on this for anything where a wrong time causes harm. Report an error via the contact form.
Versioning and terms
The /v1 contract is stable: fields may be added, never removed or renamed. Free for personal and commercial use under the terms of use; do not resell raw access as your own service without attribution. “Data from timezones.in” is appreciated, not required.
