pygeofetch Documentation
Universal satellite data pipeline — unified access to 22+ providers. Handles auth, federated search, parallel downloads, caching, band selection, and post-processing.
Up and running in 3 minutes
pygeofetch works immediately with 10 free providers — no credentials needed. Free data includes Sentinel-2, Landsat, NAIP, GOES weather, and more.
Interactive demo — try commands
Select a command from the dropdown and click Run to see the expected output:
Managing Provider Credentials
Credentials are stored in your system keyring — never in plain-text files. Supports username/password, API keys, and OAuth2 client credentials.
# Username / password (USGS, NASA, Copernicus) pygeofetch auth add usgs --username YOUR_USER --password YOUR_PASS pygeofetch auth add copernicus --username email@example.com --password PASS pygeofetch auth add nasa_earthdata --username USER --password PASS # API key (Planet, OpenTopography, TerraBotics, Airbus) pygeofetch auth add planet --api-key YOUR_API_KEY pygeofetch auth add opentopography --api-key YOUR_KEY # OAuth2 client credentials (Sentinel Hub) pygeofetch auth add sentinel_hub --client-id YOUR_ID --client-secret YOUR_SECRET # Interactive login — prompts for all fields pygeofetch auth login copernicus # List, test, remove pygeofetch auth list pygeofetch auth test usgs pygeofetch auth remove planet --yes # Export backup (WARNING: contains secrets — store securely) pygeofetch auth export --output creds_backup.json
Environment variables
# Format: pygeofetch_{PROVIDER}_{FIELD} export pygeofetch_USGS_USERNAME=myuser export pygeofetch_USGS_PASSWORD=mypass export pygeofetch_PLANET_API_KEY=PL-abc123 export pygeofetch_COPERNICUS_USERNAME=email@example.com export pygeofetch_COPERNICUS_PASSWORD=pass export pygeofetch_NASA_EARTHDATA_USERNAME=user export pygeofetch_OPENTOPOGRAPHY_API_KEY=mykey export pygeofetch_SENTINEL_HUB_CLIENT_ID=id export pygeofetch_SENTINEL_HUB_CLIENT_SECRET=secret # Global settings export pygeofetch_LOG_LEVEL=DEBUG export pygeofetch_DOWNLOAD__PARALLEL=8 export pygeofetch_CACHE__TTL_SECONDS=7200
PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring and use environment variables instead.Provider auth types
| Provider | Auth Type | Free? | Register At |
|---|---|---|---|
usgs | Username / Password | ✓ Free | ers.cr.usgs.gov |
copernicus | Username / Password (OAuth2) | ✓ Free | dataspace.copernicus.eu |
nasa_earthdata | Username / Password | ✓ Free | urs.earthdata.nasa.gov |
nasa_earthdata_cloud | Username / Password + S3 creds | ✓ Free | urs.earthdata.nasa.gov |
planet | API Key | Subscription | planet.com/account |
sentinel_hub | OAuth2 client credentials | Freemium | apps.sentinel-hub.com |
opentopography | API Key | ✓ Free tier | portal.opentopography.org |
maxar_gbdx | API Token | Subscription | developers.maxar.com |
airbus_oneatlas | API Key | Subscription | oneatlas.airbus.com |
alaska_satellite_facility | Earthdata (same as NASA) | ✓ Free | urs.earthdata.nasa.gov |
google_earth_engine | Service Account JSON | Free tier | console.cloud.google.com |
terrabotics | API Key | Subscription | terrabotics.earth |
Searching Satellite Data
Federated search across multiple providers simultaneously. Results are deduplicated, scored by cloud cover and recency, and returned in STAC 1.0 format.
# Free providers — works immediately, no credentials pygeofetch search run \ --bbox "-74.1,40.6,-73.7,40.9" \ --start-date 2024-01-01 --end-date 2024-03-01 \ --cloud-cover 0-10 \ --providers aws_earth,planetary_computer,element84 \ --format table # Save to GeoJSON for download, open in QGIS, or share pygeofetch search run \ --bbox "-74.1,40.6,-73.7,40.9" \ --cloud-cover 0-5 \ --providers aws_earth \ --output results.geojson # Specific satellite, sorted by cloud cover ascending pygeofetch search run \ --bbox "-10,35,10,55" \ --start-date 2024-06-01 \ --providers copernicus \ --satellites Sentinel-2 \ --cloud-cover 0-15 \ --sort-by cloud_cover --sort-order asc \ --max-results 50 # CQL2 advanced filter (Planetary Computer, Element84) pygeofetch search run \ --bbox "-74.1,40.6,-73.7,40.9" \ --providers planetary_computer \ --cql2 "eo:cloud_cover < 5 AND platform = 'sentinel-2b'" # Search using a GeoJSON geometry file pygeofetch search run \ --geometry-file my_area.geojson \ --cloud-cover 0-10 \ --providers aws_earth # CSV output — pipe to spreadsheet or analytics tools pygeofetch search run \ --bbox "-74.1,40.6,-73.7,40.9" \ --providers aws_earth \ --format csv --output results.csv
All search flags
"minlon,minlat,maxlon,maxlat". Longitude first. Alternative to --geometry-file.YYYY-MM-DD.min-max in percent. E.g. 0-20.min-max. E.g. 10-30.aws_earth,copernicus,usgs.Sentinel-2,Landsat-8.L2A, L2SP.datetime, cloud_cover, score, satellite.asc or desc.skip, abort, retry.Output formats
CQL2 filter examples
# Cloud filter --cql2 "eo:cloud_cover < 10" # Platform filter --cql2 "platform = 'sentinel-2b'" # Combined AND filter --cql2 "eo:cloud_cover < 5 AND platform = 'sentinel-2b'" # Processing level --cql2 "s2:processing_level = 'L2A'" # Landsat tier --cql2 "landsat:collection_category = 'T1'"
Downloading Satellite Data
Parallel, resumable downloads with real-time progress, retry logic, band selection, and a post-processing chain. Progress bar updates per-scene as each completes.
# Basic — download 3 scenes from search results pygeofetch download run \ --from-search results.geojson \ --output ./data/ \ --parallel 2 \ --max-items 3 # RGB bands only — ~150 MB vs 600 MB for full Sentinel-2 scene pygeofetch download run \ --from-search results.geojson \ --output ./data/ \ --bands "B02,B03,B04" \ --max-items 5 # Full options — checksum, resume, bandwidth throttle, Slack notify pygeofetch download run \ --from-search results.geojson \ --output ./data/ \ --parallel 4 \ --retry 5 \ --verify-checksum \ --resume \ --bandwidth-limit 10MB \ --priority high \ --on-failure skip \ --notify webhook:https://hooks.slack.com/services/YOUR/WEBHOOK # Post-processing chain pygeofetch download run \ --from-search results.geojson \ --output ./processed/ \ --post-process "unzip,reproject:EPSG:4326,compress:lzw,cog" # NDVI workflow — download Red + NIR, compute NDVI, export COG pygeofetch download run \ --from-search results.geojson \ --bands "B04,B08" \ --post-process "reproject:EPSG:4326,ndvi,cog" \ --output ./ndvi/
All download flags
search run --output. Required.10MB, 500KB. 0 = unlimited.high, normal, low.B02,B03,B04. Default: all data assets."unzip,reproject:EPSG:4326,cog".skip, abort, retry.webhook:URL or email:ADDRESS. Repeatable for multiple targets.Band selection for Sentinel-2
| Bands | Purpose | Resolution | Approx Size/Scene |
|---|---|---|---|
B02,B03,B04 | RGB (Blue, Green, Red) | 10m | ~150 MB |
visual | True colour composite (TCI pre-rendered) | 10m | ~200 MB |
B04,B08 | NDVI (Red + NIR) | 10m | ~100 MB |
B02,B03,B04,B08 | RGB + NIR (4-band) | 10m | ~200 MB |
B11,B12 | SWIR (fire, burn scar, soil moisture) | 20m | ~50 MB |
SCL | Scene Classification Layer (cloud mask) | 20m | ~20 MB |
| (omit --bands) | All data bands (full scene) | 10/20/60m | ~600 MB |
Post-processing actions
| Action | Syntax | Description | Requires |
|---|---|---|---|
unzip | unzip | Extract ZIP/TAR archives | — |
reproject | reproject:EPSG:4326 | Reproject to target CRS | rasterio |
compress | compress:lzw | GeoTIFF compression (lzw, deflate, zstd) | rasterio |
cog | cog | Convert to Cloud Optimized GeoTIFF | rasterio |
clip | clip:file.geojson | Clip raster to polygon boundary | rasterio |
resample | resample:30 | Resample to target resolution (metres) | rasterio |
ndvi | ndvi | Calculate NDVI from Red and NIR bands | rasterio |
ndwi | ndwi | Calculate NDWI water index | rasterio |
atmospheric | atmospheric:sen2cor | Atmospheric correction | sen2cor |
pan-sharpen | pan-sharpen | Pan-sharpen multispectral with panchromatic | rasterio |
merge | merge | Mosaic overlapping scenes | rasterio |
22 Satellite Data Providers
Filter by capability. 10 providers require no authentication and work immediately.
YAML Pipeline Orchestration
Define recurring satellite data workflows in a single YAML file. Schedule on cron, run ad-hoc, validate before committing, and watch live logs.
Full pipeline YAML example
# weekly-sentinel2.yaml name: weekly-sentinel2-ndvi schedule: "0 6 * * 1" # Every Monday at 06:00 UTC description: Weekly Sentinel-2 acquisition for NDVI monitoring steps: - search: providers: [copernicus, aws_earth, planetary_computer] date_range: last_7_days cloud_cover: 0-10 bbox: "-74.1,40.6,-73.7,40.9" max_results: 20 sort_by: cloud_cover - filter: expression: "data.cloud_cover < 5" max_items: 5 - download: parallel: 4 output: ./raw/ verify_checksum: true bands: "B04,B08" # NDVI bands only on_failure: skip - post_process: actions: "reproject:EPSG:4326,ndvi,cog" - export: format: cloud_optimized_geotiff destination: s3://my-bucket/ndvi/ notify: - webhook: https://hooks.slack.com/services/YOUR/WEBHOOK - email: ops@example.com
Pipeline CLI commands
# Run immediately (one-shot) pygeofetch pipeline run weekly-sentinel2.yaml # Validate YAML without executing pygeofetch pipeline validate weekly-sentinel2.yaml # Schedule for recurring execution pygeofetch pipeline schedule weekly-sentinel2.yaml --name ndvi-monitor # List all scheduled pipelines pygeofetch pipeline list-scheduled # Watch logs live pygeofetch pipeline logs ndvi-monitor --follow # View run history pygeofetch pipeline history --limit 20 # Retry a failed run pygeofetch pipeline retry RUN_ID_HERE # Stop scheduling pygeofetch pipeline unschedule ndvi-monitor # Run a specific step only pygeofetch pipeline run weekly-sentinel2.yaml --step download
pipeline schedule uses the system cron daemon on Linux/macOS, and Windows Task Scheduler on Windows. Run pygeofetch pipeline list-scheduled to confirm registration.Python API Reference
Use pygeofetch as a library in your own scripts, notebooks, or applications. The Python API gives you full programmatic control over search, download, and post-processing.
from pathlib import Path from pygeofetch import pygeofetch from pygeofetch.models import SearchQuery, DownloadOptions # Initialize client client = pygeofetch() # Add credentials (or use env vars) client.add_credentials("usgs", username="user", password="pass") client.add_credentials("planet", api_key="PL_KEY") # Search across multiple providers results = client.search( SearchQuery( bbox=(-74.1, 40.6, -73.7, 40.9), start_date="2024-01-01", end_date="2024-06-01", cloud_cover_max=20, max_results=50, sort_by="cloud_cover", ), providers=["usgs", "copernicus", "planetary_computer", "aws_earth"], ) print(f"Found {len(results)} scenes") for r in results[:3]: print(f" {r.id} | {r.datetime} | {r.cloud_cover:.1f}% cloud") # Download top 5 results download_results = client.download( results[:5], destination=Path("./data/"), options=DownloadOptions( parallel=4, verify_checksum=True, resume=True, bands=["B02", "B03", "B04"], post_process=["reproject:EPSG:4326", "cog"], ), ) for dr in download_results: if dr.success: print(f" ✓ {dr.data_id} ({dr.bytes_downloaded // 1024 // 1024:.1f} MB)") else: print(f" ✗ {dr.data_id}: {dr.error}")
SearchQuery parameters
["Sentinel-2", "Landsat-8"]."L2A"."datetime", "cloud_cover", "score", "satellite". Default: "datetime"."asc" or "desc". Default: "desc".DownloadOptions parameters
["B02", "B03", "B04"]. Default: all assets.["reproject:EPSG:4326", "cog"]."10MB", "500KB". None = unlimited."skip", "abort", or "retry". Default: "skip".pygeofetch class methods
Full CLI Reference
Complete listing of all commands, subcommands, and global options.
Global options
pygeofetch [OPTIONS] COMMAND [ARGS] Options: --log-level TEXT Log level: DEBUG, INFO, WARNING, ERROR [default: INFO] --log-file TEXT Write logs to file path --log-format TEXT console or json [default: console] --config FILE Path to config file [default: ~/.pygeofetch/config.yaml] --version Show version and exit --help Show help message and exit --install-completion Install shell completion (bash/zsh/fish)
All command groups
| Group | Subcommands | Description |
|---|---|---|
auth | add, login, list, test, remove, export | Manage provider credentials |
providers | list, info, search | Browse and inspect providers |
search | run, demo | Search for satellite scenes |
download | run, demo | Download scenes to disk |
cache | stats, clear, ttl, location, prune | Manage search result cache |
pipeline | run, validate, schedule, list-scheduled, unschedule, logs, history, retry | Pipeline orchestration |
config | show, get, set, path, reset | Read and modify configuration |
status | — | System status dashboard |
doctor | — | Diagnose installation and connectivity |
version | — | Show version info |
Cache commands
pygeofetch cache stats [--json] pygeofetch cache clear [--provider PROVIDER] [--older-than 7d] [--dry-run] pygeofetch cache ttl show pygeofetch cache ttl set 7200 pygeofetch cache location pygeofetch cache prune --max-size 1GB
Providers commands
# List all providers pygeofetch providers list # Filter by auth, capability, or satellite pygeofetch providers list --no-auth pygeofetch providers list --capabilities sar pygeofetch providers list --satellite Landsat # Detailed info for one provider pygeofetch providers info planetary_computer # Fuzzy search across provider names and descriptions pygeofetch providers search "landsat"
Shell completion
# Bash pygeofetch --install-completion bash echo 'source ~/.pygeofetch-complete.bash' >> ~/.bashrc # Zsh pygeofetch --install-completion zsh echo 'source ~/.pygeofetch-complete.zsh' >> ~/.zshrc # Fish pygeofetch --install-completion fish
Configuration Reference
pygeofetch uses a layered config system. Settings are merged in order of precedence from lowest to highest.
pygeofetch_* env vars. Override file config.Full configuration file
download: parallel: 4 retry_attempts: 5 retry_delay_seconds: 1.0 retry_max_delay_seconds: 60.0 retry_jitter: true verify_checksum: false checksum_algorithm: sha256 # md5, sha256, sha512 chunk_size_mb: 10 resume: true bandwidth_limit_mbps: null # null = unlimited overwrite_existing: false notify_on_completion: null # webhook:URL or email:ADDRESS notify_on_failure: null on_failure: skip # skip, abort, retry cache: enabled: true ttl_seconds: 3600 max_size_gb: 10 location: ~/.pygeofetch/cache search: default_providers: [] max_results: 100 timeout_seconds: 60 on_provider_failure: skip sort_by: datetime sort_order: desc auth: storage_backend: keyring # keyring or file keyring_service: pygeofetch file_path: ~/.pygeofetch/credentials.enc proxy: http_proxy: null https_proxy: null no_proxy: [] logging: level: INFO format: console # console, json file: null max_file_size_mb: 10 backup_count: 3 providers: planetary_computer: endpoint: https://planetarycomputer.microsoft.com/api/stac/v1 timeout: 60 element84: endpoint: https://earth-search.aws.element84.com/v1 timeout: 60 copernicus: endpoint: https://catalogue.dataspace.copernicus.eu/resto/api/ timeout: 45 planet: endpoint: https://api.planet.com/data/v1/ rate_limit: 100 usgs: endpoint: https://m2m.cr.usgs.gov/api/api/json/stable/ timeout: 60
Config CLI commands
# Show the merged effective configuration pygeofetch config show # Get a specific key pygeofetch config get download.parallel # Set a value pygeofetch config set download.parallel 8 pygeofetch config set cache.ttl_seconds 7200 pygeofetch config set search.default_providers "aws_earth,planetary_computer" # Show config file path pygeofetch config path # Reset to defaults pygeofetch config reset
Security Model
pygeofetch is designed with credential safety, network security, and data integrity as first-class concerns.
- Credentials never written to disk in plain text
- System keyring storage: macOS Keychain, Windows Credential Manager, Linux Secret Service
- Encrypted file fallback (
~/.pygeofetch/credentials.enc) using Fernet AES-128-CBC - All log filters redact passwords, tokens, and API keys
- Credentials cleared from memory immediately after use
- Environment variable support for CI/CD and Docker
- TLS 1.2+ enforced on all outbound connections
- SSL certificate verification always on — no
verify=Falsein codebase - Certificate pinning available for enterprise deployments
- HTTP proxy support via
HTTP_PROXY/HTTPS_PROXY - Connection timeouts enforced per provider
- SHA256 checksum verification on all downloads (configurable: MD5, SHA256, SHA512)
- Atomic file writes — partial downloads never corrupt existing data
- Download resume tokens prevent data duplication
- Temp files cleaned up on failure or interruption
- No telemetry — pygeofetch does not phone home
- No analytics — zero usage data collection
- No third-party requests beyond configured providers
- All data stays local unless you configure export/webhook
Error Handling & Resilience
pygeofetch handles failures at every layer — provider outages, network interruptions, checksum mismatches, and partial failures are all managed gracefully.
Provider failures
# Skip failing providers — return partial results from others pygeofetch search run --providers copernicus,usgs,planet \ --on-provider-failure skip # Abort entirely if any provider fails pygeofetch search run --providers copernicus,usgs \ --on-provider-failure abort # Auto-retry failing providers (up to 3 attempts) pygeofetch search run --providers copernicus \ --on-provider-failure retry
Common errors and fixes
auth add or set the appropriate env var.--timeout or check provider status page.[geo] extra or verify rasterio installation.Download resilience internals
.tmp then renamed atomically on completion. Partial files never corrupt existing data. Temp files cleaned up on failure.Docker & Containers
pygeofetch ships an official Docker image for reproducible environments, CI/CD pipelines, and scheduled pipeline execution.
Quick start
docker pull pygeofetch/pygeofetch:latest # Search — mount credentials and data output docker run \ -v ~/.pygeofetch:/root/.pygeofetch \ -v $(pwd)/data:/data \ pygeofetch/pygeofetch search run \ --bbox "-74.1,40.6,-73.7,40.9" \ --providers aws_earth \ --output /data/results.geojson # Download from saved results docker run \ -v ~/.pygeofetch:/root/.pygeofetch \ -v $(pwd)/data:/data \ pygeofetch/pygeofetch download run \ --from-search /data/results.geojson \ --output /data/scenes/ \ --parallel 4
Docker Compose for scheduled pipelines
version: '3.8'
services:
pygeofetch-scheduler:
image: pygeofetch/pygeofetch:latest
volumes:
- ~/.pygeofetch:/root/.pygeofetch
- ./pipelines:/pipelines
- ./data:/data
command: pygeofetch pipeline run /pipelines/weekly-ndvi.yaml
restart: unless-stopped
environment:
- pygeofetch_LOG_LEVEL=INFO
- pygeofetch_DOWNLOAD__PARALLEL=4
- PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
# Credentials via env vars for headless Docker
- pygeofetch_PLANET_API_KEY=${PLANET_API_KEY}
- pygeofetch_COPERNICUS_USERNAME=${COPERNICUS_USER}
- pygeofetch_COPERNICUS_PASSWORD=${COPERNICUS_PASS}
Build locally
git clone https://github.com/appiahkubis14/pygeofetch cd pygeofetch docker build -t pygeofetch:local . docker run pygeofetch:local doctor
pygeofetch/pygeofetch) and GitHub Container Registry (ghcr.io/appiahkubis14/pygeofetch). Tags: latest, 1.0.0, slim (no rasterio).Testing
pygeofetch ships with 60 tests covering unit, integration, property-based, and CLI end-to-end scenarios.
# Install dev dependencies pip install -e ".[dev,all]" # Run all tests pytest tests/ -v # With coverage report pytest tests/ -v --cov=pygeofetch --cov-report=html open htmlcov/index.html # Unit tests only (fast, no network) pytest tests/unit/ -v # Integration tests (requires real credentials) pytest tests/integration/ -v --run-integration # Run a specific test file pytest tests/unit/test_search.py -v # With hypothesis property-based testing pytest tests/property/ -v --hypothesis-seed=12345
Testing strategy
responses and httpx mocks. No network required.pytest-vcr for deterministic replay. Cassettes checked into the repo — CI never hits real APIs.hypothesis. Covers bbox validation, date parsing, band selection, and config merging.CliRunner. Search → save → download → post-process pipelines tested end-to-end without spawning subprocesses.--run-integration. Require credentials. Run in CI with secret injection from GitHub Actions.Contributing tests
tests/ ├── unit/ │ ├── test_search.py # SearchQuery, provider adapters │ ├── test_download.py # DownloadOptions, resume, checksum │ ├── test_auth.py # Keyring, env vars, credential storage │ ├── test_pipeline.py # YAML parsing, step execution │ ├── test_postprocess.py # Processing chain actions │ └── test_config.py # Layered config merging ├── integration/ │ ├── test_aws_earth.py # Live AWS Earth Open Data │ ├── test_planetary.py # Live Planetary Computer │ └── conftest.py ├── property/ │ └── test_models.py # hypothesis tests ├── cli/ │ └── test_cli_workflow.py # CliRunner end-to-end └── cassettes/ # VCR HTTP recordings
Roadmap
Planned features by version. Vote on priorities at github.com/appiahkubis14/pygeofetch/discussions.
- 22 provider integrations
- YAML pipeline orchestration
- Keyring credential management
- 7 output formats including GeoParquet
- Post-processing chain (NDVI, COG, reproject)
- 60 test suite with CI
- Docker image
- BlackSky provider
- SI Imaging Services (KOMPSAT)
- Interactive search mode (--interactive)
- Slack, Discord, Teams webhook templates
- Streaming COG partial reads
- Web dashboard for pipeline monitoring
- REST API server mode (pygeofetch serve)
- Automatic provider health monitoring
- Bandwidth scheduling by time of day
Why pygeofetch vs alternatives?
| Feature | pygeofetch | EODAG | pystac-client | satpy | sentinelsat |
|---|---|---|---|---|---|
| Providers | 22+ | 10+ | STAC only | Limited | Sentinel only |
| Full CLI | ✓ | — | — | — | Basic |
| Pipeline / YAML | ✓ | — | — | — | — |
| Keyring Auth | ✓ | Partial | — | — | ✓ |
| Parallel Downloads | ✓ Adaptive | ✓ | — | — | — |
| STAC Output | ✓ Native | — | ✓ | — | — |
| GeoParquet | ✓ | — | — | — | — |
| Docker | ✓ | — | — | — | — |
| Cron Scheduler | ✓ | — | — | — | — |
| Webhooks | ✓ | — | — | — | — |
| Planet / Maxar | ✓ | — | — | — | — |