Scheduled Downtime
On Friday 21 April 2023 @ 5pm MT, this website will be down for maintenance and expected to return online the morning of 24 April 2023 at the latest

Using the ECMWF Climate Data Store (CDS) to Download ERA5 Data in a Conda Environment

William.Hatheway

Active member

Using the ECMWF Climate Data Store (CDS) to Download ERA5 Data in a Conda Environment​

This guide shows you how to:

  1. Create a Conda environment called CDS with pip and cdsapi
  2. Activate the environment
  3. Set up your CDS API token (.cdsapirc)
  4. Use the Python script Download_CDS_ERA5_Data_Hourly.py to download hourly ERA5 pressure-level and surface data

1. Create the Conda Environment CDS​

Make sure you have conda (Anaconda or Miniconda) installed.

1.1 Create the environment (with Python and pip)​

conda create -n CDS python=3.10 pip
  • -n CDS → environment name is CDS
  • python=3.10 → sets Python version
  • pip → ensures pip is available in the environment

1.2 Activate the environment​

conda activate CDS
Your shell prompt should now show (CDS) at the beginning.

1.3 Install cdsapi inside CDS​

pip install "cdsapi>=0.7.7"
This installs the official Climate Data Store API client library.


2. Get and Set Up Your CDS API Token​

The script uses the cdsapi client, which reads your credentials from a file called ~/.cdsapirc.

2.1 Get your token from the CDS website​

  1. Log in to the Copernicus Climate Data Store (CDS).
  2. Go to the CDS API / personal access token page.
  3. You will see something like:
    url: https://cds.climate.copernicus.eu/api
    key: YOUR_PERSONAL_ACCESS_TOKEN
⚠️ Keep your key secret. Treat it like a password.

2.2 Create the .cdsapirc file​

On Linux/macOS (or WSL / Git Bash on Windows):

nano ~/.cdsapirc
Paste in:

url: https://cds.climate.copernicus.eu/api
key: YOUR_PERSONAL_ACCESS_TOKEN
Save and exit.

2.3 Quick test: can cdsapi see your token?​

With the CDS environment active:

python - << 'EOF'
import cdsapi
c = cdsapi.Client()
print("CDS client initialized successfully.")
EOF
If no error appears, your token and URL are configured correctly.


3. Overview of Download_CDS_ERA5_Data_Hourly.py​

The main script is:

