lat float required Observer latitude in WGS 84 decimal degrees, positive north (−90 to 90).
Sunrise, sunset, solar noon, day length, the three twilights and solar elevation/azimuth for any coordinate and date, from the NOAA equations.
Authoritative reference data or standards computation
date is a local civil date in tz; omit it for today in that zone. All events are anchored to the solar noon of that local date, so sunrise always precedes solar noon and solar noon always precedes sunset.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
lat
required
| float | allowed: -90 – 90 example: 55.6761 | Observer latitude in WGS 84 decimal degrees, positive north (−90 to 90). |
lng
required
| float | allowed: -180 – 180 example: 12.5683 | Observer longitude in WGS 84 decimal degrees, positive east (−180 to 180). |
date | date | example: 2026-06-21 | Local civil date (YYYY-MM-DD) in the resolved zone, years 1900–2100. Defaults to today in that zone. An RFC 3339 timestamp is accepted too and is reduced to the local civil date that instant falls on in `tz` — except at exactly 00:00 UTC, which is indistinguishable from the bare date and is read as that calendar date. |
tz | string | default: UTC example: Europe/Copenhagen | IANA zone used to resolve the local civil date and to render every `local` wall clock, case-insensitive. Unknown ids return a 400 — browse them at /api/timezones. |
lat float required Observer latitude in WGS 84 decimal degrees, positive north (−90 to 90).
lng float required Observer longitude in WGS 84 decimal degrees, positive east (−180 to 180).
date date Local civil date (YYYY-MM-DD) in the resolved zone, years 1900–2100. Defaults to today in that zone. An RFC 3339 timestamp is accepted too and is reduced to the local civil date that instant falls on in `tz` — except at exactly 00:00 UTC, which is indistinguishable from the bare date and is read as that calendar date.
tz string IANA zone used to resolve the local civil date and to render every `local` wall clock, case-insensitive. Unknown ids return a 400 — browse them at /api/timezones.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
fields | list | example: date,timezone | Return only these fields (comma-separated). Mutually exclusive with 'exclude'. |
exclude | list | example: astronomicalDusk | Return all fields except these (comma-separated). |
pretty | boolean | default: false example: true | Pretty-print the JSON response. |
unwrap | boolean | default: false example: true | Drop the envelope: return the raw array/object without data/meta wrapper. |
fields list Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude list Return all fields except these (comma-separated).
pretty boolean Pretty-print the JSON response.
unwrap boolean Drop the envelope: return the raw array/object without data/meta wrapper.
| Field | Type | Description | Example |
|---|---|---|---|
date | string (YYYY-MM-DD) | The local civil date the results describe, in the resolved zone. On the rare date that contains no solar transit at all — where local solar noon sits within seconds of local midnight — the events are anchored to the nearest transit and `meta.warnings` names the date it falls on. | 2026-06-21 |
timezone | string | Canonical IANA id applied to the local date and every `local` wall clock. | Europe/Copenhagen |
latitude | float | Observer latitude in decimal degrees, echoed as supplied. | 55.6761 |
longitude | float | Observer longitude in decimal degrees, echoed as supplied. | 12.5683 |
solarNoon | object | Meridian transit — the Sun's highest point of the local day. Always present, so `reason` is always null here. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null. | {"instant":"2026-06-21T11:11:33.000Z","local":"2026-06-21T13:11:33","reason":null} |
sunrise | object | Sun's centre crossing the −0.833° horizon while rising. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null. | {"instant":"2026-06-21T02:25:20.000Z","local":"2026-06-21T04:25:20","reason":null} |
sunset | object | Sun's centre crossing the −0.833° horizon while setting. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null. | {"instant":"2026-06-21T19:57:45.000Z","local":"2026-06-21T21:57:45","reason":null} |
dayLengthSeconds | integer (0-86400) | Seconds the Sun spends above the −0.833° horizon on this solar day: exactly the gap between the returned sunrise and sunset instants when both exist, 86400 through a polar day and 0 through a polar night. On the changeover day, where only one of the two crossings happens, the measured half is added to the full 12 hours on the side the Sun never sets or never rises. | 63145 |
civilDawn | object | Sun's centre reaching 6° below the horizon while rising. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null. | {"instant":"2026-06-21T01:24:09.000Z","local":"2026-06-21T03:24:09","reason":null} |
civilDusk | object | Sun's centre reaching 6° below the horizon while setting. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null. | {"instant":"2026-06-21T20:58:55.000Z","local":"2026-06-21T22:58:55","reason":null} |
nauticalDawn | object | Sun's centre reaching 12° below the horizon while rising. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null. | {"instant":null,"local":null,"reason":"polar-day"} |
nauticalDusk | object | Sun's centre reaching 12° below the horizon while setting. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null. | {"instant":null,"local":null,"reason":"polar-day"} |
astronomicalDawn | object | Sun's centre reaching 18° below the horizon while rising. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null. | {"instant":null,"local":null,"reason":"polar-day"} |
astronomicalDusk | object | Sun's centre reaching 18° below the horizon while setting. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null. | {"instant":null,"local":null,"reason":"polar-day"} |
date string (YYYY-MM-DD) The local civil date the results describe, in the resolved zone. On the rare date that contains no solar transit at all — where local solar noon sits within seconds of local midnight — the events are anchored to the nearest transit and `meta.warnings` names the date it falls on.
example: 2026-06-21
timezone string Canonical IANA id applied to the local date and every `local` wall clock.
example: Europe/Copenhagen
latitude float Observer latitude in decimal degrees, echoed as supplied.
example: 55.6761
longitude float Observer longitude in decimal degrees, echoed as supplied.
example: 12.5683
solarNoon object Meridian transit — the Sun's highest point of the local day. Always present, so `reason` is always null here. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null.
example: {"instant":"2026-06-21T11:11:33.000Z","local":"2026-06-21T13:11:33","reason":null}
sunrise object Sun's centre crossing the −0.833° horizon while rising. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null.
example: {"instant":"2026-06-21T02:25:20.000Z","local":"2026-06-21T04:25:20","reason":null}
sunset object Sun's centre crossing the −0.833° horizon while setting. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null.
example: {"instant":"2026-06-21T19:57:45.000Z","local":"2026-06-21T21:57:45","reason":null}
dayLengthSeconds integer (0-86400) Seconds the Sun spends above the −0.833° horizon on this solar day: exactly the gap between the returned sunrise and sunset instants when both exist, 86400 through a polar day and 0 through a polar night. On the changeover day, where only one of the two crossings happens, the measured half is added to the full 12 hours on the side the Sun never sets or never rises.
example: 63145
civilDawn object Sun's centre reaching 6° below the horizon while rising. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null.
example: {"instant":"2026-06-21T01:24:09.000Z","local":"2026-06-21T03:24:09","reason":null}
civilDusk object Sun's centre reaching 6° below the horizon while setting. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null.
example: {"instant":"2026-06-21T20:58:55.000Z","local":"2026-06-21T22:58:55","reason":null}
nauticalDawn object Sun's centre reaching 12° below the horizon while rising. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null.
example: {"instant":null,"local":null,"reason":"polar-day"}
nauticalDusk object Sun's centre reaching 12° below the horizon while setting. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null.
example: {"instant":null,"local":null,"reason":"polar-day"}
astronomicalDawn object Sun's centre reaching 18° below the horizon while rising. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null.
example: {"instant":null,"local":null,"reason":"polar-day"}
astronomicalDusk object Sun's centre reaching 18° below the horizon while setting. Object with `instant` (UTC ISO 8601, whole seconds), `local` (naive wall clock in `tz`) and `reason`. On a normal day `reason` is null; when the crossing does not happen it is `polar-day` (the Sun stays above this altitude all day) or `polar-night` (it stays below), and both times are null.
example: {"instant":null,"local":null,"reason":"polar-day"}
/api/sun/times?lat=55.6761&lng=12.5683&date=2026-06-21&tz=Europe/Copenhagen {
"data": {
"date": "2026-06-21",
"timezone": "Europe/Copenhagen",
"latitude": 55.6761,
"longitude": 12.5683,
"solarNoon": {
"instant": "2026-06-21T11:11:33.000Z",
"local": "2026-06-21T13:11:33",
"reason": null
},
"sunrise": {
"instant": "2026-06-21T02:25:20.000Z",
"local": "2026-06-21T04:25:20",
"reason": null
},
"sunset": {
"instant": "2026-06-21T19:57:45.000Z",
"local": "2026-06-21T21:57:45",
"reason": null
},
"dayLengthSeconds": 63145,
"civilDawn": {
"instant": "2026-06-21T01:24:09.000Z",
"local": "2026-06-21T03:24:09",
"reason": null
},
"civilDusk": {
"instant": "2026-06-21T20:58:55.000Z",
"local": "2026-06-21T22:58:55",
"reason": null
},
"nauticalDawn": {
"instant": null,
"local": null,
"reason": "polar-day"
},
"nauticalDusk": {
"instant": null,
"local": null,
…
"generatedAt": "2026-07-30T15:14:08.000Z"
}
} /api/sun/times?lat=-0.1807&lng=-78.4678&date=2026-03-20&tz=America/Guayaquil {
"data": {
"date": "2026-03-20",
"timezone": "America/Guayaquil",
"latitude": -0.1807,
"longitude": -78.4678,
"solarNoon": {
"instant": "2026-03-20T17:21:14.000Z",
"local": "2026-03-20T12:21:14",
"reason": null
},
"sunrise": {
"instant": "2026-03-20T11:17:59.000Z",
"local": "2026-03-20T06:17:59",
"reason": null
},
"sunset": {
"instant": "2026-03-20T23:24:30.000Z",
"local": "2026-03-20T18:24:30",
"reason": null
},
"dayLengthSeconds": 43591,
"civilDawn": {
"instant": "2026-03-20T10:57:19.000Z",
"local": "2026-03-20T05:57:19",
"reason": null
},
"civilDusk": {
"instant": "2026-03-20T23:45:09.000Z",
"local": "2026-03-20T18:45:09",
"reason": null
},
"nauticalDawn": {
"instant": "2026-03-20T10:33:19.000Z",
"local": "2026-03-20T05:33:19",
"reason": null
},
"nauticalDusk": {
"instant": "2026-03-21T00:09:09.000Z",
"local": "2026-03-20T19:09:09",
…
"generatedAt": "2026-07-30T15:14:08.000Z"
}
} /api/sun/times?lat=69.6492&lng=18.9553&date=2026-12-21&tz=Europe/Oslo {
"data": {
"date": "2026-12-21",
"timezone": "Europe/Oslo",
"latitude": 69.6492,
"longitude": 18.9553,
"solarNoon": {
"instant": "2026-12-21T10:42:14.000Z",
"local": "2026-12-21T11:42:14",
"reason": null
},
"sunrise": {
"instant": null,
"local": null,
"reason": "polar-night"
},
"sunset": {
"instant": null,
"local": null,
"reason": "polar-night"
},
"dayLengthSeconds": 0,
"civilDawn": {
"instant": "2026-12-21T08:31:13.000Z",
"local": "2026-12-21T09:31:13",
"reason": null
},
"civilDusk": {
"instant": "2026-12-21T12:53:13.000Z",
"local": "2026-12-21T13:53:13",
"reason": null
},
"nauticalDawn": {
"instant": "2026-12-21T06:46:42.000Z",
"local": "2026-12-21T07:46:42",
"reason": null
},
"nauticalDusk": {
"instant": "2026-12-21T14:37:45.000Z",
"local": "2026-12-21T15:37:45",
…
"generatedAt": "2026-07-30T15:14:08.000Z"
}
} /api/sun/times?lat=35.6762&lng=139.6503&tz=Asia/Tokyo {
"data": {
"date": "2026-07-31",
"timezone": "Asia/Tokyo",
"latitude": 35.6762,
"longitude": 139.6503,
"solarNoon": {
"instant": "2026-07-31T02:47:50.000Z",
"local": "2026-07-31T11:47:50",
"reason": null
},
"sunrise": {
"instant": "2026-07-30T19:48:17.000Z",
"local": "2026-07-31T04:48:17",
"reason": null
},
"sunset": {
"instant": "2026-07-31T09:46:55.000Z",
"local": "2026-07-31T18:46:55",
"reason": null
},
"dayLengthSeconds": 50318,
"civilDawn": {
"instant": "2026-07-30T19:20:03.000Z",
"local": "2026-07-31T04:20:03",
"reason": null
},
"civilDusk": {
"instant": "2026-07-31T10:15:04.000Z",
"local": "2026-07-31T19:15:04",
"reason": null
},
"nauticalDawn": {
"instant": "2026-07-30T18:45:44.000Z",
"local": "2026-07-31T03:45:44",
"reason": null
},
"nauticalDusk": {
"instant": "2026-07-31T10:49:16.000Z",
"local": "2026-07-31T19:49:16",
…
"generatedAt": "2026-07-30T15:14:08.000Z"
}
} at is an absolute instant (date-only means UTC midnight); omit it for now. Elevation is geometric — no refraction correction is applied to it.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
lat
required
| float | allowed: -90 – 90 example: 55.6761 | Observer latitude in WGS 84 decimal degrees, positive north (−90 to 90). |
lng
required
| float | allowed: -180 – 180 example: 12.5683 | Observer longitude in WGS 84 decimal degrees, positive east (−180 to 180). |
at | date | example: 2026-06-21T12:00:00Z | Absolute instant: YYYY-MM-DD (UTC midnight) or RFC 3339 with Z or an explicit offset, years 1900–2100. Defaults to now. |
tz | string | default: UTC example: Europe/Copenhagen | IANA zone used only to render `localTime`, case-insensitive. It does not move the instant; unknown ids return a 400. |
lat float required Observer latitude in WGS 84 decimal degrees, positive north (−90 to 90).
lng float required Observer longitude in WGS 84 decimal degrees, positive east (−180 to 180).
at date Absolute instant: YYYY-MM-DD (UTC midnight) or RFC 3339 with Z or an explicit offset, years 1900–2100. Defaults to now.
tz string IANA zone used only to render `localTime`, case-insensitive. It does not move the instant; unknown ids return a 400.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
fields | list | example: at,timezone | Return only these fields (comma-separated). Mutually exclusive with 'exclude'. |
exclude | list | example: isDaylight | Return all fields except these (comma-separated). |
pretty | boolean | default: false example: true | Pretty-print the JSON response. |
unwrap | boolean | default: false example: true | Drop the envelope: return the raw array/object without data/meta wrapper. |
fields list Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude list Return all fields except these (comma-separated).
pretty boolean Pretty-print the JSON response.
unwrap boolean Drop the envelope: return the raw array/object without data/meta wrapper.
| Field | Type | Description | Example |
|---|---|---|---|
at | string (ISO 8601 UTC) | The evaluated instant in UTC. | 2026-06-21T12:00:00.000Z |
timezone | string | Canonical IANA id used to render localTime. | Europe/Copenhagen |
localTime | string (YYYY-MM-DDTHH:mm:ss) | Naive local wall clock of the same instant in `timezone`. | 2026-06-21T14:00:00 |
elevationDegrees | float (-90 to 90) | Geometric elevation of the Sun's centre above the true horizon. No atmospheric refraction correction is applied, so near the horizon the apparent Sun sits about 0.57° higher than this figure. | 56.5453 |
azimuthDegrees | float (0 to 360) | Compass bearing of the Sun, 0° = north increasing clockwise. Within ~0.06° of the zenith or of a pole the bearing is geometrically undefined and NOAA's meridian convention is reported instead: 180 for an observer north of the equator, 0 otherwise. | 200.4393 |
declinationDegrees | float (-23.5 to 23.5) | Apparent solar declination at the instant. | 23.4381 |
equationOfTimeMinutes | float | Apparent solar time minus mean solar time, in minutes (roughly −14 to +16 over a year). | -1.8243 |
hourAngleDegrees | float (-180 to 180) | Local hour angle of the Sun: 0 at solar noon, negative before it, positive after, 15° per hour. | 12.1122 |
isDaylight | boolean | True when elevationDegrees is above the −0.833° horizon that /times uses for sunrise and sunset, so the two routes agree. | true |
at string (ISO 8601 UTC) The evaluated instant in UTC.
example: 2026-06-21T12:00:00.000Z
timezone string Canonical IANA id used to render localTime.
example: Europe/Copenhagen
localTime string (YYYY-MM-DDTHH:mm:ss) Naive local wall clock of the same instant in `timezone`.
example: 2026-06-21T14:00:00
elevationDegrees float (-90 to 90) Geometric elevation of the Sun's centre above the true horizon. No atmospheric refraction correction is applied, so near the horizon the apparent Sun sits about 0.57° higher than this figure.
example: 56.5453
azimuthDegrees float (0 to 360) Compass bearing of the Sun, 0° = north increasing clockwise. Within ~0.06° of the zenith or of a pole the bearing is geometrically undefined and NOAA's meridian convention is reported instead: 180 for an observer north of the equator, 0 otherwise.
example: 200.4393
declinationDegrees float (-23.5 to 23.5) Apparent solar declination at the instant.
example: 23.4381
equationOfTimeMinutes float Apparent solar time minus mean solar time, in minutes (roughly −14 to +16 over a year).
example: -1.8243
hourAngleDegrees float (-180 to 180) Local hour angle of the Sun: 0 at solar noon, negative before it, positive after, 15° per hour.
example: 12.1122
isDaylight boolean True when elevationDegrees is above the −0.833° horizon that /times uses for sunrise and sunset, so the two routes agree.
example: true
/api/sun/position?lat=55.6761&lng=12.5683&at=2026-06-21T12:00:00Z&tz=Europe/Copenhagen {
"data": {
"at": "2026-06-21T12:00:00.000Z",
"timezone": "Europe/Copenhagen",
"localTime": "2026-06-21T14:00:00",
"elevationDegrees": 56.5453,
"azimuthDegrees": 200.4393,
"declinationDegrees": 23.4381,
"equationOfTimeMinutes": -1.8243,
"hourAngleDegrees": 12.1122,
"isDaylight": true
},
"meta": {
"endpoint": "sun",
"route": "/position",
"params": {
"lat": 55.6761,
"lng": 12.5683,
"at": "2026-06-21T12:00:00.000Z",
"tz": "Europe/Copenhagen"
},
"generatedAt": "2026-07-30T15:14:08.000Z"
}
} /api/sun/position?lat=69.6492&lng=18.9553&at=2026-06-21T22:45:00Z&tz=Europe/Oslo {
"data": {
"at": "2026-06-21T22:45:00.000Z",
"timezone": "Europe/Oslo",
"localTime": "2026-06-22T00:45:00",
"elevationDegrees": 3.0863,
"azimuthDegrees": 359.7472,
"declinationDegrees": 23.4369,
"equationOfTimeMinutes": -1.9216,
"hourAngleDegrees": 179.7249,
"isDaylight": true
},
"meta": {
"endpoint": "sun",
"route": "/position",
"params": {
"lat": 69.6492,
"lng": 18.9553,
"at": "2026-06-21T22:45:00.000Z",
"tz": "Europe/Oslo"
},
"generatedAt": "2026-07-30T15:14:08.000Z"
}
} /api/sun/position?lat=-33.8688&lng=151.2093&tz=Australia/Sydney {
"data": {
"at": "2026-07-30T15:14:08.000Z",
"timezone": "Australia/Sydney",
"localTime": "2026-07-31T01:14:08",
"elevationDegrees": -67.6183,
"azimuthDegrees": 129.1672,
"declinationDegrees": 18.3986,
"equationOfTimeMinutes": -6.4635,
"hourAngleDegrees": -161.8733,
"isDaylight": false
},
"meta": {
"endpoint": "sun",
"route": "/position",
"params": {
"lat": -33.8688,
"lng": 151.2093,
"tz": "Australia/Sydney",
"at": "2026-07-30T15:14:08.000Z"
},
"generatedAt": "2026-07-30T15:14:08.000Z"
}
} Meeus chapter 27 (mean expressions plus the 24 periodic corrections of table 27.C). The Terrestrial-Time result is converted to UTC with the Espenak & Meeus ΔT polynomials, and the ΔT applied is returned per event.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
year | int | allowed: 1900 – 2100 example: 2026 | Calendar year (1900–2100). Defaults to the current year in the resolved zone. |
tz | string | default: UTC example: Europe/Copenhagen | IANA zone used to render each `local` wall clock and to resolve the default year, case-insensitive. Unknown ids return a 400. |
year int Calendar year (1900–2100). Defaults to the current year in the resolved zone.
tz string IANA zone used to render each `local` wall clock and to resolve the default year, case-insensitive. Unknown ids return a 400.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
fields | list | example: year,timezone | Return only these fields (comma-separated). Mutually exclusive with 'exclude'. |
exclude | list | example: decemberSolstice | Return all fields except these (comma-separated). |
pretty | boolean | default: false example: true | Pretty-print the JSON response. |
unwrap | boolean | default: false example: true | Drop the envelope: return the raw array/object without data/meta wrapper. |
fields list Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude list Return all fields except these (comma-separated).
pretty boolean Pretty-print the JSON response.
unwrap boolean Drop the envelope: return the raw array/object without data/meta wrapper.
| Field | Type | Description | Example |
|---|---|---|---|
year | integer | Calendar year the four instants belong to. | 2026 |
timezone | string | Canonical IANA id used to render every `local` wall clock. | UTC |
marchEquinox | object | March (northward) equinox: `instant` in UTC, `local` wall clock in `tz`, and `deltaTSeconds`, the TT−UT offset applied. | {"instant":"2026-03-20T14:45:30.000Z","local":"2026-03-20T14:45:30","deltaTSeconds":75.2} |
juneSolstice | object | June (northern summer) solstice, in the same shape as marchEquinox. | {"instant":"2026-06-21T08:24:49.000Z","local":"2026-06-21T08:24:49","deltaTSeconds":75.4} |
septemberEquinox | object | September (southward) equinox, in the same shape as marchEquinox. | {"instant":"2026-09-23T00:05:24.000Z","local":"2026-09-23T00:05:24","deltaTSeconds":75.5} |
decemberSolstice | object | December (northern winter) solstice, in the same shape as marchEquinox. | {"instant":"2026-12-21T20:50:07.000Z","local":"2026-12-21T20:50:07","deltaTSeconds":75.7} |
year integer Calendar year the four instants belong to.
example: 2026
timezone string Canonical IANA id used to render every `local` wall clock.
example: UTC
marchEquinox object March (northward) equinox: `instant` in UTC, `local` wall clock in `tz`, and `deltaTSeconds`, the TT−UT offset applied.
example: {"instant":"2026-03-20T14:45:30.000Z","local":"2026-03-20T14:45:30","deltaTSeconds":75.2}
juneSolstice object June (northern summer) solstice, in the same shape as marchEquinox.
example: {"instant":"2026-06-21T08:24:49.000Z","local":"2026-06-21T08:24:49","deltaTSeconds":75.4}
septemberEquinox object September (southward) equinox, in the same shape as marchEquinox.
example: {"instant":"2026-09-23T00:05:24.000Z","local":"2026-09-23T00:05:24","deltaTSeconds":75.5}
decemberSolstice object December (northern winter) solstice, in the same shape as marchEquinox.
example: {"instant":"2026-12-21T20:50:07.000Z","local":"2026-12-21T20:50:07","deltaTSeconds":75.7}
/api/sun/seasons?year=2026 {
"data": {
"year": 2026,
"timezone": "UTC",
"marchEquinox": {
"instant": "2026-03-20T14:45:30.000Z",
"local": "2026-03-20T14:45:30",
"deltaTSeconds": 75.2
},
"juneSolstice": {
"instant": "2026-06-21T08:24:49.000Z",
"local": "2026-06-21T08:24:49",
"deltaTSeconds": 75.4
},
"septemberEquinox": {
"instant": "2026-09-23T00:05:24.000Z",
"local": "2026-09-23T00:05:24",
"deltaTSeconds": 75.5
},
"decemberSolstice": {
"instant": "2026-12-21T20:50:07.000Z",
"local": "2026-12-21T20:50:07",
"deltaTSeconds": 75.7
}
},
"meta": {
"endpoint": "sun",
"route": "/seasons",
"params": {
"year": 2026,
"tz": "UTC"
},
"generatedAt": "2026-07-30T15:14:08.000Z"
}
} /api/sun/seasons?year=2026&tz=Europe/Copenhagen {
"data": {
"year": 2026,
"timezone": "Europe/Copenhagen",
"marchEquinox": {
"instant": "2026-03-20T14:45:30.000Z",
"local": "2026-03-20T15:45:30",
"deltaTSeconds": 75.2
},
"juneSolstice": {
"instant": "2026-06-21T08:24:49.000Z",
"local": "2026-06-21T10:24:49",
"deltaTSeconds": 75.4
},
"septemberEquinox": {
"instant": "2026-09-23T00:05:24.000Z",
"local": "2026-09-23T02:05:24",
"deltaTSeconds": 75.5
},
"decemberSolstice": {
"instant": "2026-12-21T20:50:07.000Z",
"local": "2026-12-21T21:50:07",
"deltaTSeconds": 75.7
}
},
"meta": {
"endpoint": "sun",
"route": "/seasons",
"params": {
"year": 2026,
"tz": "Europe/Copenhagen"
},
"generatedAt": "2026-07-30T15:14:08.000Z"
}
} /api/sun/seasons {
"data": {
"year": 2026,
"timezone": "UTC",
"marchEquinox": {
"instant": "2026-03-20T14:45:30.000Z",
"local": "2026-03-20T14:45:30",
"deltaTSeconds": 75.2
},
"juneSolstice": {
"instant": "2026-06-21T08:24:49.000Z",
"local": "2026-06-21T08:24:49",
"deltaTSeconds": 75.4
},
"septemberEquinox": {
"instant": "2026-09-23T00:05:24.000Z",
"local": "2026-09-23T00:05:24",
"deltaTSeconds": 75.5
},
"decemberSolstice": {
"instant": "2026-12-21T20:50:07.000Z",
"local": "2026-12-21T20:50:07",
"deltaTSeconds": 75.7
}
},
"meta": {
"endpoint": "sun",
"route": "/seasons",
"params": {
"tz": "UTC",
"year": 2026
},
"generatedAt": "2026-07-30T15:14:08.000Z"
}
} Sunrise, sunset, twilight and solar-position values computed from the NOAA Global Monitoring Laboratory solar equations (after Jean Meeus, Astronomical Algorithms, 2nd ed.). It is pure trigonometry evaluated per request — no ephemeris file to download, no upstream service that can go down, no key.
/api/sun/times — sunrise, sunset, solar noon, day length and the civil, nautical and astronomical twilights for one coordinate on one local civil date. Every event is an object carrying the UTC instant, the local wall clock in the requested zone, and a reason./api/sun/position — geometric elevation, azimuth (0° = north, increasing clockwise), declination, equation of time and hour angle at one instant./api/sun/seasons — the March and September equinox and the June and December solstice instants for a year.Polar day and polar night are answered honestly. When the Sun never climbs to an event's altitude the times are null and reason is polar-night; when it never drops to that altitude reason is polar-day. A placeholder timestamp is never substituted. The same mechanism covers mid-latitude twilight gaps: Copenhagen has no nautical twilight for weeks around midsummer, so nauticalDawn/nauticalDusk come back null with reason: "polar-day" even though 55°N is nowhere near the Arctic.
/times is anchored to the solar noon that falls on the requested local date. Whenever sunrise and sunset exist, sunrise < solarNoon < sunset therefore always holds, and dayLengthSeconds is exactly the gap between the two returned instants. At high latitudes that means a dusk can carry the next local calendar date — which the local timestamp shows explicitly rather than silently clamping.
On the single day a polar day or polar night begins or ends, only one of the two crossings happens: a real sunrise with sunset: polar-day, for instance. dayLengthSeconds then counts the half-day the crossing bounds plus the full 12 hours on the side where the Sun never leaves the sky, so Tromsø's curve runs 83 508 → 85 759 → 86 400 s rather than dropping to zero for a day. The endpoint says which half was measured and which was assumed by the reason on each event.
Consecutive meridian transits are 24 hours ± ~20 seconds apart, never exactly 24 hours. At a longitude/zone pairing that puts solar noon within seconds of local midnight — near the antimeridian in UTC, for example — the drift leaves a couple of local civil dates a year containing no transit at all, and a neighbour containing two — a sweep of every date of a year found two such dates at the antimeridian in UTC and two more at longitude 0 on the Auckland clock, and none at all in Copenhagen. A date with no transit is anchored to the nearest one and meta.warnings names the transit date actually used; nothing is substituted silently.
NOAA states its calculator is "theoretically accurate to within a minute for locations between +/- 72° latitude, and within 10 minutes outside of those latitudes". Plan against that bound. The reference days in this endpoint's regression suite — Copenhagen, Quito, New York, Sydney, Reykjavík, Kiritimati, a point on the equator and two daylight-saving change days — reproduce the U.S. Naval Observatory's published rise, transit, set and civil-twilight times to within a minute, and solar declination and elevation track the USNO's own figures to about 0.01° (azimuth is intrinsically less stable when the Sun is near the zenith).
That ±1 minute assumes a reasonably steep horizon crossing. Within a few weeks of a polar-day or polar-night boundary the Sun grazes the horizon instead, and the same equations drift further: at Tromsø (69.6°N) in mid-May this endpoint lands about two minutes off the USNO's published sunset. Treat high-latitude answers near the transition dates as approximate.
The one or two days a year on which a polar day or polar night actually begins or ends are weaker still, and in a way worth spelling out. NOAA solves for a rise and for a set independently, each from a first guess at 0h UT, and each pass re-reads the Sun's declination at wherever the previous pass landed. When the Sun clears the horizon by only a few hundredths of a degree, the declination half a day either side of the crossing is enough to move it to the other side of the threshold, so the search can conclude that the crossing never happens at all — and then polar-day or polar-night is returned for a day that really does have a sunrise, or the reverse.
Measured, not estimated: 27 450 requests across fifteen polar latitudes, five longitudes and a full year of dates were checked against a brute-force scan of this endpoint's own /position output. 116 of them — 0.4%, every single one a changeover day — landed on the wrong side. The largest error inside the ±72° band NOAA's ±1 minute claim covers was 68°N on 2026-01-03, reported as polar night when the Sun was in fact up for 43 minutes; the largest anywhere was 85°N on 2026-03-05, off by 80 minutes. Days that are not a changeover are unaffected. If the changeover dates themselves have to be right, take them from a national almanac office.
Where the two searches contradict each other the answer is repaired rather than published: a real sunrise cannot sit beside a sunset that claims the Sun never reached the horizon at all, so that set is re-solved starting from the sunrise, which is by construction inside the arc. A real sunrise beside sunset: polar-day is not a contradiction — the Sun rose and then stayed up — and is published as-is, which is what the USNO also lists for Tromsø on 2026-05-18.
Not modelled: observer elevation above the terrain, local atmospheric pressure and temperature, and the real horizon profile. Rise and set use NOAA's fixed −0.833° horizon (34′ of mean refraction plus the Sun's 16′ semi-diameter); /position reports geometric elevation with no refraction correction at all. These values are not suitable for navigational, legal or safety-critical use — use a national almanac office for that.
"Golden hour" and "blue hour" are photographic conventions with no standards body behind them, so they are deliberately absent. The three twilights returned here are the standard definitions: civil −6°, nautical −12°, astronomical −18°.
/seasons uses Meeus chapter 27 (the mean expressions of table 27.B plus the 24 periodic corrections of table 27.C), which yields Terrestrial Time. The result is converted to UTC with the Espenak & Meeus ΔT polynomials published by NASA GSFC, and the ΔT actually applied is returned per event as deltaTSeconds so the conversion is auditable. Meeus gives the method an error under a minute for 1951–2050; measured against the USNO table it holds to about a minute from 1900 through 2050 and widens to about two minutes near 2100, where ΔT itself is an extrapolation.
Every route is limited to years 1900–2100; anything outside returns a 400 rather than an unfitted extrapolation.
Call /api/sun/times?lat=55.6761&lng=12.5683&tz=Europe/Copenhagen. It returns sunrise, sunset, solar noon and the three twilights — each with a UTC instant and a local wall clock — plus dayLengthSeconds. No key, no signup, no quota form.
null for the times, plus a reason of polar-day or polar-night on the same event object, and it never returns a placeholder timestamp. The same applies to twilights that do not occur — Copenhagen's nautical twilight around midsummer, for example. On the day a polar day begins there is a real sunrise and no sunset, and dayLengthSeconds counts the 12 hours the Sun never leaves rather than reporting zero.
NOAA describes its equations as "theoretically accurate to within a minute for locations between +/- 72° latitude, and within 10 minutes outside of those latitudes". The regression suite checks the rise, transit, set and civil-twilight values against the U.S. Naval Observatory's published times for Copenhagen, Quito, New York, Sydney, Reykjavík, Kiritimati and the equator; they agree to within a minute.
No. Sunrise and sunset use NOAA's fixed −0.833° horizon (34′ of mean refraction plus the Sun's 16′ semi-diameter); observer elevation, pressure, temperature and terrain are ignored. Do not use the output for navigational, legal or safety-critical decisions.
/api/sun/position?lat=55.6761&lng=12.5683&at=2026-06-21T12:00:00Z returns geometric elevationDegrees (no refraction correction), azimuthDegrees measured clockwise from north, plus declination, equation of time and hour angle.
No. They are photographic conventions with no standards body defining them, so publishing them beside NOAA-derived values would imply an authority they do not have. Civil (−6°), nautical (−12°) and astronomical (−18°) twilight are included instead.
Current time in any IANA timezone — UTC instant, unix seconds, local date & time, UTC offset, ISO week, day of year and a live DST flag.
Live IANA offsets, DST transitions, local-time ambiguity resolution and exact instant conversion — no guessed wall-clock mappings.
Real calendar facts for any date — weekday, ISO week, day of year, quarter, leap year, days in month, weekend flag and Unix timestamp. Defaults to today.
Great-circle distance, bearings, destinations and bounding boxes for WGS 84 coordinates on an explicitly documented mean-Earth sphere.
Random geographic coordinates: uniform across the globe (no pole clustering), inside a bounding box, or within a radius of a point — with haversine distances.
Moon phase, illumination, moonrise, moonset, lunar transit and topocentric position for any coordinate, plus every primary phase instant of a year. No key.