Saturday, November 5, 2011

Planetary states API

Update: This API is deprecated. Use the new json api instead.

I needed a way to deal with planetary positions and velocities and found NASA's HORIZONS and the ephemerides. But I wanted a simpler interface than telnet or lugging around the massive ephemeris files with my applications. So instead, I wrote a simple JSON api for dealing with ephemeris files.

Suppose one wanted to get the chebyshev coefficients for computing mercury's state for today's date (November 5th), the URL query would look like this:

Which would return a JSON object whose structure looks like this:

"date": 2455870.5,
"results": {
{"mercury": {
"coeffs": ...
"start": 2455856.5,
"end": 2455872.5

Where "coeffs" contains the chebyshev coefficients for evaluating the state of mercury between the julian dates 2455856.5 and 2455872.5

To simplify it even further, you can grab the state of mercury at 9:30am on November 5th 2011 by using this url:

Which would return:

"date": 2455870.89583,
"results": {
"mercury": [
[30007449.557, -50119248.882, -29922524.4351],
[2879610.10503, 2030853.04543, 786401.74378]

Where the first array in "mercury" is the position vector (x, y, z) and the second array is the velocity vector (vx, vy, vz)

Multiple planets can be entered, comma-separated.

Applications requiring entire ephemeride records can use this:

This will give you...

"date": 2455870.89583,
"start": 2455824.5,
"end": 2455888.5,
"results": {
"mercury": [

Where date is the date asked for, start is the beginning of the record and end is the end of the record. "results" contains every ephemeris body mapped to a list of its coefficient chunks for that record.

The ephemeris being used is DE406 for the time being, though I may add others later (and a backwards compatible means of specifying).

It doesn't include the full date range of DE406 yet, it only contains dates between 2000-2200 (I'll be adding more as needed, if you request a range increase it will probably be granted).

To see a web application using it in action, visit and click "start" (its streaming the records to evaluate positions for the planets, the interface can be dragged and zoomed with the mouse).

Lastly, the constants section of the ephemeris is also available from the url

When querying for coefficients, you can't ask for earth or moon directly. You have to use "earthmoon" (the earthmoon barycenter) and "geomoon" (the geocentric moon) and compute their states from those. However, when querying for "states", astro-phys does this for you.

PS: All api queries can also take a '&callback=somefunction' to be treated as jsonp. This works great with jquery's getJSON

Here's an example using jQuery.getJSON (note, when date is missing the current time is assumed)
var url = '';
$.getJSON(url, {bodies: 'mercury'}, function(data) {
var p = data.results.mercury[0];
var v = data.results.mercury[1];


Frederic Pearl, PhD said...

Thank you for writing this API. I hope you will leave it up forever, or teach me how to get the data directly. How come the data is limited to 200 years? Suppose I want to know the xyz position of a planet on March 15th 410 AD? Is it even possibly to query for such data?

Wybiral said...

I do plan to leave it up. Especially with the feedback I've gotten (seeing it put to use in situations like mobile apps is promising). The timeframe is limited because the ephemerides are limited, but I can extend it some in both directions.

Its computing the positions from JPL's DE406 ephemeris. I will, undoubtably, have it cover all of the 406 range before long. I can try to add data outside of that if I can find a semi-reliable way of doing so.

What I also plan to do is add a Javascript API that will push off more of the computation to the client (thats how the site's main page does it, and its the most feasable in the case of wider adoption unless I can fund more serve power).

Glad to hear its being put to various uses though. It annoyed me that JPL only offered a telnet interface. If anyone has any advice on supporting things like rotational computations, let me know.

Wybiral said...

I've finally gotten around to expanding it. As of now it covers 1700AD-2100AD. I should have it all the way from 100AD to 3000AD within the next week.

It's Thick said...

This is incredible.

Thank you for putting this together -

I am also eager to help make sure this is maintained and lives on -

Please let me know if I can be of any assistance -


alana hosick said...

Is The api down? I have been getting date out of range errors for all dates. Has something changed?

Wybiral said...

It did go down. It's hosted on Google App Engine which has daily usage quotas and it appears to have met them.

I can reorganize things a bit to reduce some of the load (caching results / optimizing database reads) but it might be sketchy for a while.

It would help to know what your use-case is like (what kinds of queries you use it for) so I can factor that in when optimizing it.

alana hosick said...

I love your service. I think it is great that you have it.
I use it to get the xyz coordinates of the planets on different days.

Is there a query to get the RA and declination too?

Wybiral said...

There is no way to get ascension / declination right now. I'd like to add those but I need a reliable way to calculate them (I'm open to suggestions).

It looks like the quota issue was due to database reads rather than CPU usage (a bit surprising since it's evaluating all of those coefficients for every state/position request). I suspect it's because the records are somewhat large (the entire reason I wanted it as a web service is because it's impractical to lug around the actual records).

I can probably eliminate some of that by splitting the records into smaller pieces but then grabbing the data for every planet will increase the number of queries.

If that happens again it will error with "Daily quota exceeded! :(" instead of the date range error.

Thanks for the feedback! I'm always curious to see how people use this thing.

wmaster said...

Hi Wybiral!

This is a great API!

Now I am developing a project, and I would like to use your scripts.

You described, how to call the API with the parameters, I am just not sure, how can I apply timezone from this, through the URL:

Can you give me a brief, how can I set a specific timezone?