Checked against NASA JPL Horizons

Asterwise computes positions with the Swiss Ephemeris. This page checks that output against a source that shares no code with it: Horizons, the ephemeris service of NASA's Jet Propulsion Laboratory. 80 geocentric longitudes, 10 bodies at 8 instants between 1950 and 2050, generated on 28 September 2026.

Short answer: over 80 planetary positions between 1950 and 2050, Asterwise longitudes differ from NASA JPL Horizons by a median of 0.050 arcseconds, and 79 of 80 agree within half an arcsecond. The raw data and the script to repeat the check are on this page.

MeasureValue
Median difference0.050″
95th percentile0.231″
Within half an arcsecond79 of 80
Largest difference2.929″ (Moon, 2050, explained below)

For scale: one arcsecond is 1/3600 of a degree. A chart shown to two decimal places of a degree rounds at 36 arcseconds, so every difference on this page is far below what any chart displays. The Moon, the fastest body, moves about 0.55 arcseconds per second of time.

Method

Asterwise side. The tropical longitudes below are what POST /v1/western/natal (the Western astrology API) returns for each instant: the engine at commit 7d68ba3, the build serving production when the page was generated, run with the same Swiss Ephemeris data files. The API returns longitude as an unrounded float; nothing here is rounded before the comparison. Location was set to latitude 0, longitude 0, which does not affect geocentric planetary positions.

Reference side. The Horizons API, observer table, centre 500@399 (geocentre), quantity 31, apparent airless positions, times given as Julian Day UT. That returns the observer-centred ecliptic-of-date longitude, the same quantity the Swiss Ephemeris returns by default. Horizons draws each body from its own JPL solution, listed in the per-body table.

What is not on this page. Horizons has no ayanamsa, so sidereal (Vedic) positions cannot be checked against it directly. Asterwise derives them by subtracting the Lahiri ayanamsa, in the Swiss Ephemeris definition, from the tropical longitude verified here; the ayanamsa is a convention rather than an observable. House cusps and the ascendant are also outside Horizons' scope. Both are covered on the reference-chart page, which compares the full Vedic and Western output against a direct Swiss Ephemeris calculation. Rahu is a mean lunar node, not a body Horizons tabulates, and is omitted.

Updated 28 September 2026. Horizons reads each time as UTC. Until this date Asterwise treated a UTC clock time as Universal Time (UT1), which differs from UTC by up to 0.9 seconds between 1972 and today; that put the Moon up to 0.18 arcseconds off at the 1985 to 2026 instants, where it now agrees within 0.07. The engine now converts UTC to UT1 with leap seconds. With the timing exact, the Sun and the inner planets show the same small offset, about 0.05 arcseconds, at every instant; before, the timing error happened to offset part of it, which is why the overall median moved from 0.046 to 0.050 while the Moon's halved. Earlier figures are in the site's history; this page always shows the latest run.

Per body

BodyLargest differenceMedianJPL solution used by Horizons
Sun0.195″0.047″DE441
Moon2.929″0.054″DE441
Mercury0.431″0.047″DE441
Venus0.231″0.049″DE441
Mars0.095″0.048″mar099
Jupiter0.123″0.051″jup365_merged
Saturn0.095″0.046″sat441l
Uranus0.254″0.066″ura184_merged
Neptune0.106″0.064″nep098_merged
Pluto0.091″0.043″plu060_merged

The one outlier

The Moon on 30 June 2050 differs by 2.929 arcseconds; every other comparison is under half an arcsecond. Converting a civil time to the dynamical time an ephemeris runs on requires ΔT, which is measured for the past and only extrapolated for the future. The Swiss Ephemeris uses 74.73 seconds of ΔT for that date; at the Moon's rate of motion, 2.929 arcseconds corresponds to the two systems disagreeing on ΔT by roughly five seconds. That is consistent with an extrapolation difference and is the most likely cause, though we have not obtained JPL's value to confirm it. It will not affect any 2050 date until 2050 arrives and ΔT is measured.

