Skip to main content

Universal satellite data pipeline — unified access to 22+ providers

Project description

PyGeoFetch 🛰️

PyPI version Python Versions License: MIT Tests Coverage

Universal satellite data pipeline + geospatial processing platform — unified access to 22+ satellite repositories, 17 spectral indices, full SAR processing, and chainable YAML pipelines. One CLI, one Python API.


📖 Introduction

PyGeoFetch is a production-ready satellite data acquisition and processing framework that provides unified, authenticated access to 22+ Earth observation repositories — including Sentinel, Landsat, Planet, Maxar, Airbus, Copernicus, USGS, NASA, JAXA, and more — through a single consistent CLI and Python API.

The package abstracts away the authentication complexity, API fragmentation, and format inconsistencies of individual satellite providers, and adds a complete geospatial processing engine on top. PyGeoFetch provides six core capabilities:

  1. Authenticated access to 22+ providers, with secure credential storage via system keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service).
  2. Unified federated search across all providers, returning standardized STAC 1.0 GeoJSON, GeoParquet, or CSV results sortable by cloud cover, date, or relevance score.
  3. Resilient parallel downloads with band selection, checksum verification, resume support, exponential backoff, and atomic writes.
  4. Preprocessing engine — atmospheric correction, cloud masking, reprojection, resampling, pan-sharpening, mosaicking, and compositing.
  5. 17 spectral indices — NDVI, EVI, SAVI, NDWI, MNDWI, NDBI, TCT, PCA, LST, Albedo, dNBR, GLCM texture, and more.
  6. YAML pipeline orchestration with cron scheduling, batch processing, and full execution history — enabling repeatable, automated geospatial workflows.

📝 Statement of Need

Accessing satellite data at scale is surprisingly fragmented. Each provider — USGS, Copernicus, Planet, Maxar, NASA — exposes a different authentication scheme, a different query API, a different download protocol, and a different file format. Researchers and engineers working across multiple providers must maintain a patchwork of custom scripts, scattered credentials, and ad hoc download logic, making workflows difficult to reproduce and brittle to maintain.

Existing tools address parts of this problem: EODAG supports several providers but lacks pipeline orchestration and commercial coverage; pystac-client handles STAC-compliant endpoints only; sentinelsat is Sentinel-specific. No single tool covers the full breadth of providers, processing, and automation needed for operational geospatial workflows.

Feature PyGeoFetch EODAG pystac-client satpy sentinelsat
Providers 22+ 10+ STAC only Limited Sentinel only
Processing Engine ✅ Full Partial
Spectral Indices ✅ 17+
SAR Processing
YAML Pipelines
Auth Management ✅ Keyring Partial
STAC 1.0 Output ✅ Native
Cron Scheduling
Commercial Providers ✅ Planet/Maxar

🛰️ 22+ Satellite Providers

Open access — no login required (10):

Provider ID Satellites Capabilities
planetary_computer Sentinel-1/2, Landsat 8/9, MODIS, NAIP, ALOS DEM STAC, SAR
aws_earth Sentinel-2 COG, Landsat C2, NAIP STAC
element84 Sentinel-2 L2A, Landsat C2, Sentinel-1 RTC, COP-DEM STAC, SAR
noaa_big_data GOES-16/17/18, NEXRAD radar Weather
esa_scihub Sentinel-1/2/3/5P (public mirrors) SAR
jaxa_earth ALOS 30m DSM, PALSAR-2 SAR
isro_bhuvan ResourceSat-2/2A (5.8m), Cartosat-1 (2.5m)
inpe_cbers CBERS-4, CBERS-4A
digitalglobe WorldView open disaster response <1m VHR
geoserver_generic Any OGC WMS/WFS/WCS endpoint Generic

Authenticated providers (12): USGS · Copernicus CDSE · NASA Earthdata · NASA Earthdata Cloud · Alaska SAR Facility · OpenTopography · Planet Labs · Sentinel Hub · Maxar GBDX · Airbus OneAtlas · Google Earth Engine · TerraBotics

