FreeAstroAPI LogoFreeAstroAPI
Back to Guides
Build Astrology Apps

How to Get Moon Eclipse Data in Your App

Learn how to get solar and lunar eclipse data in your app, including local visibility, contact times, magnitude, and obscuration.

If you are wondering how to get moon eclipse data in your app, you can use the FreeAstroAPI Moon Phase endpoint for both solar and lunar eclipses. One request can tell you whether an eclipse is near a date, what kind it is, when its contacts occur, and whether it is visible from the user's location.

This guide builds a location-aware eclipse feature with GET /api/v1/moon/phase. It also explains an important distinction: an eclipse can be total globally while appearing partial at the observer's coordinates.

What the Moon endpoint returns

Set include_eclipse=true to search for the nearest solar or lunar eclipse within 15 days of the requested date.

The response separates global eclipse circumstances from observer-specific circumstances:

FieldScopeMeaning
kindGlobalsolar or lunar
typeGlobalSolar: total, annular, hybrid, or partial; lunar: total, partial, or penumbral
dateGlobalTime of maximum eclipse in UTC
starts_at, ends_atGlobalFirst and last global contact times
central_phase_starts_at, central_phase_ends_atGlobalStart and end of totality, annularity, or the hybrid central phase when applicable
magnitudeGlobalEclipse magnitude at the global maximum
obscurationGlobalFraction of the Sun's disc obscured at maximum, from 0 to 1
maximum_locationGlobalLatitude and longitude of the solar eclipse maximum
visible_at_locationObserverWhether the eclipse is visible from the supplied coordinates
type_at_locationObserverSolar eclipse type at the observer: total, annular, or partial
local_starts_at, local_maximum_at, local_ends_atObserverLocal solar eclipse contact times, returned in UTC
magnitude_at_locationObserverSolar eclipse magnitude at the supplied location
obscuration_at_locationObserverFraction of the Sun obscured at the supplied location
is_blood_moonGlobaltrue only for a total lunar eclipse

For lunar eclipses, the location-aware result currently adds visible_at_location. Solar eclipses also include the detailed local contact, magnitude, obscuration, and local-type fields.

Make a location-based eclipse request

Use a city or a latitude/longitude pair. Coordinates are best when your app already has a map, device location, or geocoded place record because they avoid ambiguous city names.

This request checks the August 12, 2026 eclipse from Paris:

curl -X GET "https://api.freeastroapi.com/api/v1/moon/phase?date=2026-08-12T17:47:00Z&lat=48.8566&lon=2.3522&include_eclipse=true" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY"

You can replace the coordinates with city=Paris, but explicit coordinates make the observer used by the calculation unambiguous.

Understand the eclipse response

The 2026 event is a total solar eclipse globally, but Paris sees it as a partial eclipse. The API represents both facts without collapsing them into one field:

{
  "timestamp": "2026-08-12T17:47:00+00:00",
  "eclipse": {
    "is_eclipse": true,
    "is_blood_moon": false,
    "kind": "solar",
    "type": "total",
    "date": "2026-08-12T17:45:59Z",
    "starts_at": "2026-08-12T15:34:33Z",
    "ends_at": "2026-08-12T19:57:58Z",
    "central_phase_starts_at": "2026-08-12T16:58:09Z",
    "central_phase_ends_at": "2026-08-12T18:34:00Z",
    "magnitude": 1.0395,
    "obscuration": 1.0,
    "maximum_location": {
      "lat": 65.1653,
      "lon": -25.1048
    },
    "visible_at_location": true,
    "type_at_location": "partial",
    "local_starts_at": "2026-08-12T17:22:13Z",
    "local_maximum_at": "2026-08-12T18:17:19Z",
    "local_ends_at": "2026-08-12T19:09:26Z",
    "magnitude_at_location": 0.9309,
    "obscuration_at_location": 0.921
  }
}

Use eclipse.type when describing the global event. Use eclipse.type_at_location for the label shown to a user at a known location. In this example, a good interface says “Partial solar eclipse visible in Paris,” even though the global event is total.

Call the eclipse API from a Node.js server

Keep your FreeAstroAPI key on the server. Do not put it in mobile binaries, browser JavaScript, public environment variables, or source control.

type EclipseRequest = {
  date: string;
  lat: number;
  lon: number;
};

export async function getEclipseData(input: EclipseRequest) {
  const apiKey = process.env.FREE_ASTRO_API_KEY;
  if (!apiKey) throw new Error("FREE_ASTRO_API_KEY is not configured");

  const params = new URLSearchParams({
    date: input.date,
    lat: String(input.lat),
    lon: String(input.lon),
    include_eclipse: "true",
  });

  const response = await fetch(
    `https://api.freeastroapi.com/api/v1/moon/phase?${params}`,
    {
      headers: {
        "Content-Type": "application/json",
        "x-api-key": apiKey,
      },
      cache: "no-store",
    }
  );

  if (!response.ok) {
    throw new Error(`Moon API request failed: ${response.status}`);
  }

  return response.json();
}

