Skip to content
AstroWay/api v2.325.2 · docs
all systems operational

Calculation Accuracy

Last updated View as Markdown Agent setup

The reference for AstroWay positions is NASA JPL Horizons, the ephemeris service of NASA’s Jet Propulsion Laboratory. Every calculation runs on our own servers, with no upstream API between your request and the answer. Every core calculation endpoint is also covered by our own regression snapshot tests, and the numbers are cross-checked against independent references, plus the NASA 5-Millennium Eclipse Catalog:

  • Against NASA JPL Horizons, with somebody else’s benchmark (RoxyAPI’s): 231 of 231 within tolerance, median 0.052", maximum 1.1" (Chiron in 1900; 0.47" for the Sun, Moon and planets)
  • Regression suite: 888 frozen snapshots on every pull request; one regression blocks the release
  • Planet positions against the swetest reference output from Astrodienst: median 0.0013", maximum 0.561" (measured 2026-07-29 over 130 samples). Per-body breakdown below
  • Placidus house cusps: 0.000" exact match
  • Eclipses: < 1 minute vs NASA 5-Millennium Eclipse Catalog
  • ACG lines: < 1.5 km at the equator vs swetest
  • Sunrise/sunset: < 10 seconds vs timeanddate.com
  • Moon VOC, ingresses, planet conjunctions: sub-second precision

Checked against NASA JPL Horizons, with somebody else’s tool

Section titled “Checked against NASA JPL Horizons, with somebody else’s tool”

RoxyAPI publish their own benchmark against NASA JPL Horizons DE441: MIT licence, standard library only, 17 domains and 2,701 values since 2026-11-01, of which the western-planets folder holds 21 charts and 231 positions, and a --base-url flag that points it at any other API. Their README says outright that the tolerance bands are deliberately not sized to their own engine, because a benchmark inviting you to test a competitor has to be honest.

We pointed it at ourselves with no number in their code changed. The adapter renames one request field and drops one response envelope.

AstroWay, 2026-10-19RoxyAPI, their run of 2026-11-01
Within tolerance231 of 231231 of 231
Median deviation0.052"0.048"
Maximum1.1"0.32"

Our run is on the current version of their harness, which added Chiron and two daylight-saving cases and reads the Horizons values to seven decimals; it cost 21 API calls. The medians are 0.004” apart. Our largest deviation is Chiron in 1900, where our asteroid ephemeris and the Horizons small-body integration differ by 1.1”; for the Sun, Moon and planets our maximum is 0.47”. Row by row, all 231: CSV. The 2026-09-09 run on the older version of the harness: CSV.

Against the swetest reference output: how this was measured

Section titled “Against the swetest reference output: how this was measured”

These are measured numbers, not estimates. The script takes 10 charts spread from 1900 to 2050, asks the live swetest CGI at Astrodienst for the same instants, and compares all 13 bodies we return. 130 samples in total.

BodyMaximum drift
Sun, Venus, Saturn0.001"
Mercury0.002"
true Node0.004"
Mars0.007"
Jupiter0.009"
Moon0.022"
Uranus0.083"
Pluto0.097"
Neptune0.223"
Chiron0.561"
mean Apogee (Lilith)0.000"

Median across all 130 samples: 0.0013".

This page previously carried a blanket ”< 0.1 arcsec” promise. The 2026-07-29 measurement showed Neptune, Pluto and Chiron do not hold it, so the promise was replaced with the measured figures. Chiron and the outer planets drift further because their positions come from the compressed ephemeris set our build uses.

You can reproduce this: api-calc/scripts/accuracy-vs-swetest.mjs makes exactly these requests and prints the same table.

Check it yourself. The script behind the numbers above is a public MIT repository: astroway/astrology-accuracy-benchmark. It is not ours-only: an adapter for any other API is about thirty lines, so you can run the same 130 samples against a competitor and compare. A sandbox key is enough.

Besides JPL Horizons and our own snapshots, the numbers are compared with three other public references:

The reference output Astrodienst publishes, the team behind Astro.com. Drift from it is 0.00-0.07 arcsec on the reference charts.

An independent open-source Python library, run on the same charts.

A remote astrology API (sidereal Lahiri). Systemic drift of 8-17 arcsec comes from different versions of the Lahiri ayanamsa formula, not from position accuracy.

Chartvs swetest (Astrodienst)vs Kerykeion (Python)vs Prokerala API
Monroe 19260.00”0.19”16.95” (systemic)
Diana 19610.00”0.69”8.18” (systemic)
Einstein 18790.07”Kerykeion LMT artifact14.96” (systemic)

Each of the core calculation endpoints is covered by frozen snapshot tests on 3 reference charts (Monroe / Diana / Einstein) = 888 snapshots.

The snapshot suite catches:

  • Input-mapping bugs: wrong planet id, UT, house system
  • Post-processing: rounding, unit conversion, sign loss
  • Defaults divergence: mean vs true node, geocentric vs topocentric
  • Schema drift: validation let through a wrong shape
  • Stale deploy: prod dist out of sync with code

Default tolerance: 5e-5° (≈0.18 arcsec) for all numeric fields.

ChartDateMax drift
Marilyn Monroe1926-06-010.00”
Princess Diana1961-07-010.00”
Albert Einstein1879-03-140.07”
ChartASC driftMC driftMax cusp drift
Monroe0.000”0.000”0.000”
Diana0.000”0.000”0.000”
EventNASA maxOurs maxDrift
2025-03-14 Lunar Total06:58 UT06:58 UT0.8 min
2025-03-29 Solar Partial10:47 UT10:47 UT0.5 min
2025-09-07 Lunar Total18:11 UT18:11 UT0.8 min
2025-09-21 Solar Partial19:41 UT19:42 UT1.0 min

MC and IC lines are built from the longitude = RA - GMST formula (Kenneth Bowser standard). Drift from authoritative: < 1.5 km at the equator for all planets.

The ASC and DSC horizon lines are solved from the horizon equation in the same equatorial coordinates: cos H = -tan φ · tan δ, where H = (GMST + lng) - RA. The two halves differ by the sign of the hour angle: at H < 0 the body is east of the meridian and therefore rising. The check we run on every pass takes every point of every horizon curve and computes the body’s altitude there. Across 8419 points the largest deviation is 0.0 km, so the body really is on the horizon everywhere we drew the line.

LocationDateParameterDrift
London2026-04-15Sunrise0.6 sec
London2026-04-15Sunset9 sec

Polar locations (|lat| > 66.5°) automatically return polarState + a warning that regular planetary hours are undefined.

AstroWay uses variable per-planet orbs (MIN-of-two-planets rule), as in ZET9 and astro.com. Default orbs (natal chart):

AspectSunMoonInnerJupiterOuter
Conjunction12°10°5°8°5°
Sextile6.5°6°5°5°5°
Square10°8°5°7°5°
Trine12°8°5°5°5°
Opposition12°10°5°8°5°

Minor aspects (36°, 40°, 45°, 72°, 108°, 135°, 144°) are off by default. Enable explicitly via ALL_ASPECTS.

For |lat| > 66.5° the Placidus/Koch/Regiomontanus systems are mathematically undefined. In that case the cusps are computed as Porphyry, and the response says so in a warning field next to "system": "P", naming the substituted system and the latitude.

Regression is checked on every PR through CI:

  • api-calc/tests/endpoints/: 888 snapshots against reference charts (Monroe / Diana / Einstein) + synastry / composite / davison
  • .github/workflows/api-accuracy.yml: auto-run on PR
  • Cross-check against swetest CGI + Kerykeion: weekly
  • Extreme dates (before 1800 and after 2399): an analytical ephemeris is used, precision ~0.1” (vs < 0.01” inside 1800-2399)
  • True Lilith (id=13) vs Mean Lilith (id=12): up to 12° difference: the default is Mean Lilith (stable behavior), True Lilith is available via planetIds: [13]
  • Topocentric vs geocentric: geocentric by default

Accuracy issues: report via support@astroway.info with chart data + expected reference (from astro.com or similar authoritative source).