Free forever
No signup, no API key, no credit card. Just link back to sunrisesunset.io.
JSON sunrise, sunset, twilight, golden hour and moon data for any point on Earth. One GET request, no signup.
api.sunrisesunset.io/json?lat=38.9&lng=-77fetch("https://api.sunrisesunset.io/json?lat=38.9&lng=-77")
.then(r => r.json())
.then(data => console.log(data.results.sunrise));curl "https://api.sunrisesunset.io/json?lat=38.9&lng=-77"{
"results": {
"date": "2026-06-21",
"sunrise": "5:41:58 AM",
"sunset": "8:38:05 PM",
"first_light": "3:42:23 AM",
"last_light": "10:37:39 PM",
"dawn": "5:09:48 AM",
"dusk": "9:10:15 PM",
"solar_noon": "1:10:02 PM",
"golden_hour": "7:58:03 PM",
"day_length": "14:56:06",
"nautical_twilight_begin": "4:29:11 AM",
"nautical_twilight_end": "9:50:51 PM",
"timezone": "America/New_York",
"utc_offset": -240,
"sun_altitude": 74.54,
"sun_azimuth": 180,
"sunrise_azimuth": 58.3,
"sunset_azimuth": 301.7,
"moonrise": "1:01:52 PM",
"moonset": "12:41:20 AM",
"moon_illumination": 47.57,
"moon_phase": "First Quarter",
"moon_phase_value": 0.24,
"moon_always_up": false,
"moon_always_down": false,
"elevation": 26,
"sun_status": "normal",
"golden_hour_morning": {
"begin": "5:22:29 AM",
"end": "6:22:00 AM"
},
"golden_hour_evening": {
"begin": "7:58:03 PM",
"end": "8:57:33 PM"
},
"blue_hour_morning": {
"begin": "5:09:48 AM",
"end": "5:22:29 AM"
},
"blue_hour_evening": {
"begin": "8:57:33 PM",
"end": "9:10:15 PM"
}
},
"status": "OK",
"tzid": "America/New_York"
}No signup, no API key, no credit card. Just link back to sunrisesunset.io.
Cloudflare Workers in 300+ cities. P99 under 50 ms.
One request returns a full year of daily data via date_start + date_end.
One endpoint returns rise, set, azimuth, altitude, moon phase, golden and blue hour.
Hits the live API from your browser. Same request your own front-end would make.
https://api.sunrisesunset.io/json?lat=38.907192&lng=-77.036873Results appear here.All sent as query-string values on a single GET request.
latRequirednumber38.907192lngRequirednumber-77.036873dateOptionalstring2026-06-21date_startOptionalstringdate_endOptionalstringtimezoneOptionalIANA tzautoAmerica/New_Yorktime_formatOptionalenum12formattedOptional0 | 11elevationOptionalnumber | falseautocallbackOptionalstringWrapped in { results, status, tzid }. results is a single object, or an array when a date range is used.
datesunrisesunsetdawnduskfirst_lightlast_lightnautical_twilight_beginnautical_twilight_endsolar_noongolden_hourgolden_hour_morninggolden_hour_eveningblue_hour_morningblue_hour_eveningday_lengthtimezoneutc_offsetsun_altitudesun_azimuthsunrise_azimuthsunset_azimuthmoonrisemoonsetmoon_illuminationmoon_phasemoon_phase_valuemoon_always_upmoon_always_downelevationsun_statusReturned in the status field. HTTP status tracks it: 200 for OK and INVALID_TZID (which still returns data), 400 for bad input, 500 for server errors.
OKRequest succeeded.INVALID_TZIDTimezone didn't validate. Fell back to the location's own zone and returned data anyway.INVALID_REQUESTMissing or malformed lat/lng.INVALID_DATEUnparseable date, or a range longer than one year.UNKNOWN_ERRORSomething broke on our end. Retry.Paste this into ChatGPT, Claude or Cursor, then ask for the code you want. It includes every parameter and field, plus the edge cases that break first drafts: nulls at the poles, utc_offset in minutes, times as strings rather than dates.
There's also an OpenAPI 3.0 spec at api.sunrisesunset.io/openapi.yaml for Postman, Insomnia, or generating a typed client.
# SunriseSunset.io API reference
Free JSON API for sun and moon times anywhere on Earth. No API key or signup. GET only, CORS enabled, so it can be called directly from a browser.
Endpoint: GET https://api.sunrisesunset.io/json
## Query parameters
- lat (number, REQUIRED): Latitude in decimal degrees.
- lng (number, REQUIRED): Longitude in decimal degrees.
- date (string): Date to query. ISO YYYY-MM-DD, or a relative word like "today" or "tomorrow". Defaults to today in the location's timezone.
- date_start (string): Start of a date range (inclusive). Must be paired with date_end. Up to 365 days.
- date_end (string): End of a date range (inclusive). Returns an array of daily results instead of a single object.
- timezone (IANA tz, default: auto): Return times in this timezone. Defaults to the location's IANA timezone resolved from lat/lng. An invalid value still returns data, with status INVALID_TZID and the detected zone.
- time_format (enum, default: 12): Format of all time fields. One of 12, 24, military, unix. Unix timestamps are always UTC.
- formatted (0 | 1, default: 1): Set to 0 to receive times in ISO 8601 format and day_length in seconds.
- elevation (number | false, default: auto): Elevation override in meters. By default, auto-detected from terrain via ETOPO1. Pass false to compute at sea level. Higher elevation pushes sunrise earlier and sunset later.
- callback (string): JSONP callback function name. Returns application/javascript wrapped in your callback when present.
## Response shape
{ results, status, tzid }. `results` is a single object, or an array of those objects when date_start/date_end is used. On an error, `results` is null and an `error` string replaces `tzid`.
## Fields inside `results`
- date (string): Queried date, YYYY-MM-DD.
- sunrise (time): Sunrise time.
- sunset (time): Sunset time.
- dawn (time): Civil dawn. Sun 6° below the horizon.
- dusk (time): Civil dusk. Sun 6° below the horizon.
- first_light (time): Astronomical dawn. The faintest brightening of the sky.
- last_light (time): Astronomical dusk. The last trace of sky light.
- nautical_twilight_begin (time): Sun 12° below the horizon, morning.
- nautical_twilight_end (time): Sun 12° below the horizon, evening.
- solar_noon (time): Sun at its highest point.
- golden_hour (time): Start of evening golden hour. Same value as golden_hour_evening.begin, kept for backwards compatibility.
- golden_hour_morning ({ begin, end }): Sun between 4° below and 6° above the horizon, rising.
- golden_hour_evening ({ begin, end }): Sun between 6° above and 4° below the horizon, setting.
- blue_hour_morning ({ begin, end }): Sun between 6° and 4° below the horizon, rising. Ends where golden_hour_morning begins.
- blue_hour_evening ({ begin, end }): Sun between 4° and 6° below the horizon, setting. Begins where golden_hour_evening ends.
- day_length (H:MM:SS | seconds): Length of daylight (seconds if formatted=0).
- timezone (string): IANA timezone of the response times.
- utc_offset (number): UTC offset in minutes.
- sun_altitude (degrees): Sun altitude at solar noon.
- sun_azimuth (degrees): Sun azimuth at solar noon (N = 0°, clockwise).
- sunrise_azimuth (degrees): Compass bearing where the sun rises.
- sunset_azimuth (degrees): Compass bearing where the sun sets.
- moonrise (time | null): Moonrise time. Null if the moon doesn't rise that day.
- moonset (time | null): Moonset time. Null if the moon doesn't set that day.
- moon_illumination (percent): Percent of the moon's disk illuminated, 0–100.
- moon_phase (string): Named phase: New Moon, Waxing Crescent, First Quarter, Waxing Gibbous, Full Moon, Waning Gibbous, Last Quarter, Waning Crescent.
- moon_phase_value (0–1): Continuous phase value. 0 and 1 are new, 0.5 is full.
- moon_always_up (boolean): True at polar latitudes when the moon is circumpolar that day.
- moon_always_down (boolean): True when the moon doesn't appear above the horizon.
- elevation (meters): Terrain elevation used in the calculation.
- sun_status (enum): normal, midnight_sun (the sun never sets) or polar_night (it never rises). Both polar cases null out sunrise, sunset and day_length, so this tells you which one you got.
## Things that trip people up
- Every time field is a string in the format chosen by time_format/formatted, NOT a Date. Use formatted=0 for ISO 8601 if you plan to parse it.
- Any time field can be null when the event does not happen that day. Read sun_status before assuming a null sunrise is a bug: midnight_sun and polar_night are normal at high latitudes.
- day_length is an H:MM:SS string by default and a number of seconds when formatted=0.
- utc_offset is in MINUTES, not hours (-240 means UTC-4).
- golden_hour is a single time kept for backwards compatibility, equal to golden_hour_evening.begin. Prefer the {begin, end} window fields for new code.
- A sunset after local midnight carries the next calendar date, so in ISO mode sunset can look 'before' sunrise as text. Compare timestamps, not strings.
- status can be OK, INVALID_TZID, INVALID_REQUEST, INVALID_DATE or UNKNOWN_ERROR. INVALID_TZID still returns full data with a fallback timezone and HTTP 200.
- Times for a past date never change. Cache them rather than re-requesting.
## Machine-readable spec
An OpenAPI 3.0 description is served at https://api.sunrisesunset.io/openapi.yaml. Import it into Postman or Insomnia, generate a typed client from it, or fetch it directly.
## Attribution (required)
The API is free for commercial use in exchange for a visible backlink: Powered by <a href="https://sunrisesunset.io">SunriseSunset.io</a>
## Example
curl 'https://api.sunrisesunset.io/json?lat=38.907192&lng=-77.036873&date=2026-06-21'
{
"results": {
"date": "2026-06-21",
"sunrise": "5:41:58 AM",
"sunset": "8:38:05 PM",
"first_light": "3:42:23 AM",
"last_light": "10:37:39 PM",
"dawn": "5:09:48 AM",
"dusk": "9:10:15 PM",
"solar_noon": "1:10:02 PM",
"golden_hour": "7:58:03 PM",
"day_length": "14:56:06",
"nautical_twilight_begin": "4:29:11 AM",
"nautical_twilight_end": "9:50:51 PM",
"timezone": "America/New_York",
"utc_offset": -240,
"sun_altitude": 74.54,
"sun_azimuth": 180,
"sunrise_azimuth": 58.3,
"sunset_azimuth": 301.7,
"moonrise": "1:01:52 PM",
"moonset": "12:41:20 AM",
"moon_illumination": 47.57,
"moon_phase": "First Quarter",
"moon_phase_value": 0.24,
"moon_always_up": false,
"moon_always_down": false,
"elevation": 26,
"sun_status": "normal",
"golden_hour_morning": {
"begin": "5:22:29 AM",
"end": "6:22:00 AM"
},
"golden_hour_evening": {
"begin": "7:58:03 PM",
"end": "8:57:33 PM"
},
"blue_hour_morning": {
"begin": "5:09:48 AM",
"end": "5:22:29 AM"
},
"blue_hour_evening": {
"begin": "8:57:33 PM",
"end": "9:10:15 PM"
}
},
"status": "OK",
"tzid": "America/New_York"
}Free for personal and commercial use. All we ask is a visible backlink, so paste this anywhere on your site:
Powered by <a href="https://sunrisesunset.io">SunriseSunset.io</a>Authorization: Bearer sss_.... Never put it in the query string; proxies and CDNs log those.sun_status tells you which case you got, midnight_sun or polar_night, so a null sunrise is never ambiguous. For the moon, moon_always_up or moon_always_down flips to true.{ begin, end } windows for morning and evening, and they meet exactly: blue_hour_morning.end is golden_hour_morning.begin. Near the poles either half can be null, since the sun can cross one boundary angle in a day without crossing the other.date_start and date_end (up to 365 days apart) and you get an array of daily objects in one request.timezone parameter.Golden hour and blue hour as begin/end windows, morning and evening. New sun_status field separates midnight sun from polar night. Additive only; every existing field is unchanged, including golden_hour.
Moon data (rise/set, phase, illumination), sun altitude/azimuth at solar noon + rise + set, automatic elevation from terrain.
JSONP callback, formatted=0 for ISO 8601 output, nautical twilight fields, granular status codes.
Fixed a DST edge-case that could return the wrong day at the boundary.
time_format option (12, 24, military, unix).
date_start + date_end range queries, up to 365 days.
Lower response times; migrated onto Cloudflare Workers.
utc_offset added to responses.
first_light + last_light fields (astronomical twilight).
API released.
Watching the API? Status page