Python package to download and preprocess vegetation products from Copernicus services:
- HR-VPP (High Resolution Vegetation Phenology and Productivity) via WEkEO
- Sentinel-2 L2A raw data via CDSE (Copernicus Data Space Ecosystem)
The VPP_Index dataset (EO:EEA:DAT:CLMS_HRVPP_VI) currently returns 404 errors on WEkEO.
This dataset, which contained daily vegetation indices (LAI, FAPAR, NDVI, PPI), appears to have been discontinued or moved since 2024.
VPP_ST(Seasonal Trajectories): Contains PPI, QFLAGVPP_Pheno(Phenology & Productivity): Contains SOSD, MAXD, EOSD, LENGTH, AMPL, TPROD, etc.
- For PPI → Use
VPP_ST - For phenology parameters → Use
VPP_Pheno - For LAI, FAPAR, NDVI → Currently not available via PyVPP (see alternatives below)
See DATASETS_AVAILABLE.md for more details.
pip install pyvppPyVPP supports two main workflows:
import pyvpp
# Create .hdarc file with your credentials
pyvpp.create_hdarc("your_wekeo_username", "your_wekeo_password")import pyvpp
# Download phenology parameters (annual products)
downloader = pyvpp.wekeo_download(
dataset='VPP_Pheno', # ✅ Working
shape='path/to/your/area.shp', # or DEIMS ID
dates=['2020-01-01', '2020-12-31'],
products=['SOSD', 'MAXD', 'EOSD', 'LENGTH']
)
downloader.run()import pyvpp
# Download PPI (Plant Phenology Index) every 10 days
downloader = pyvpp.wekeo_download(
dataset='VPP_ST', # ✅ Working
shape='path/to/your/area.shp',
dates=['2020-01-01', '2020-12-31'],
products=['PPI', 'QFLAG']
)
downloader.run()import pyvpp
# ⚠️ WARNING: This dataset is currently returning 404 errors
# VPP_Index (LAI, FAPAR, NDVI) is not available as of January 2025
downloader = pyvpp.wekeo_download(
dataset='VPP_Index', # ⚠️ Returns 404 error
shape='path/to/your/area.shp',
dates=['2020-01-01', '2020-12-31'],
products=['LAI', 'FAPAR'] # Not available
)
# This will fail with: 404 Client ErrorNew in v0.4.0: Download Sentinel-2 L2A products directly from CDSE.
You have three options:
Option 1: Configuration file (recommended)
mkdir -p ~/.pyvpp
cat > ~/.pyvpp/config.toml << EOF
[cdse]
user = "your_email@example.com"
password = "your_password"
EOFOption 2: Environment variables
export CDSE_USER="your_email@example.com"
export CDSE_PASSWORD="your_password"Option 3: Direct in code
from pyvpp.cdse import load_cdse_credentials
# Credentials passed directly to CDSEDownloadRegister at: https://dataspace.copernicus.eu/
L2A - Bottom of Atmosphere (Default - Atmospherically Corrected)
from pyvpp import CDSEDownload
# Download Sentinel-2 L2A products (recommended for most use cases)
downloader = CDSEDownload(
shape='path/to/your/area.shp', # or DEIMS ID
dates=('2023-06-01', '2023-06-30'),
bands=['B04', 'B08'], # Red, NIR
outdir='sentinel2_data',
processing_level='L2A', # Default: atmospherically corrected
utm_zone='30T' # Optional: filter by UTM zone
)
# Run full pipeline: search -> download -> mosaic -> clip
downloader.run()L1C - Top of Atmosphere (No Atmospheric Correction - for ACOLITE, etc.)
from pyvpp import CDSEDownload
# Download Sentinel-2 L1C products (TOA reflectance)
# Useful for custom atmospheric correction (ACOLITE, Sen2Cor, etc.)
downloader = CDSEDownload(
shape='path/to/your/area.shp',
dates=('2023-06-01', '2023-06-30'),
bands=['B04', 'B08'],
outdir='sentinel2_L1C',
processing_level='L1C' # Top of Atmosphere
)
downloader.run()Output: one mosaic per requested band per acquisition date, organized
in subfolders <outdir>/YYYYMMDD_s2msi/. Files are named
YYYYMMDD_s2msi_<alias>.tif (e.g. 20230610_s2msi_b04_red.tif).
Each band is delivered in its native resolution (10 m or 20 m);
the SCL band keeps its uint8 dtype.
Processing Level Comparison:
L2A(default): Bottom of Atmosphere - atmospherically corrected, ready for analysisL1C: Top of Atmosphere - raw reflectance, use for custom atmospheric correction with tools like ACOLITE
Reflectance bands (any combination of resolutions can be requested in a single call):
| Band | Alias | Resolution | Description |
|---|---|---|---|
B02 |
b02_blue |
10 m | Blue |
B03 |
b03_green |
10 m | Green |
B04 |
b04_red |
10 m | Red |
B08 |
b08_nir |
10 m | NIR (broad, 842 nm) |
B01 |
b01_coastal |
20 m | Coastal aerosol |
B05 |
b05_re1 |
20 m | Red-edge 1 |
B06 |
b06_re2 |
20 m | Red-edge 2 |
B07 |
b07_re3 |
20 m | Red-edge 3 |
B8A |
b8a_nir |
20 m | NIR (narrow, 865 nm) |
B11 |
b11_swir1 |
20 m | SWIR 1 |
B12 |
b12_swir2 |
20 m | SWIR 2 |
Cloud / scene-classification mask (L2A only):
| Band | Alias | Resolution | Description |
|---|---|---|---|
SCL |
scl |
20 m | Sen2Cor Scene Classification Layer (categorical) |
Example use cases:
# NDVI calculation
CDSEDownload(shape='area.shp', dates=('2023-01-01', '2023-12-31'), bands=['B04', 'B08'])
# RGB visualization
CDSEDownload(shape='area.shp', dates=('2023-01-01', '2023-12-31'), bands=['B02', 'B03', 'B04'])
# Water mask / turbidity (mixes 10 m + 20 m + categorical SCL)
CDSEDownload(
shape='area.shp',
dates=('2023-01-01', '2023-12-31'),
bands=['B02', 'B03', 'B04', 'B08', 'B11', 'B12', 'SCL'],
)Status: Working
Products:
- SOSD (Start of Season Date)
- EOSD (End of Season Date)
- MAXD (Maximum Date)
- MINV (Minimum Value)
- MAXV (Maximum Value)
- AMPL (Amplitude)
- LENGTH (Length of Season)
- LSLOPE (Left Slope)
- RSLOPE (Right Slope)
- SPROD (Seasonal Productivity)
- TPROD (Total Productivity)
- SOSV (Start of Season Value)
- EOSV (End of Season Value)
Status: Working
Products:
- PPI (Plant Phenology Index)
- QFLAG (Quality Flag)
Status: NOT AVAILABLE (404 Error as of January 2025)
Products (no longer accessible):
LAI (Leaf Area Index)FAPAR (Fraction of Absorbed Photosynthetically Active Radiation)NDVI (Normalized Difference Vegetation Index)PPI (now available in VPP_ST)
Status: Working
Products: SL_2_LST___
You can use DEIMS site IDs instead of shapefiles:
downloader = pyvpp.wekeo_download(
dataset='VPP_Pheno',
shape='deimsid:https://deims.org/bcbc866c-3f4f-47a8-bbbc-0a93df6de7b2',
dates=['2020-01-01', '2020-12-31'],
products=['SOSD', 'MAXD']
)PyVPP performs the following operations:
- Downloads all Sentinel-2 tiles that intersect your area of interest
- Filters tiles by UTM zone
- Creates mosaics for each date and product
- Clips mosaics to your exact boundaries
- Saves final products as
mosaic_YYYYMMDD_PRODUCT_rec.tif - Cleans up intermediate files
downloader = pyvpp.wekeo_download(
dataset='VPP_Pheno',
shape='area.shp',
dates=['2020-01-01', '2020-12-31'],
products=['SOSD'],
user='your_username', # Direct credentials
password='your_password'
)If you have an old .hdarc file (pre-March 2024):
import pyvpp
pyvpp.clean_old_hdarc() # Removes obsolete 'url:' line# Execute steps individually
downloader.download() # Only download
downloader.mosaic_and_clip() # Only mosaic and clip
downloader.clean() # Only clean intermediate filesSince VPP_Index is currently unavailable, here are alternatives:
// Calculate NDVI from Sentinel-2
var s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
.filterDate('2020-01-01', '2020-12-31')
.filterBounds(geometry);
var addNDVI = function(image) {
var ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI');
return image.addBands(ndvi);
};- Pre-computed LAI, FAPAR, NDVI available
https://land.copernicus.eu/global/products/
- 300m resolution (not 10m like HR-VPP)
import rasterio
import numpy as np
# NDVI = (NIR - Red) / (NIR + Red)
with rasterio.open('sentinel2.tif') as src:
red = src.read(4) # Band 4
nir = src.read(8) # Band 8
ndvi = (nir - red) / (nir + red)If you get a 404 error with VPP_Index:
requests.exceptions.HTTPError: 404 Client Error: Not Found for url:
https://gateway.prod.wekeo2.eu/hda-broker/api/v1/datasets/EO:EEA:DAT:CLMS_HRVPP_VI
Solution: Use VPP_Pheno or VPP_ST instead (see examples above).
# Recreate your .hdarc file
import pyvpp
pyvpp.create_hdarc("username", "password")This usually means:
- Date range is outside available data
- Area of interest has no coverage
- Product name is misspelled
Check the official documentation for data availability.
- Python >= 3.9
- requests >= 2.28
- geopandas >= 0.12
- rasterio >= 1.3
- pyproj >= 3.4
- shapely >= 1.8
- deims >= 3.1
- fiona >= 1.8.20
- hda >= 2.18 (for WEkEO only)
- HR-VPP Documentation: https://land.copernicus.eu/pan-european/biophysical-parameters/high-resolution-vegetation-phenology-and-productivity
- WEkEO Help Center: https://help.wekeo.eu/
- PyVPP Repository: https://github.com/Digdgeo/PyVPP
- Report Issues: https://github.com/Digdgeo/PyVPP/issues
If you use PyVPP in your research, please cite:
García-Díaz, D. (2025). PyVPP: Python package for HR-VPP data access and processing.
https://github.com/Digdgeo/PyVPP
MIT License - see LICENSE file for details
Contributions are welcome! Please feel free to submit a Pull Request.
- Per-date output: mosaics organized in
YYYYMMDD_s2msi/subfolders, one per acquisition date - Landsat-style naming:
YYYYMMDD_s2msi_<alias>.tif(e.g.20230610_s2msi_b04_red.tif) - Red-edge bands: B05, B06, B07, B8A now fully supported
- Token auto-refresh: prevents
401 Unauthorizedon long download sessions - Resume support: already-extracted SAFE directories are skipped on re-run
- geopandas >= 0.14 required (fixes fiona 1.10+ compatibility)
- Added CDSE (Copernicus Data Space Ecosystem) support for Sentinel-2 L2A/L1C
- New module
pyvpp.cdsewithCDSEDownloadclass - Multi-resolution support (10 m + 20 m + SCL in a single call)
- Per-band output files in native resolution
- Authentication via config file, env vars, or direct credentials
- Fixed
.hdarcformat for HDA API v2.18+ - Added
create_hdarc(),clean_old_hdarc(),delete_hdarc()helpers
Last updated: May 2026
Status: VPP_ST ✅ | VPP_Pheno ✅ | VPP_Index