🔍 Unified Search

  • Federated query across multiple providers simultaneously with deduplicated results
  • Filter by bbox, geometry file, date range, cloud cover, resolution, processing level, and CQL2 expressions
  • 7 output formats: table · json · stac · geojson · geoparquet · csv · ids

📥 Resilient Downloads

  • Adaptive parallel downloads with configurable concurrency and real-time progress
  • Band selection (e.g. B02,B03,B04 → download 150 MB instead of 600 MB full scene)
  • SHA256 checksum verification, resume support, exponential-backoff retries
  • Atomic writes — no partial files ever written to disk

⚙️ Preprocessing Engine (client.preprocess)

Method Description
atmos() Atmospheric correction: DOS1, DOS2, Sen2Cor, FLAASH, 6S, iCOR
cloud_mask() Cloud masking: SCL, FMask, threshold, NDSI
cloud_fill() Fill cloud gaps from time-series
topo_correct() Topographic correction: cosine, Minnaert, C-correction
clip() Clip to bounding box or GeoJSON polygon
reproject() Reproject to any CRS (EPSG:4326, UTM, etc.)
resample() Change resolution: nearest, bilinear, cubic, lanczos
pansharpen() Pan-sharpening: Brovey, IHS, Gram-Schmidt
tile() Split into overlapping tiles for AI inference
mosaic() Merge scenes: first, last, min, max
composite() Multi-temporal: median, mean, max, best-pixel

📊 Spectral Indices (client.indices)

Index Formula Use Case
ndvi (NIR−Red)/(NIR+Red) Vegetation health
evi G·(NIR−Red)/(NIR+C1·Red−C2·Blue+L) Dense canopy
savi (NIR−Red)/(NIR+Red+L)·(1+L) Sparse vegetation
ndwi (Green−NIR)/(Green+NIR) Water bodies
mndwi (Green−SWIR1)/(Green+SWIR1) Urban water
ndbi (SWIR1−NIR)/(SWIR1+NIR) Built-up areas
ndsi (Green−SWIR1)/(Green+SWIR1) Snow / ice
ndmi (NIR−SWIR1)/(NIR+SWIR1) Canopy moisture
nbr / dnbr (NIR−SWIR2)/(NIR+SWIR2) Burn severity
tct Matrix coefficients Brightness, Greenness, Wetness
pca Eigen decomposition Dimensionality reduction
texture GLCM Contrast, homogeneity, energy
lst Thermal → Kelvin / Celsius Land surface temperature
albedo Narrowband→broadband (Liang 2001) Surface reflectance
band_math Arbitrary expression on B[i] Custom indices

🔧 Post-Processing (client.post)

vectorizesmoothregularizezonal_statsbuffercentroidscompresscog

📡 SAR Processing (client.sar)

Method Description
despeckle() Lee, Enhanced Lee, Frost, Gamma MAP, Boxcar
calibrate() DN → sigma0 / gamma0 / beta0 (dB or linear)
flood_map() Threshold or change-based flood detection
coherence() Interferometric coherence (stable surface / change)

📋 YAML Pipeline Orchestration

  • Define search → filter → download → process → export workflows in YAML
  • Chain any preprocessing, index, or post-processing step
  • Schedule with cron expressions, run history, and retry
  • 6 built-in templates: ndvi · change_detection · flood_map · urban_mapping · sar_analysis · land_cover

🔐 Security by Default

  • Credentials stored in system keyring — never logged or written to disk in plaintext
  • TLS 1.2+ enforced, SSL verification always on, no telemetry, no analytics

📦 Installation

# Core — free providers work immediately, no extras needed
pip install PyGeoFetch

# + Raster/vector processing (rasterio, geopandas, shapely)
pip install "PyGeoFetch[geo]"

