Getting Started
Install
pip install edown
edown supports Python 3.9 through 3.14.
To include Zarr stacking support:
pip install "edown[stack]"
For development (linting, type checking, tests, and stacking):
pip install -e ".[dev,stack,dask]"
Authenticate
edown needs access to Google Earth Engine. Set up one of:
Option 1 -- Service account (recommended for CI and servers):
export GEE_SERVICE_ACCOUNT="my-sa@my-project.iam.gserviceaccount.com"
export GEE_SERVICE_ACCOUNT_KEY="/path/to/key.json"
Option 2 -- Local credentials (simplest for personal use):
earthengine authenticate
Option 3 -- Application Default Credentials:
gcloud auth application-default login \
--scopes=https://www.googleapis.com/auth/earthengine
edown tries each strategy in order and uses the first one that succeeds.
Your first download
Search and download Sentinel-2 bands B4 (red) and B8 (NIR) over London:
edown download \
--collection-id COPERNICUS/S2_SR_HARMONIZED \
--start-date 2024-06-01 \
--end-date 2024-06-07 \
--bbox -0.15 51.48 0.02 51.56 \
--band B4 --band B8 \
--output-root ./data
This will:
- Query Earth Engine for matching images
- Download each image as a native-grid GeoTIFF under
./data/images/ - Write a run manifest under
./data/manifests/
Build a Zarr stack
Once the download completes, stack alignment-compatible images into a Zarr datacube:
edown stack \
--manifest-path ./data/manifests/run-*.json \
--output-root ./data
The output Zarr stores appear under ./data/stacks/, one per alignment group,
with dimensions (time, band, y, x).
Python API
The same workflow from Python:
from pathlib import Path
from edown import (
AOI,
DownloadConfig,
StackConfig,
download_images,
stack_images,
)
# Download
config = DownloadConfig(
collection_id="COPERNICUS/S2_SR_HARMONIZED",
start_date="2024-06-01",
end_date="2024-06-07",
aoi=AOI.from_bbox((-0.15, 51.48, 0.02, 51.56)),
bands=("B4", "B8"),
output_root=Path("data"),
)
summary = download_images(config)
print(f"{summary.downloaded} images downloaded")
# Stack
stack_config = StackConfig(manifest_path=summary.manifest_path)
results = stack_images(stack_config)
for result in results:
if result.output_path:
print(f"Stack: {result.output_path}")
Using a GeoJSON AOI
Instead of a bounding box, pass a GeoJSON file:
edown download \
--collection-id COPERNICUS/S2_SR_HARMONIZED \
--start-date 2024-06-01 \
--end-date 2024-06-07 \
--geojson my_area.geojson \
--band B4 --band B8 \
--output-root ./data
edown accepts GeoJSON Feature, Geometry, or FeatureCollection files.
For a FeatureCollection, all geometries are merged into a single AOI.
Tuning performance
A few options to control download speed:
| Option | Default | Purpose |
|---|---|---|
--download-workers |
10 | Number of parallel download threads |
--prepare-workers |
10 | Threads for job preparation (CRS transforms) |
--max-inflight-chunks |
32 | Cap on in-flight chunk requests |
--request-byte-limit |
48 MB | Max bytes per chunk request |
--max-retries |
4 | Retries per chunk with exponential backoff |
Live smoke test
Run a real end-to-end test against Earth Engine:
pip install -e ".[dev,stack]"
export EDOWN_RUN_LIVE_TESTS=1
python -m pytest -s tests/test_live_s2.py
Override defaults with environment variables: EDOWN_LIVE_COLLECTION_ID,
EDOWN_LIVE_START_DATE, EDOWN_LIVE_END_DATE, EDOWN_LIVE_BBOX,
EDOWN_LIVE_BANDS.