Skip to content

Precipitation (CHIRPS)

CHIRPS v3.0 Overview

CHIRPS v3.0 is available for three domains: Global, Africa, and Latin America. Similar to CHIRPS v2.0, two products of CHIRPS v3.0 are available. A preliminary version and a final version. The preliminary version is produced at the end of every pentad with rapidly available Global Telecommunication System (GTS) data, while the final version – produced about two weeks after the end of the month – incorporates data from the Global Historical Climatology Network (GHCN), and the Global Summary of the Day (GSOD).

CHIRPS v3.0 benefits from nearly four times more sources of gauge data compared to CHIRPS v2.0. This increased volume of observations significantly improves the spatial and temporal accuracy of rainfall estimates.


Dataset Overview



Download CHIRPS PCP

The following script downloads monthly CHIRPS v3.0 GeoTIFFs for a given year range:

import requests
import os
import numpy as np
import rasterio
from osgeo import gdal
import calendar

first_year = 1981
last_year = 2024


temporal_resolution="Annual" # Annual, Monthly , Dekadal or Daily
# Data Available : 1981 - present


output_folder_path = "/Users/amanchaudhary/Documents/Resources/World_Bank/Zambia"   
geojson_boundary = "/Users/amanchaudhary/Documents/Resources/World_Bank/Zambia/Shapefile/Zambia_L0.geojson" 

# ressampling 5km chirps pcp to 300m
resampling=False
# resampling=True


output_folder = os.path.join(output_folder_path, f"CHIRPS_v3_PCP_{temporal_resolution}") 

os.makedirs(output_folder, exist_ok=True)



filenames = []
if temporal_resolution == "Annual":
    for year in range(first_year, last_year + 1):
        url = f"https://data.chc.ucsb.edu/products/CHIRPS/v3.0/annual/global/tifs/chirps-v3.0.{year}.tif"
        output_filename = f"PCP_{year}0101.tif"
        filenames.append((url, output_filename))

elif temporal_resolution == "Monthly":
    for year in range(first_year, last_year + 1):
        for month in range(1, 13):
            url = f"https://data.chc.ucsb.edu/products/CHIRPS/v3.0/monthly/global/tifs/chirps-v3.0.{year}.{month:02d}.tif"
            output_filename = f"PCP_{year}{month:02d}01.tif"
            filenames.append((url, output_filename))
elif temporal_resolution == "Dekadal":
    for year in range(first_year, last_year + 1):
        for month in range(1, 13):
            for dekad in range(1, 4):  
                url = f"https://data.chc.ucsb.edu/products/CHIRPS/v3.0/dekads/global/tifs/chirps-v3.0.{year}.{month:02d}.{dekad}.tif"
                output_filename = f"PCP_{year}{month:02d}_D{dekad}.tif"
                filenames.append((url, output_filename))
elif temporal_resolution == "Daily":
    for year in range(first_year, last_year + 1):
        for month in range(1, 13):
            num_days = calendar.monthrange(year, month)[1]
            for day in range(1, num_days + 1):
                url = f"https://data.chc.ucsb.edu/products/CHIRPS/v3.0/daily/global/tifs/chirps-v3.0.{year}.{month:02d}.{day:02d}.tif"
                output_filename = f"PCP_{year}{month:02d}{day:02d}.tif"
                filenames.append((url, output_filename))


else:
    raise ValueError("temporal_resolution must be 'Annual' or 'Monthly'")

total = len(filenames)
print("Total files:",total)


for url, output_filename in filenames:

    output_path = os.path.join(output_folder, output_filename)

    print(f"Downloading {output_filename} from {url} ...")

    vsicurl_url = f"/vsicurl/{url}"

    if resampling:

        try:
            temp_full = os.path.join(output_folder, f"temp_full_{output_filename}")

            # Save full raster locally first
            gdal.Translate(
                destName=temp_full, 
                xRes=0.003,  # 300m resolution
                yRes=0.003,
                resampleAlg="near",
                srcDS=vsicurl_url)
        except Exception as e:
            print(f"❌ Failed to download full raster: {e}")
            continue

        try:
            # 2. Resample and clip the downloaded raster
            warp_options = gdal.WarpOptions(
                cutlineDSName=geojson_boundary,
                cropToCutline=True,
                dstNodata=-9999,

            )
            gdal.Warp(destNameOrDestDS=output_path, srcDSOrSrcDSTab=temp_full, options=warp_options)
        except Exception as e:
            print(f"❌ GDAL warp failed for {output_filename}: {e}")

        # Remove intermediate file
        if os.path.exists(temp_full):
            os.remove(temp_full)
        print(f"✅ Processed and saved: {output_filename}")


    else:
        warp_options = gdal.WarpOptions(
            cutlineDSName=geojson_boundary,
            cropToCutline=True,
            dstNodata=-9999
        )
        gdal.Warp(destNameOrDestDS=output_path, srcDSOrSrcDSTab=vsicurl_url, options=warp_options)
        print(f"✅ Processed and saved: {output_filename}")