# + Cloud provider S3 access
pip install "PyGeoFetch[cloud]"

# + Cron scheduling
pip install "PyGeoFetch[schedule]"

# Everything
pip install "PyGeoFetch[all]"

Requirements: Python 3.9+

Verify your installation:

PyGeoFetch doctor
# ✓ Python 3.11   ✓ httpx   ✓ pydantic   ✓ rich
# ✓ AWS Earth Search: HTTP 200
# ✓ Planetary Computer: HTTP 200
# ✓ Element 84: HTTP 200

⚡ Quick Start

CLI

# Add credentials (free providers need no credentials at all)
PyGeoFetch auth add usgs --username USER --password PASS
PyGeoFetch auth add copernicus --username email@example.com --password PASS
PyGeoFetch auth add planet --api-key YOUR_KEY

# Search (free — no login)
PyGeoFetch search run \
    --bbox "-74.1,40.6,-73.7,40.9" \
    --start-date 2024-01-01 \
    --cloud-cover 0-15 \
    --providers planetary_computer,aws_earth \
    --format table \
    --output results.geojson

# Download with band selection
PyGeoFetch download run \
    --from-search results.geojson \
    --output ./data/ \
    --parallel 4 \
    --bands "B02,B03,B04" \
    --max-items 3

# Download with full post-processing chain
PyGeoFetch download run \
    --from-search results.geojson \
    --output ./data/ \
    --parallel 4 \
    --verify-checksum \
    --post-process "unzip,reproject:EPSG:4326,compress:lzw,cog"

Python API

from pathlib import Path
from pygeofetch import PyGeoFetch
from pygeofetch.models.search_query import SearchQuery, BoundingBox
from pygeofetch.models.download_task import DownloadOptions

client = PyGeoFetch()

# Credentials
client.add_credentials("usgs",       username="user", password="pass")
client.add_credentials("copernicus", username="email@example.com", password="pass")
client.add_credentials("planet",     api_key="PL_KEY")

# Search
results = client.search(
    SearchQuery(
        bbox=BoundingBox.from_string("-74.1,40.6,-73.7,40.9"),
        start_date="2024-01-01",
        end_date="2024-06-01",
        cloud_cover_max=20,
        sort_by="cloud_cover",
        sort_ascending=True,
    ),
    providers=["usgs", "copernicus", "planetary_computer", "aws_earth"],
)

# Download
downloads = client.download(
    results[:5],
    destination=Path("./data/"),
    options=DownloadOptions(
        parallel=4,
        verify_checksum=True,
        resume=True,
        bands=["B02", "B03", "B04"],
    ),
)

for dr in downloads:
    if dr.success:
        print(f"✓ {dr.data_id} ({dr.bytes_downloaded // 1024 // 1024:.1f} MB)")
    else:
        print(f"✗ {dr.data_id}: {dr.error}")

# Process
ndvi   = client.indices.ndvi(red="B04.tif", nir="B08.tif")
clipped = client.preprocess.clip("scene.tif", bbox=(-74.1, 40.6, -73.7, 40.9))
cog     = client.post.cog("ndvi.tif", compress="deflate")

# End-to-end pipeline
result = (
    client.pipeline("sentinel2-ndvi")
    .atmos(method="dos1")
    .cloud_mask(method="scl", scl_band="SCL.tif")
    .clip(bbox=(-74.1, 40.6, -73.7, 40.9))
    .ndvi(red="B04.tif", nir="B08.tif")
    .vectorize(threshold=0.3)
    .cog(compress="deflate")
    .run(input="scene.tif", output_dir="./processed/")
)
print(f"Pipeline: {result.success} in {result.duration_seconds:.1f}s")

YAML Pipeline

name: weekly-sentinel2-ndvi
schedule: "0 6 * * 1"   # Every Monday 06:00 UTC
description: Weekly NDVI monitoring — search, download, process, export