All 80 comparisons

Longitudes in degrees along the ecliptic of date, 0 to 360. The difference is Asterwise minus Horizons, in arcseconds.

1 January 1950, 00:00 UTC — JD 2433282.50000
BodyAsterwiseJPL HorizonsDifference
Sun280.004856°280.004830°+0.093″
Moon61.415434°61.415409°+0.090″
Mercury299.447278°299.447252°+0.093″
Venus316.979503°316.979477°+0.092″
Mars182.211223°182.211197°+0.095″
Jupiter306.505359°306.505325°+0.123″
Saturn169.437441°169.437422°+0.069″
Uranus92.682791°92.682721°+0.254″
Neptune197.266065°197.266039°+0.093″
Pluto137.798387°137.798381°+0.021″
20 July 1969, 20:17 UTC — JD 2440423.34514
BodyAsterwiseJPL HorizonsDifference
Sun117.910743°117.910730°+0.046″
Moon187.873761°187.873753°+0.028″
Mercury115.842911°115.842899°+0.044″
Venus75.037422°75.037409°+0.048″
Mars242.773295°242.773283°+0.042″
Jupiter180.746241°180.746224°+0.060″
Saturn38.097998°38.097996°+0.009″
Uranus180.690021°180.690001°+0.072″
Neptune236.022925°236.022908°+0.063″
Pluto173.007183°173.007187°-0.015″
12 November 1985, 01:15 UTC — JD 2446381.55208
BodyAsterwiseJPL HorizonsDifference
Sun229.596716°229.596703°+0.047″
Moon221.838361°221.838343°+0.066″
Mercury252.179088°252.179075°+0.047″
Venus213.031986°213.031972°+0.051″
Mars189.652430°189.652416°+0.049″
Jupiter309.615963°309.615951°+0.043″
Saturn239.403371°239.403365°+0.023″
Uranus256.518242°256.518228°+0.051″
Neptune271.812678°271.812662°+0.056″
Pluto215.278855°215.278852°+0.012″
1 January 2000, 12:00 UTC — JD 2451545.00000
BodyAsterwiseJPL HorizonsDifference
Sun280.368923°280.368909°+0.050″
Moon223.323801°223.323786°+0.054″
Mercury271.889283°271.889270°+0.047″
Venus241.565793°241.565779°+0.049″
Mars327.963306°327.963292°+0.050″
Jupiter25.253088°25.253069°+0.070″
Saturn40.395663°40.395637°+0.095″
Uranus314.809187°314.809168°+0.068″
Neptune303.193012°303.193001°+0.041″
Pluto251.454777°251.454764°+0.045″
21 December 2012, 11:11 UTC — JD 2456282.96597
BodyAsterwiseJPL HorizonsDifference
Sun269.999569°269.999556°+0.047″
Moon14.237539°14.237524°+0.055″
Mercury254.698237°254.698223°+0.050″
Venus246.586146°246.586133°+0.048″
Mars296.427713°296.427699°+0.050″
Jupiter68.900779°68.900776°+0.012″
Saturn218.661038°218.661031°+0.024″
Uranus4.641019°4.641001°+0.064″
Neptune330.813461°330.813448°+0.046″
Pluto278.949404°278.949379°+0.091″
8 April 2024, 18:17 UTC — JD 2460409.26181
BodyAsterwiseJPL HorizonsDifference
Sun19.397806°19.397794°+0.045″
Moon19.360256°19.360251°+0.019″
Mercury24.799566°24.799554°+0.044″
Venus4.441792°4.441779°+0.047″
Mars343.049347°343.049334°+0.045″
Jupiter49.045165°49.045141°+0.086″
Saturn344.454960°344.454938°+0.078″
Uranus51.170990°51.170986°+0.015″
Neptune358.190056°358.190038°+0.065″
Pluto301.967628°301.967612°+0.058″
5 September 2026, 00:00 UTC — JD 2461288.50000
BodyAsterwiseJPL HorizonsDifference
Sun162.466161°162.466148°+0.047″
Moon81.376306°81.376294°+0.045″
Mercury170.075747°170.075734°+0.046″
Venus206.256933°206.256921°+0.042″
Mars105.919213°105.919200°+0.047″
Jupiter134.534412°134.534400°+0.043″
Saturn13.446074°13.446053°+0.077″
Uranus65.682488°65.682490°-0.006″
Neptune3.566514°3.566495°+0.068″
Pluto303.441539°303.441528°+0.041″
30 June 2050, 12:00 UTC — JD 2469988.00000
BodyAsterwiseJPL HorizonsDifference
Sun98.922069°98.922015°+0.195″
Moon224.357974°224.357160°+2.929″
Mercury110.984285°110.984165°+0.431″
Venus140.969345°140.969281°+0.231″
Mars325.337280°325.337276°+0.013″
Jupiter127.214993°127.214987°+0.022″
Saturn307.531895°307.531896°-0.005″
Uranus167.209741°167.209812°-0.254″
Neptune57.383267°57.383237°+0.106″
Pluto340.610638°340.610659°-0.076″

