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:
| Field | Scope | Meaning |
|---|---|---|
kind | Global | solar or lunar |
type | Global | Solar: total, annular, hybrid, or partial; lunar: total, partial, or penumbral |
date | Global | Time of maximum eclipse in UTC |
starts_at, ends_at | Global | First and last global contact times |
central_phase_starts_at, central_phase_ends_at | Global | Start and end of totality, annularity, or the hybrid central phase when applicable |
magnitude | Global | Eclipse magnitude at the global maximum |
obscuration | Global | Fraction of the Sun's disc obscured at maximum, from 0 to 1 |
maximum_location | Global | Latitude and longitude of the solar eclipse maximum |
visible_at_location | Observer | Whether the eclipse is visible from the supplied coordinates |
type_at_location | Observer | Solar eclipse type at the observer: total, annular, or partial |
local_starts_at, local_maximum_at, local_ends_at | Observer | Local solar eclipse contact times, returned in UTC |
magnitude_at_location | Observer | Solar eclipse magnitude at the supplied location |
obscuration_at_location | Observer | Fraction of the Sun obscured at the supplied location |
is_blood_moon | Global | true 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
- 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_locationin location-based UI. - Treating magnitude and obscuration as the same value. Magnitude measures a diameter ratio; obscuration measures the covered area of the Sun's disc.
- Exposing the API key. Call FreeAstroAPI from a trusted server component.
- Assuming every date has eclipse details. Check
is_eclipsebefore reading optional fields. - Displaying UTC as local time. Convert contact timestamps with the observer's IANA time zone.
- Using only a time zone for visibility. Send coordinates or a city; visibility is location based.
Next steps
- Read the complete Moon Phase endpoint documentation.
- Build a calendar with the Moon Phase Timeline endpoint.
- Review authentication and API-key handling.
- Create a free API key and test a known eclipse from your server.