Skip to content
Free · No key · Millions of requests / month

A fast, keyless API for the sun and the moon.

JSON sunrise, sunset, twilight, golden hour and moon data for any point on Earth. One GET request, no signup.

Try it live

Request
GETapi.sunrisesunset.io/json?lat=38.9&lng=-77
fetch("https://api.sunrisesunset.io/json?lat=38.9&lng=-77")
  .then(r => r.json())
  .then(data => console.log(data.results.sunrise));
cURL
curl "https://api.sunrisesunset.io/json?lat=38.9&lng=-77"
Response200 OK
{
  "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 forever

No signup, no API key, no credit card. Just link back to sunrisesunset.io.

Edge-served

Cloudflare Workers in 300+ cities. P99 under 50 ms.

Up to 365 days

One request returns a full year of daily data via date_start + date_end.

Moon + sun

One endpoint returns rise, set, azimuth, altitude, moon phase, golden and blue hour.

Try it

Hits the live API from your browser. Same request your own front-end would make.

Jump to

Tromsø is inside the Arctic Circle, so it shows sun_status and null events.

Leave empty for today in the location's timezone.

No date ranges here; see the one-year example below.

GEThttps://api.sunrisesunset.io/json?lat=38.907192&lng=-77.036873
Ready
Results appear here.

Example requests

All parameters

Parameters

All sent as query-string values on a single GET request.

latRequirednumber
Latitude in decimal degrees.
Example: 38.907192
lngRequirednumber
Longitude in decimal degrees.
Example: -77.036873
dateOptionalstring
Date to query. ISO YYYY-MM-DD, or a relative word like "today" or "tomorrow". Defaults to today in the location's timezone.
Example: 2026-06-21
date_startOptionalstring
Start of a date range (inclusive). Must be paired with date_end. Up to 365 days.
date_endOptionalstring
End of a date range (inclusive). Returns an array of daily results instead of a single object.
timezoneOptionalIANA tz
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.
Default: auto
Example: America/New_York
time_formatOptionalenum
Format of all time fields. One of 12, 24, military, unix. Unix timestamps are always UTC.
Default: 12
formattedOptional0 | 1
Set to 0 to receive times in ISO 8601 format and day_length in seconds.
Default: 1
elevationOptionalnumber | false
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.
Default: auto
callbackOptionalstring
JSONP callback function name. Returns application/javascript wrapped in your callback when present.

Response fields

Wrapped in { results, status, tzid }. results is a single object, or an array when a date range is used.

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.

Status codes

Returned 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.

Building with an AI assistant?

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.

API reference for LLMs
# 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"
}

Attribution

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>

FAQ

Do I need an API key?
No, the keyless endpoint works for most apps. For higher limits or per-app usage tracking, sign in and mint a key, then send it as Authorization: Bearer sss_.... Never put it in the query string; proxies and CDNs log those.
Is it really free for commercial use?
Yes. Just link back to sunrisesunset.io somewhere on your site.
How accurate are the times?
Astronomical to the second. Atmospheric refraction and terrain elevation are both factored in by default.
What if the sun or moon never rises/sets that day?
Those fields return null. 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.
What's the difference between golden hour and blue hour?
Golden hour is the warm light, sun between 4° below and 6° above the horizon. Blue hour is the deeper light just outside it, sun between 6° and 4° below. Both come back as { 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.
Can I bulk-query a full year?
Yes. Use date_start and date_end (up to 365 days apart) and you get an array of daily objects in one request.
What timezone are the times in?
The location's own, auto-detected from lat/lng. Override with the timezone parameter.
Rate limits?
None enforced, within reason. If you'd be calling it hourly per user, cache on your end.

Changelog

  1. 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.

  2. Moon data (rise/set, phase, illumination), sun altitude/azimuth at solar noon + rise + set, automatic elevation from terrain.

  3. JSONP callback, formatted=0 for ISO 8601 output, nautical twilight fields, granular status codes.

  4. Fixed a DST edge-case that could return the wrong day at the boundary.

  5. time_format option (12, 24, military, unix).

  6. date_start + date_end range queries, up to 365 days.

  7. Lower response times; migrated onto Cloudflare Workers.

  8. utc_offset added to responses.

  9. first_light + last_light fields (astronomical twilight).

  10. API released.

Watching the API? Status page