Download_CDS_ERA5_Data_Hourly.py
It does four main things:

  1. Imports & description
    """
    Downloads hourly ERA5 pressure-level and surface-level data from CDS.

    - pressure-level files → ./pressure/
    - surface-level files → ./surface/
    """
    import os
    from datetime import date, timedelta
    from pathlib import Path
    import cdsapi
    • Uses cdsapi for downloads, Path for directories, date/timedelta for looping over days.
  2. CDS config helpers
    • _parse_cds_config(path)
      • Reads a .cdsapirc-style file and extracts url and key.
    • get_cds_client()
      • Looks for:
        • ~/.cdsapirc (home directory), or
        • .cdsapirc in the script directory
      • If found, returns a configured cdsapi.Client.
      • If not, interactively asks for:
        • URL and key or
        • Path to an existing .cdsapirc.
  3. User input helpers
    • prompt_int(prompt_text, default)
      • Prompts for an integer with a default (for year/month/day).
    • prompt_float(prompt_text, default)
      • Prompts for a float with a default (for lat/lon).
  4. Main download logic
    • download_era5_data(start_year, start_month, start_day, end_year, end_month, end_day, north_latitude, south_latitude, west_longitude, east_longitude, https_proxy=None)
    • Inside this function:
    • Optional proxy support via HTTPS_PROXY / https_proxy env vars.
    • Calls get_cds_client() to get an authenticated cdsapi.Client.
    • Creates output folders next to the script:
      • pressure/
      • surface/
    • Builds a list of all 24 hours:
      times = [
      "00:00", "01:00", "02:00", "03:00",
      "04:00", "05:00", "06:00", "07:00",
      "08:00", "09:00", "10:00", "11:00",
      "12:00", "13:00", "14:00", "15:00",
      "16:00", "17:00", "18:00", "19:00",
      "20:00", "21:00", "22:00", "23:00",
      ]
    • Loops from the start date to the end dateand for each day/hour:
      • Builds file names like:
        • pressure/preslev_YYYYMMDD_HHMM.grib
        • surface/surface_YYYYMMDD_HHMM.grib
      • Issues two CDS requests per hour:
      • (a) Pressure levels
      c.retrieve(
      "reanalysis-era5-pressure-levels",
      {
      "product_type": "reanalysis",
      "format": "grib",
      "year": stryear,
      "month": strmonth,
      "day": strday,
      "time": [hour],
      "variable": [
      "divergence", "fraction_of_cloud_cover", "geopotential",
      "ozone_mass_mixing_ratio", "potential_vorticity",
      "relative_humidity",
      "specific_cloud_ice_water_content",
      "specific_cloud_liquid_water_content",
      "specific_humidity",
      "specific_rain_water_content",
      "specific_snow_water_content",
      "temperature",
      "u_component_of_wind",
      "v_component_of_wind",
      "vertical_velocity",
      "vorticity",
      ],
      "pressure_level": [
      "10", "20", "30", "50", "70", "100", "125", "150", "175",
      "200", "225", "250", "300", "350", "400", "450", "500",
      "550", "600", "650", "700", "750", "775", "800", "825",
      "850", "875", "900", "925", "950", "975", "1000",
      ],
      "area": [
      north_latitude, west_longitude,
      south_latitude, east_longitude,
      ],
      "grid": [0.25, 0.25],
      },
      str(pressure_filename),
      )
      (b) Single (surface) levels
      c.retrieve(
      "reanalysis-era5-single-levels",
      {
      "product_type": "reanalysis",
      "format": "grib",
      "year": stryear,
      "month": strmonth,
      "day": strday,
      "time": [hour],
      "variable": [
      "10m_u_component_of_wind",
      "10m_v_component_of_wind",
      "2m_dewpoint_temperature",
      "2m_temperature",
      "land_sea_mask",
      "mean_sea_level_pressure",
      "sea_ice_cover",
      "sea_surface_temperature",
      "skin_temperature",
      "snow_density",
      "snow_depth",
      "soil_temperature_level_1",
      "soil_temperature_level_2",
      "soil_temperature_level_3",
      "soil_temperature_level_4",
      "surface_pressure",
      "volumetric_soil_water_layer_1",
      "volumetric_soil_water_layer_2",
      "volumetric_soil_water_layer_3",
      "volumetric_soil_water_layer_4",
      ],
      "area": [
      north_latitude, west_longitude,
      south_latitude, east_longitude,
      ],
      "grid": [0.25, 0.25],
      },
      str(surface_filename),
      )
    • After all downloads:
      print("Hourly ERA5 downloads complete.")
      print(f"Pressure files saved in: {pressure_dir}")
      print(f"Surface files saved in: {surface_dir}")

4. Interactive Main Block​

At the bottom of the script:

if __name__ == "__main__":
print("=== ERA5 Download Configuration ===")
print("Press Enter to accept the default value shown in [brackets].\n")

# Default values
default_start_year = 2024
default_start_month = 9
default_start_day = 25

default_end_year = 2024
default_end_month = 9
default_end_day = 29

default_north_lat = 45.0
default_south_lat = 5.0
default_west_lon = 60.0
default_east_lon = 100.0
The script then:

  1. Prompts for start/end year, month, day using prompt_int.
  2. Prompts for north/south latitude and west/east longitude using prompt_float.
  3. Optionally asks for an HTTPS proxy.
  4. Prints a summary of your choices.
  5. Calls download_era5_data(...) with the values you entered.
From a user perspective:

  1. Run the script.
  2. Accept defaults or enter your own values.
  3. Files appear in pressure/ and surface/ directories next to the script.

5. How to Run the Script in the CDS Conda Environment​

Assuming:

  • Script path:
    /media/yourdisk/Download_CDS_ERA5_Data_Hourly.py
  • CDS environment is set up.
  • .cdsapirc is configured.

5.1 Activate the environment​

conda activate CDS

5.2 Run the script​

python "/media/yourdisk/Download_CDS_ERA5_Data_Hourly.py"

5.3 Follow the prompts​

You’ll see something like:

=== ERA5 Download Configuration ===
Press Enter to accept the default value shown in [brackets].

Start date:
Start year [2024]:
Start month [9]:
Start day [25]:

End date:
End year [2024]:
End month [9]:
End day [29]:

Geographic bounding box (latitudes/longitudes):
Note: North > South; longitudes in degrees (West/East, can be negative).
North latitude [45.0]:
South latitude [5.0]:
West longitude [60.0]:
East longitude [100.0]:

HTTPS proxy (optional).
Example: http://user: password@proxy-server: port
Enter HTTPS proxy (or leave blank for none):
Press Enter to accept defaults or type your own values. The script will print messages like:

Requesting data for 20240925 00:00
and will write the GRIB files into:

  • pressure/
  • surface/

Pytthon Code attached in Zip Files
 

Attachments

  • Download_CDS_ERA5_Data_Hourly.zip
    4.3 KB · Views: 2
Last edited:
Top