steps:
  - search:
      providers: [copernicus, aws_earth, planetary_computer]
      bbox: "-74.1,40.6,-73.7,40.9"
      date_range: last_7_days
      cloud_cover: "0-10"
      max_results: 20

  - filter:
      expression: "data.cloud_cover < 5"

  - download:
      parallel: 4
      output: ./raw/
      verify_checksum: true
      bands: [B04, B08]

  - ndvi:
      red: B04.tif
      nir: B08.tif

  - vectorize:
      threshold: 0.3
      format: geojson

  - cog:
      compress: deflate
# Validate without running
PyGeoFetch proc-pipeline validate weekly-sentinel2.yaml

# Run once
PyGeoFetch proc-pipeline run weekly-sentinel2.yaml --input scene.tif

# Schedule (recurring)
PyGeoFetch pipeline schedule weekly-sentinel2.yaml --name "ndvi-weekly"

# Generate a starter template
PyGeoFetch proc-pipeline template ndvi
PyGeoFetch proc-pipeline template flood_map
PyGeoFetch proc-pipeline template change_detection

🖥️ Complete CLI Reference

SYSTEM
  PyGeoFetch doctor                     diagnose installation + connectivity
  PyGeoFetch status [--json]            provider and cache overview
  PyGeoFetch version

AUTH
  PyGeoFetch auth add PROVIDER [--username U] [--password P] [--api-key K]
  PyGeoFetch auth login PROVIDER        interactive prompt
  PyGeoFetch auth list [--json]
  PyGeoFetch auth test PROVIDER
  PyGeoFetch auth remove PROVIDER [--yes]
  PyGeoFetch auth export [--output FILE]

PROVIDERS
  PyGeoFetch providers list [--auth|--no-auth] [--capabilities sar] [--json]
  PyGeoFetch providers info PROVIDER
  PyGeoFetch providers search "TERM"

SEARCH
  PyGeoFetch search run \
    --bbox "minlon,minlat,maxlon,maxlat"   or  --geometry-file area.geojson
    --start-date YYYY-MM-DD  --end-date YYYY-MM-DD
    --cloud-cover 0-20
    --providers aws_earth,copernicus
    --satellites Sentinel-2
    --sort-by cloud_cover  --sort-order asc
    --max-results 50
    --cql2 "eo:cloud_cover < 5"
    --format table|json|stac|geojson|geoparquet|csv|ids
    --output results.geojson
    --no-cache  --timeout 60

DOWNLOAD
  PyGeoFetch download run \
    --from-search results.geojson
    --output ./data/
    --parallel 4  --retry 5
    --bands "B02,B03,B04"
    --verify-checksum  --resume
    --bandwidth-limit 10MB
    --post-process "reproject:EPSG:4326,compress:lzw,cog"
    --on-failure skip
    --max-items 10
    --notify webhook:https://hooks.slack.com/YOUR/WEBHOOK
    --json

PREPROCESSING
  PyGeoFetch preprocess atmos         scene.tif --method dos1|sen2cor|flaash|6s
  PyGeoFetch preprocess cloud-mask    scene.tif --method scl|fmask|threshold
  PyGeoFetch preprocess cloud-fill    cloudy.tif t1.tif t2.tif
  PyGeoFetch preprocess topo-correct  scene.tif dem.tif --method cosine
  PyGeoFetch preprocess clip          scene.tif --bbox "..." | --geometry file.geojson
  PyGeoFetch preprocess reproject     scene.tif --crs EPSG:4326
  PyGeoFetch preprocess resample      scene.tif --resolution 30
  PyGeoFetch preprocess pansharpen    pan.tif ms.tif --method brovey
  PyGeoFetch preprocess mosaic        s1.tif s2.tif --method first|last|min|max
  PyGeoFetch preprocess composite     *.tif --method median|mean|max|best_pixel
  PyGeoFetch preprocess tile          scene.tif --tile-size 512 --overlap 64

