Sunset and sunrise times API v2

Our free API tells you when the sun rises and sets anywhere on Earth, plus twilight, golden hour, solar position and moon data. All you need is a latitude and longitude: you make a simple GET request and get the answer as JSON.

Times come in the local timezone of the place, and you can ask for a single day or up to a whole year in one request.

The API is free to use: no sign up or API key required. We do require attribution: display a visible link to sunrise-sunset.org in the app or page where you show the data.

The documentation for version 1 of the API (/json) has moved to v1 documentation. The API itself is unchanged and supported forever.

API documentation

Make a GET request to https://api.sunrise-sunset.org/v2. Try it right now, this link works in your browser:

https://api.sunrise-sunset.org/v2?lat=36.7201600&lng=-4.4203400

Plain HTTP is supported too: handy for IoT and embedded devices (Arduino, ESP8266, microcontrollers) that cannot make TLS connections.

More examples: a specific date, and a whole year in one request:

https://api.sunrise-sunset.org/v2?lat=36.7201600&lng=-4.4203400&date=2026-07-12
https://api.sunrise-sunset.org/v2?lat=36.7201600&lng=-4.4203400&date_start=2026-01-01&date_end=2026-12-31

Request parameters

Response

All times use the ISO 8601 format: 2026-01-15T08:27:43+01:00 means January 15 at 08:27:43 in the morning, local time (1 hour ahead of UTC). Every programming language understands it out of the box; in JavaScript, new Date(data.sunrise) just works. An example response:


    {
      "date": "2026-01-15",
      "tzid": "Europe/Madrid",
      "utc_offset": "+01:00",
      "lat": 36.7202,
      "lng": -4.4203,
      "sunrise": "2026-01-15T08:27:43+01:00",
      "sunset": "2026-01-15T18:26:27+01:00",
      "solar_noon": "2026-01-15T13:27:05+01:00",
      "day_length": 35924,
      "sun_status": "normal",
      "civil_twilight_begin": "2026-01-15T08:01:01+01:00",
      "civil_twilight_end": "2026-01-15T18:53:09+01:00",
      "nautical_twilight_begin": "2026-01-15T07:29:13+01:00",
      "nautical_twilight_end": "2026-01-15T19:24:57+01:00",
      "astronomical_twilight_begin": "2026-01-15T06:58:10+01:00",
      "astronomical_twilight_end": "2026-01-15T19:56:00+01:00",
      "dawn": "2026-01-15T08:01:01+01:00",
      "dusk": "2026-01-15T18:53:09+01:00",
      "first_light": "2026-01-15T07:29:13+01:00",
      "last_light": "2026-01-15T19:24:57+01:00",
      "golden_hour": {
        "morning": { "begin": "2026-01-15T08:11:54+01:00", "end": "2026-01-15T09:08:17+01:00" },
        "evening": { "begin": "2026-01-15T17:46:10+01:00", "end": "2026-01-15T18:42:33+01:00" }
      },
      "blue_hour": {
        "morning": { "begin": "2026-01-15T08:01:01+01:00", "end": "2026-01-15T08:11:54+01:00" },
        "evening": { "begin": "2026-01-15T18:42:33+01:00", "end": "2026-01-15T18:53:09+01:00" }
      },
      "solar_position": {
        "sunrise_azimuth": 118.31,
        "sunset_azimuth": 241.82,
        "solar_noon_azimuth": 180.09,
        "solar_noon_altitude": 32.06
      },
      "moonrise": "2026-01-15T06:01:54+01:00",
      "moonset": "2026-01-15T15:14:23+01:00",
      "moon_phase": "Waning Crescent",
      "moon_illumination": 10.62
    }
  

With date_start/date_end, the response is {"tzid", "lat", "lng", "days": […]} where each element of days has the fields above (minus tzid/lat/lng).

Field definitions

What each field means, in plain words, with the exact definition in parentheses (the same request always returns exactly the same times):

Consult our glossary of astronomical definitions to learn more about each event.

Polar days and nullability

sun_status is normal, midnight_sun (the sun never sets: day_length is 86400) or polar_night (the sun never rises: day_length is 0). Events that do not occur are null. All events are independently nullable: near the polar circles there are transition days where the sun rises but does not set within the calendar day; then sunrise has a value, sunset is null, sun_status is normal and day_length is null. Never infer one event from another.

Errors

If something in your request is wrong, the API tells you what happened and how to fix it, in plain words:


    {
      "error": "invalid_tz",
      "message": "Unknown tz 'PST'. Use IANA identifiers like 'America/Los_Angeles'.",
      "docs": "https://sunrise-sunset.org/api#tz"
    }
  

For the technically inclined: standard HTTP status codes are used: 400 for invalid input, 404 for unknown routes, 429 when you send too many requests too quickly.

Usage limits and attribution

The API is free of charge for reasonable request volumes. We require that you show attribution to us with a link to our site.

If you send too many requests too quickly the API answers 429 ("slow down") with a Retry-After header telling you how many seconds to wait before trying again. A date range counts as a single request, so if you show data for the same place every day, ask for the whole year once with date_start/date_end: faster for you, lighter for everyone.

Another tip to stay well under the limits: the times for a given date never change, so save the response and reuse it instead of asking again (browsers even do this automatically with our responses). (Technical details: explicit dates are served with Cache-Control: immutable, today/tomorrow with max-age until local midnight, and ETag is supported.)

Using the API from a web page (JavaScript)

You can call the API directly from your web page, no server or backend needed: requests from any website are allowed:

fetch('https://api.sunrise-sunset.org/v2?lat=36.72&lng=-4.42')
  .then(response => response.json())
  .then(data => {
    console.log('Sunrise:', data.sunrise);
    console.log('Sunset:', data.sunset);
  });

Migrating from v1

v1 (/json)v2 (/v2)
formatted=0 (ISO 8601)always ISO 8601, no parameter needed
formatted=1 (12h AM/PM)removed
tzid=X (invalid values silently fall back to UTC)tz=X (invalid values return HTTP 400 invalid_tz)
times default to UTCtimes default to the local timezone of the coordinates
callback (JSONP)removed (use CORS)
errors as status: INVALID_*errors as {error, message, docs}
polar days: epoch-1970 timestampsnull + sun_status
lat=abc computed as 0HTTP 400 invalid_lat
one request per daydate_start/date_end (up to 366 days)
n/agolden & blue hour, azimuth, solar altitude

Announcements

Subscribe to our API newsletter to keep up to date with changes and announcements about the service:

Changelog

Contact

Please contact us for all your API questions.

If you enjoy using our API please consider supporting the project by buying us a coffe!