ESO Logo

 How to download data


This section of the "ESO Science Archive Programmatic: HOWTOs" shows how to programmatically download ESO data, either anonymously (for public data) or with authentication (for proprietary data), using Python.

_Usage: You can access this file either as a static HTML page (download it here), or as an interactive jupyter notebook (download it here) which you can download and run on your machine (instructions). To interact with the jupyter notebook: move up and down the various cells using the arrow keys, execute the code by pressing CTRL+ENTER; you can also modify the code and execute it at will._


Let's start by setting up the python modules:

In [ ]:
import os 
import sys

import requests
import cgi
import json

import getpass

Let's define a couple of utility functions, useful to write the files on disk using the ESO file name (provided in the response http header, via the Content-Disposition field.

In [ ]:
def getDispositionFilename( response ):
    """Get the filename from the Content-Disposition in the response's http header"""
    contentdisposition = response.headers.get('Content-Disposition')
    if contentdisposition == None:
        return None
    value, params = cgi.parse_header(contentdisposition)
    filename = params["filename"]
    return filename

def writeFile( response ):
    """Write on disk the retrieved file"""
    if response.status_code == 200:
        # The ESO filename can be found in the response header
        filename = getDispositionFilename( response )
        # Let's write on disk the downloaded FITS spectrum using the ESO filename:
        with open(filename, 'wb') as f:
            f.write(response.content)
        return filename 

How to retrieve a file anonymously

Without the need to authenticate, any user can anonymously download public files, that is, files that are out of the proprietary period (of usually one year from the moment the observation takes place).

In [ ]:
file_url = 'https://dataportal.eso.org/dataportal_new/file/ADP.2016-11-17T12:51:01.877'

response = requests.get(file_url)
filename = writeFile( response )
if filename:
    print("Saved file: %s" % (filename))
else:
    print("Could not get file (status: %d)" % (response.status_code))

How to retrieve a file with authentication

If the files you need to retrieve are under proprietary period, you can access them only if you have the rights to do so, that is, if you are the principal investigator [PI] of the observing program the files belong to, or one of his/her delegates. In this case, you certainly got already a (free) user account at the ESO User Portal.

Before downloading the file you have to authenticate and get a token. Here is the method that, given your ESO credentials (username and password), returns the token.

In [ ]:
def getToken(username, password):
    """Token based authentication to ESO: provide username and password to receive back a JSON Web Token."""
    if username==None or password==None:
        return None
    token_url = "https://www.eso.org/sso/oidc/token"
    token = None
    try:
        response = requests.get(token_url,
                            params={"response_type": "id_token token", "grant_type": "password",
                                    "client_id": "clientid",
                                    "username": username, "password": password})
        token_response = json.loads(response.content)
        token = token_response['id_token']+'=='
    except NameError as e:
        print(e)
    except:
        print("*** AUTHENTICATION ERROR: Invalid credentials provided for username %s" %(username))
    
    return token

Once you get the token, you need to add it to the HTTP header before HTTP-getting the file. Let's see how:

In [ ]:
# Suppose the file you want to download is accessible via the following link
# (please change the identifier (ADP.2020-03-24T1:45:21.866) to one of your proprietary files):

file_url = 'https://dataportal.eso.org/dataportal_new/file/ADP.2020-03-24T10:45:21.866'

# If you have not modified the identifier of that file,
# likely you won't be authorised to download the file.
# Expect a failure "Could not get file (status: 401)" in that case.

# Let's get the token, by inputting your credentials:
username = input("Type your ESO username: ")
password=getpass.getpass(prompt="%s user's password: "%(username), stream=None)
token = getToken(username, password)

# With successful authentication you get a valid token,
# which needs to be added to the HTTP header of your GET request,
# as a Bearer:

headers = None
if token!=None:
    headers = {"Authorization": "Bearer " + token}
    response = requests.get(file_url, headers=headers)
    filename = writeFile( response )
    if filename:
        print("Saved file: %s" % (filename))
    else:
        print("Could not get file (status: %d)" % (response.status_code))
else:
    print("Could not authenticate")