SPECTRAL INDICES
  PyGeoFetch index ndvi    --red B04.tif --nir B08.tif
  PyGeoFetch index evi     --blue B02.tif --red B04.tif --nir B08.tif
  PyGeoFetch index savi    --red B04.tif --nir B08.tif --soil-l 0.5
  PyGeoFetch index ndwi    --green B03.tif --nir B08.tif
  PyGeoFetch index mndwi   --green B03.tif --swir1 B11.tif
  PyGeoFetch index ndbi    --nir B08.tif --swir1 B11.tif
  PyGeoFetch index ndsi    --green B03.tif --swir1 B11.tif
  PyGeoFetch index ndmi    --nir B08.tif --swir1 B11.tif
  PyGeoFetch index nbr     --nir B08.tif --swir2 B12.tif
  PyGeoFetch index dnbr    --pre-nir B08.tif --pre-swir2 B12.tif \
                            --post-nir B08_post.tif --post-swir2 B12_post.tif
  PyGeoFetch index tct     --blue B02.tif --green B03.tif --red B04.tif \
                            --nir B08.tif --swir1 B11.tif --swir2 B12.tif
  PyGeoFetch index pca     B02.tif B03.tif B04.tif B08.tif --components 3
  PyGeoFetch index texture  B08.tif --window 7 --features contrast,homogeneity
  PyGeoFetch index lst     B10.tif --emissivity 0.97 --sensor landsat8
  PyGeoFetch index albedo  B02.tif B03.tif B04.tif B08.tif B11.tif B12.tif
  PyGeoFetch index band-math B04.tif B08.tif --expr "(B[1]-B[0])/(B[1]+B[0]+1e-6)"
  PyGeoFetch index stack   B02.tif B03.tif B04.tif

POST-PROCESSING
  PyGeoFetch post vectorize       ndvi.tif --threshold 0.3 --format geojson
  PyGeoFetch post smooth          polygons.geojson --tolerance 0.5
  PyGeoFetch post regularize      buildings.geojson
  PyGeoFetch post zonal-stats     ndvi.tif parcels.geojson --output stats.csv
  PyGeoFetch post buffer          roads.geojson --distance 15
  PyGeoFetch post centroids       polygons.geojson
  PyGeoFetch post geometry-metrics polygons.geojson
  PyGeoFetch post compress        scene.tif --method lzw|deflate|zstd
  PyGeoFetch post cog             scene.tif --compress deflate --blocksize 512

SAR PROCESSING
  PyGeoFetch sar despeckle  sar.tif --filter lee|enhanced_lee|frost|gamma --window 7
  PyGeoFetch sar calibrate  sar.tif --output-type sigma0|gamma0|beta0 --db
  PyGeoFetch sar flood-map  post.tif --threshold -15 [--reference pre.tif]
  PyGeoFetch sar coherence  slc1.tif slc2.tif --window 7

PROCESSING PIPELINES
  PyGeoFetch proc-pipeline template ndvi|change_detection|flood_map|urban_mapping|...
  PyGeoFetch proc-pipeline validate FILE
  PyGeoFetch proc-pipeline run FILE [--input scene.tif] [--output-dir ./out/]

DATA PIPELINES (search + download)
  PyGeoFetch pipeline run|validate|schedule|list-scheduled|unschedule|history

CACHE
  PyGeoFetch cache stats|clear|ttl [show|set N]|location|prune --max-size 1GB

CONFIG
  PyGeoFetch config show|get KEY|set KEY VALUE|path|reset

COMPLETION
  PyGeoFetch --install-completion bash|zsh|fish

🗂️ Project Structure

