A how-to guide implementing NASA's Astronomy Picture Of The Day (APOD) and Earth Polychromatic Imaging Camera (EPIC) APIs
This section contains an introduction to NASA’s application programming interfaces (APIs), some background, and how to set it up.
APIs provide an interface for machines to talk with each other. NASA’s APIs allow developers to use NASA’s data, such as imagery, for application development.
NASA gathers a lot of data - over 15 Terabytes per day! And by a White House mandate this data is free to the public - in a format useful to you. This is where the APIs come into play.
Figuring out the best way to distribute, use, and reuse NASA’s data is a problem. NASA’s APIs provide a solution by lowering the barrier of entry to people outside NASA to easily manipulate and access the public information.
A list of NASA APIs beginning with the Astronomy Picture Of The Day (APOD) can be found here. Here are some of the APIs available:
Head over to api.NASA.gov and follow the applying for an API key link to get your personal API key. The process takes ~5 minutes and NASA will email your key to you.
We will be working with these two APIs:
The following will be covered for each API:
Lets get started!
The APOD is a good API to start with because it’s easy to work with.
Documentation can be found here, it is brief but this is understandable for such a simple call.
The APOD call returns a JSON object containing an image or video, date, explanation, and additional metadata. It’s our job to make the call and manipulate the received data however we want.
APOD uses a GET HTTP request method to request data from the NASA server. GET methods request data from a specified request url. The following shows the HTTP method and the request url.
GET https://api.nasa.gov/planetary/apod
We append parameters to the url to create a query string (parameter/value pairs) to tell the NASA server who’s making the call (api_key parameter) and if we want something in return besides the defaults. The table below shows the query parameters.
APOD Query Parameters
Parameter | Type | Default Value | Description |
---|---|---|---|
date | YYYY-MM-DD | today | The date of the APOD image to retrieve |
hd | bool | False | Retrieve the URL for the high resolution image |
api_key | string | DEMO_KEY | api.nasa.gov key for expanded usage |
Here is an example query. It begins with the GET request url from above followed a ?
signifying the beginning of the query string. Follow the link to make the request!
https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY
Here is an example request for the first ever APOD image. Append additional parameters to the querystring with with &
and use =
to create parameter/value pairs like before.
https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY&date=1995-06-16
The request returns information in JavaScript Object Notation (JSON). JSON is a syntax used for storing and exchanging data between a client (browser) and a server (NASA database). Here is the JSON returned from our last request:
{
"date": "1995-06-16",
"explanation": "Today's Picture: Explanation: If the Earth could somehow be transformed to the ultra-high density of a neutron star , it might appear as it does in the above computer generated figure. Due to the very strong gravitational field, the neutron star distorts light from the background sky greatly. If you look closely, two images of the constellation Orion are visible. The gravity of this particular neutron star is so great that no part of the neutron star is blocked from view - light is pulled around by gravity even from the back of the neutron star. We keep an archive file. Astronomy Picture of the Day is brought to you by Robert Nemiroff and Jerry Bonnell . Original material on this page is copyrighted to Robert Nemiroff and Jerry Bonnell.",
"hdurl": "https://apod.nasa.gov/apod/image/e_lens.gif",
"media_type": "image",
"service_version": "v1",
"title": "Neutron Star Earth",
"url": "https://apod.nasa.gov/apod/image/e_lens.gif"
}
Properties and values are in quotes " "
and are seperated with a colon :
. This standard notation makes accessing and manipulating received data easy to work with using JavaScript.
We have covered how to make a call to the server and what the server sends back to us. Now it time to access the object we recieve, parse it, and use it in our application. We will be using JavaScript and HTML to display our end product. The following is our code in action.
We begin with the variable list:
var req = new XMLHttpRequest();
var url = "https://api.nasa.gov/planetary/apod?api_key=";
var api_key = "DEMO_KEY";
We define a new XMLHttpRequest and assign in to the variable req. An XMLHttpRequest provides client functionality for transferring data between a client and server. Think of it as a stream that connects our browser (client) the NASA databases (server). For ease of use, we define variables, url and api_key to hold the GET request url and API Key. Use your own API KEY by simply changing the api_key value.
The XMLHttpRequest open method initializes a request. Here are its parameters:
req.open(method, url)
We are using a GET method and have combined the url and api_key variables to create a valid url. After the request is initialized (opened) we send it to the server.
req.open("GET", url + api_key, true);
req.send();
the XMLHttpRequest addEventListener method listens for an event type and executes a function when the event fires (is fulfilled).
req.addEventListener("load", function(){
if(req.status == 200 && req.readyState == 4){
var response = JSON.parse(req.responseText);
document.getElementById("title").textContent = response.title;
document.getElementById("date").textContent = response.date;
document.getElementById("pic").src = response.hdurl;
document.getElementById("explanation").textContent = response.explanation;
}
})
The event type is load so when req (our XMLHttpRequest) is finished loading the function exececutes. Inside the function we check two things before manipulating the received data.
The status method returns a numerical status code of the response of the XMLHttpRequest. 200 denotes a succesful request.
req.status == 200
The readyState method returns the state an XMLHttpRequest client is in. 4 denotes the operation is complete.
req.readyState == 4
When both these properties are true it means the request was a success and we succesfully received the data from the server. The data recieved from the server is raw text in JSON format. We parse it into the variable response with the following code.
var response = JSON.parse(req.responseText);
Now we have neat variable that holds all the data received in JSON format. We access the Document Object Model (DOM) and change HTML elements with final lines of code:
document.getElementById("title").textContent = response.title;
document.getElementById("date").textContent = response.date;
document.getElementById("pic").src = response.hdurl;
document.getElementById("explanation").textContent = response.explanation;
Official documentation can be found on the EPIC API Documentation Page, it is more in depth than the APOD documentation.
The EPIC API gives access to the pictures taken by EPIC (Earth Polychromatic Imaging Camera) onboard NOAA’s (National Oceanic and Atmospheric Administration) DSCOVR (Deep Space Climate Observatory). Along with imagery, the API provides image metadata in JSON format.
EPIC uses a GET HTTP request method to request data from the NASA server. GET methods request data from a specified request url. The following shows the HTTP method and the request url.
GET https://epic.gsfc.nasa.gov/EPIC/api
Create a path with slashes /
to append parameters to the URL. This is different from the APOD which uses the paramter=value
query-string format.
EPIC Query Parameters
Parameter | Type | Default Value | Description |
---|---|---|---|
natural | string | Most Recent Natural Color | Metadata on the most recent date of natural color imagery. |
natural/date | YYYY-MM-DD | Most Recent Available | Metadata for natural color imagery available for a given date. |
natural/all | string | Dates for Natural Color | A listing of all dates with available natural color imagery. |
natural/available | string | Dates for Natural Color | Alternate listing of all dates with available natural color imagery. |
enhanced | string | Most Recent Enhanced Color | Metadata on the most recent date of enhanced color imagery. |
enhanced/date | YYYY-MM-DD | Most Recent Available | Metadata for enhanced color imagery for a given date. |
enhanced/all | string Dates for Enhanced Imagery | A listing of all dates with available enhanced color imagery. | |
enhanced/available | string | Dates for Enhanced Imagery | Alternate listing of all dates with available enhanced color imagery. |
api_key | string | DEMO_KEY | api.nasa.gov key for expanded usage |
Here is an example URL requesting the most recent natural color image. It begins with the GET request url from above followed by a /
signifying the beginning of the path. When the path ends we append our personal api_key. Follow the link to make the request!
https://api.nasa.gov/EPIC/api/natural?api_key=DEMO_KEY
Here is an example request for the enhanced image taken on October 31st, 2015. Append additional parameters to the URL path with /
and remember to end the URL with your API key.
https://api.nasa.gov/EPIC/api/enhanced/date/2015-10-31?api_key=DEMO_KEY
The request returns an array of JSON objects enclosed in the outermost most brackets[ ]
. Each JSON ojbect contains information for a single image. The retrievable metadata includes the image name, date, caption, and positional data. Here is an exceprt of the beginning of the JSON object information returned from our last request:
[{
"image":"epic_RGB_20151031003633_01",
"caption":"This image was taken by the NASA EPIC camera onboard the NOAA DSCOVR spacecraft",
"centroid_coordinates":{"lat":-5.07641,"lon":159.547159},
"dscovr_j2000_position":{"x":-1283061.5,"y":-669893.4375,"z":-130240.867188},
"lunar_j2000_position":...
}]
The actual response is much longer and includes numerous positional data sets such as lunar and sun positions in space. For our application we want access to the image file which is not returned. Use the image name returned to access the actual image source. Here is the syntax for creating the image source URL. Variables are denoted with a $
and are in all caps.
https://epic.gsfc.nasa.gov/archive/$COLLECTION/$YEAR/$MONTH/$DAY/$IMAGE_TYPE/$IMAGE_NAME.$IMAGE_TYPE
$COLLECTION
can be natural
or enhanced
.
$YEAR/$MONTH/$DAY
is in the format YYYY/MM/DD.
$IMAGE_TYPE
can be png
, jpg
, or thumbs
.
$IMAGE_NAME
is the image name returned in JSON object.
Here is the complete URL for a full-sze original PNG image from our last request.
https://epic.gsfc.nasa.gov/archive/enhanced/2015/10/31/png/epic_RGB_20151031003633_01.png
On July 5th, 2016 the moon passed between DSCOVR and the Earth. EPIC snapped images over a period of about 4 hours. The entire set consists of 15 pictures where one can see the far side of the moon, which is never seen from Earth. The following example uses the EPIC API to access 3 of these pictures to create an automatic slideshow showing the lunar Transit!
Begin by getting the pictures from the NASA server using the EPIC API. The process is similar to the APOD example above except this time we define two new variables img_url and img_type to be used to complete the image source url.
var req = new XMLHttpRequest();
var url = "https://api.nasa.gov/EPIC/api/natural/date/2016-07-05?api_key=";
var api_key = "5B6oJsSCQyekXZvNOKpsUhRPl1e7FHqjIAyHpybk";
var img_url = "https://epic.gsfc.nasa.gov/archive/natural/2016/07/05/png/";
var img_type = ".png";
req.open("GET", url + api_key);
req.send();
Let’s take a closer look at the request url.
var url = "https://api.nasa.gov/EPIC/api/natural/date/2016-07-05?api_key=";
We use the natural/date paramter specifying the date 2016-07-05. In other words, we are requesting all the images and their metadata from July 5th, 2016.
Then we receive and parse our request into JSON just like we did with APOD API.
req.addEventListener("load", function(){
if(req.status == 200 && req.readyState == 4){
var response = JSON.parse(req.responseText);
From the What gets received section, we receive an array of JSON objects. To access the image names in each object we use bracket notation.
document.getElementById("img1").src = img_url + response[4].image + img_type;
document.getElementById("img2").src = img_url + response[7].image + img_type;
document.getElementById("img3").src = img_url + response[10].image + img_type;
With the three image source URLs taken care of, we can implement the slideshow.
var slideIndex = 0;
showSlides();
function showSlides() {
var i;
var slides = document.getElementsByClassName("mySlides");
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
slideIndex++;
if (slideIndex> slides.length) {slideIndex = 1}
slides[slideIndex-1].style.display = "block";
setTimeout(showSlides, 2000); // Change image every 2 seconds
}
The function showSlides()
cycles through the images in the for-loop and hides them by setting the style.display
property to "none"
.
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
Then the slideIndex
is incremented and checked to see if it needs to reset back to the first image
slideIndex++;
if (slideIndex> slides.length) {slideIndex = 1}
The current image is rendered as a block element by setting the style.display
property to "block"
.
slides[slideIndex-1].style.display = "block";
Finally, we call the ShowSlides()
function recursively with the setTimeout()
function which takes a timing parameter set to 2 seconds for each image in this case. The slideshow cycles indefinitely because there is no base case to halt the recursive call.
Here is a list of the primary links used in the making of this guide. They include additional information on the various topics covered.