Your mobile or web client should call your own server route. That route can validate the requested coordinates, call FreeAstroAPI with the private key, and return only the eclipse data needed by the interface.

Call it from Python

The same request works in a Python backend, scheduled job, or data pipeline:

import os
import requests

response = requests.get(
    "https://api.freeastroapi.com/api/v1/moon/phase",
    params={
        "date": "2026-08-12T17:47:00Z",
        "lat": 48.8566,
        "lon": 2.3522,
        "include_eclipse": "true",
    },
    headers={
        "Content-Type": "application/json",
        "x-api-key": os.environ["FREE_ASTRO_API_KEY"],
    },
    timeout=15,
)
response.raise_for_status()

eclipse = response.json()["eclipse"]
print(eclipse)

Turn the response into app copy

Start with visibility, then choose the local type when it exists:

function eclipseMessage(eclipse: {
  is_eclipse: boolean;
  kind?: "solar" | "lunar";
  type?: string;
  visible_at_location?: boolean;
  type_at_location?: string;
}) {
  if (!eclipse.is_eclipse) {
    return "No solar or lunar eclipse is within 15 days of this date.";
  }

  if (eclipse.visible_at_location === false) {
    return `A ${eclipse.type} ${eclipse.kind} eclipse occurs near this date, but it is not visible here.`;
  }

  const observedType = eclipse.type_at_location ?? eclipse.type;
  return `${observedType} ${eclipse.kind} eclipse visible from this location.`;
}

Treat an omitted visible_at_location as “location not evaluated,” not as false. That field is only observer-specific, so it depends on sending usable coordinates or a resolvable city.

Find the next solar and lunar eclipses

Add include_forecast=true when the app needs upcoming events rather than only a nearby-date check:

curl -X GET "https://api.freeastroapi.com/api/v1/moon/phase?date=2026-02-06T00:00:00Z&include_forecast=true" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY"

The forecast object can include:

  • next_eclipse: the next lunar eclipse. This field remains lunar for backward compatibility.
  • next_solar_eclipse: the next global solar eclipse, including type, date, magnitude, obscuration, and maximum location.

Use include_eclipse=true&include_forecast=true together when one screen needs both the date-specific event and future eclipse cards.

Get a month of eclipse-aware Moon data

For a calendar, use GET /api/v1/moon/month instead of making one request per day:

curl -X GET "https://api.freeastroapi.com/api/v1/moon/month?year=2026&month=8&lat=48.8566&lon=2.3522&include_eclipse=true" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY"

Each item in days includes its own eclipse object. When no eclipse is within the search window, that object contains is_eclipse: false. Cache the monthly response in your backend if many users request the same month and location.

Display times correctly

Eclipse contact timestamps are returned in UTC. Convert them for display with an IANA time zone on the client or server, while keeping the original UTC value for storage and comparison.

const label = new Intl.DateTimeFormat("en", {
  dateStyle: "medium",
  timeStyle: "short",
  timeZone: "Europe/Paris",
}).format(new Date(eclipse.local_maximum_at));

Do not infer visibility from the user's time zone. Visibility is geometric and depends on latitude and longitude; a time zone can cover places with different eclipse circumstances.

Verification against known eclipse data

The eclipse implementation is regression-tested against known city circumstances, including:

  • the April 8, 2024 total eclipse in Dallas and partial eclipse in New York;
  • the October 14, 2023 annular eclipse in Albuquerque;
  • the October 25, 2022 partial eclipse in London;
  • the August 12, 2026 total global eclipse appearing partial in Paris and not visible in Sydney.

The tests compare event type, visibility, contact times, magnitude, and obscuration with official NASA reference circumstances. See the NASA solar eclipse catalog, NASA's New York circumstances, and NASA's Paris circumstances for independent reference data.

Common eclipse integration mistakes

  1. Showing the global type as the local type. A global total eclipse may be partial or invisible at the user's location. Prefer type_at_location in location-based UI.
  2. Treating magnitude and obscuration as the same value. Magnitude measures a diameter ratio; obscuration measures the covered area of the Sun's disc.
  3. Exposing the API key. Call FreeAstroAPI from a trusted server component.
  4. Assuming every date has eclipse details. Check is_eclipse before reading optional fields.
  5. Displaying UTC as local time. Convert contact timestamps with the observer's IANA time zone.
  6. Using only a time zone for visibility. Send coordinates or a city; visibility is location based.

Next steps

Read next

All guides