pygeofetch/
├── pygeofetch/
│   ├── core/                engine, authenticator, searcher, downloader, scheduler, cache
│   ├── cli/                 11 CLI command modules
│   ├── processing/          ← geospatial processing engine
│   │   ├── preprocessor.py  atmospheric, cloud, geometric, resampling, compositing
│   │   ├── indices.py       17 spectral indices + transformations
│   │   ├── postprocessor.py vectorize, smooth, zonal stats, COG, compress
│   │   ├── sar.py           despeckle, calibrate, flood map, coherence
│   │   ├── pipeline.py      chainable builder + YAML loader + 6 templates
│   │   └── batch.py         parallel batch processing
│   ├── models/              Pydantic models (search, download, auth, satellite)
│   ├── providers/           22 provider implementations
│   ├── utils/               logging, retry, geo, file, validators
│   └── config/              settings, defaults.yaml
├── notebooks/               9 Jupyter notebooks (01–09)
├── tests/                   60 unit + integration tests
├── docs/assets/
├── pyproject.toml
├── Dockerfile · Makefile · .gitignore
└── .github/workflows/tests.yml

📚 Notebooks

Notebook Topics
01_getting_started.ipynb Install, doctor, first search, first download
02_authentication_and_providers.ipynb All 22 providers, credentials, capability filters
03_advanced_search.ipynb Federated search, CQL2 filters, 7 output formats, caching
04_download_and_postprocessing.ipynb Band selection, parallel downloads, post-processing
05_pipelines_and_scheduling.ipynb YAML pipelines, scheduling, Python builder API
06_real_world_workflows.ipynb NDVI time series, change detection, multi-sensor fusion
07_copernicus_and_authenticated_providers.ipynb Copernicus, USGS, NASA, Planet, ASF, OpenTopography
08_cli_complete_reference.ipynb Every CLI command with runnable examples
09_processing_complete.ipynb Full processing engine: preprocessing, indices, SAR, pipelines
cd notebooks/
jupyter lab

📋 Documentation

Full documentation: https://appiahkubis14.github.io/pygeofetch-docs/

Covers: CLI reference · provider auth guides · pipeline configuration · post-processing catalogue · contributing guide.


🤝 Contributing

Contributions of all kinds are welcome. See CONTRIBUTING.md for full guidelines.

Good first issues include implementing stub providers to full API integrations, improving test coverage, and adding new post-processing actions.

git clone https://github.com/appiahkubis14/PyGeoFetch
cd PyGeoFetch
pip install -e ".[dev,all]"
pytest tests/unit/ -v

📄 License

PyGeoFetch is free and open source software, licensed under the MIT License.

© 2025 PyGeoFetch Contributors. Part of the PyGeoVision platform — PyGeoFetch (data + processing) + GeoAI (AI) = complete Earth observation pipeline.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pygeofetch-1.0.8.tar.gz (179.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pygeofetch-1.0.8-py3-none-any.whl (225.3 kB view details)

Uploaded Python 3

File details

Details for the file pygeofetch-1.0.8.tar.gz.

File metadata

  • Download URL: pygeofetch-1.0.8.tar.gz
  • Upload date:
  • Size: 179.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for pygeofetch-1.0.8.tar.gz
Algorithm Hash digest
SHA256 055d0793d0d04d1cb62367699058bc8f88f38cd309ddaecf53fddbc52f5857a0
MD5 dc57509546ecb466db63e47820984722
BLAKE2b-256 5780e4841ca2ecc7c047e47b131878c74b236716d7fdf4ab9bd87b66674d7d7d

See more details on using hashes here.

File details

Details for the file pygeofetch-1.0.8-py3-none-any.whl.

File metadata

  • Download URL: pygeofetch-1.0.8-py3-none-any.whl
  • Upload date:
  • Size: 225.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for pygeofetch-1.0.8-py3-none-any.whl
Algorithm Hash digest
SHA256 9fef4b9f0ab6aefebc76962d8f5554e2cea3ba0d0df81dfed0993cca9b5767ff
MD5 59a7081e8ca5bfab28ef781292a8b53a
BLAKE2b-256 de2eb08f644890a361d231cbfeea79fcd30818f78a9fa908dec3503e5c70bd38

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page