Reproduce it

The script queries Horizons live, runs the Swiss Ephemeris directly, and, if you set an Asterwise API key, calls the public endpoint so you can confirm the same numbers arrive over HTTP. A free key is enough. The Asterwise and Swiss Ephemeris columns agree to 0.0020 arcseconds, which is floating-point noise; the Horizons column is the independent check. The script converts UTC to UT1 with swe.utc_to_jd, as the API does.

pip install pyswisseph requests
curl -O https://asterwise.com/public/accuracy/compare.py
SE_EPHE_PATH=/path/to/swisseph/ephe ASTERWISE_API_KEY=aw_... python3 compare.py

The Swiss Ephemeris data files are not bundled with pyswisseph; download sepl_18.se1, semo_18.se1 and sepl_24.se1 from the ephe directory of the Swiss Ephemeris repository (the location astro.com's own download page points to) and point SE_EPHE_PATH at them. Without them the library falls back to its built-in Moshier ephemeris, which is less precise than the files Asterwise runs on, and the Swiss Ephemeris column will drift from this page.

Questions about the check

How accurate is the Swiss Ephemeris compared with NASA JPL Horizons?
Across 80 geocentric ecliptic longitudes (10 bodies at 8 instants from 1950 to 2050), Asterwise output built on the Swiss Ephemeris differed from JPL Horizons by a median of 0.050 arcseconds, with a 95th percentile of 0.231 arcseconds. 79 of 80 positions agreed within half an arcsecond. One arcsecond is 1/3600 of a degree, far below the two decimal places most charts display.
What exactly was compared?
Apparent geocentric ecliptic-of-date longitudes returned by POST /v1/western/natal (tropical) against the JPL Horizons observer table for centre 500@399, quantity 31, at eight instants between 1950 and 2050. Location does not affect geocentric planetary positions. The engine commit was 7d68ba3, the build serving production when the page was generated on 28 September 2026.
What is the largest difference and why?
2.929 arcseconds, for the Moon at the 2050 instant, the last in the range. The likely cause is that the two systems extrapolate delta-T (the offset between terrestrial and universal time) differently that far ahead; this has not been confirmed with JPL. 79 of the 80 positions agree within half an arcsecond.
Can I reproduce the check myself?
Yes. The comparison script (compare.py) and the raw comparison data (JSON) are published on this page. The script queries Horizons live, runs the Swiss Ephemeris directly and, with an Asterwise API key, calls the public endpoint so the same numbers can be confirmed over HTTP.

Downloads: raw comparison data (JSON) · compare.py. The Horizons responses are fetched live, so your run can differ from this page by hundredths of an arcsecond if JPL revises an ephemeris.