v1.0.0 · Production Ready · 60 Tests Passing

pygeofetch Documentation

Universal satellite data pipeline — unified access to 22+ providers. Handles auth, federated search, parallel downloads, caching, band selection, and post-processing.

22+
Providers
10
Free (No Login)
7
Output Formats
60
Tests Passing
$ install
pip install pygeofetch
MIT License Python 3.9+
Getting Started

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.

1
Install
# Core install — free providers work immediately pip install pygeofetch # With raster post-processing (reproject, COG) pip install "pygeofetch[geo]" # Everything including dev tools pip install "pygeofetch[all]"
2
Verify installation
pygeofetch --version # → pygeofetch, version 1.0.0 pygeofetch doctor # Checks Python, packages, keyring, # and live connectivity to free providers
3
Search (no login needed)
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 \ --format table
4
Download results
pygeofetch download run \ --from-search results.geojson \ --output ./data/ \ --parallel 2 \ --max-items 3 \ --bands "B02,B03,B04" # RGB only — ~150 MB vs 600 MB full scene

Interactive demo — try commands

Select a command from the dropdown and click Run to see the expected output:

pygeofetch — interactive demo
$ pygeofetch doctor Select a command above and click ▶ Run
$
Authentication

Managing Provider Credentials

Credentials are stored in your system keyring — never in plain-text files. Supports username/password, API keys, and OAuth2 client credentials.

auth commands
# 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

.env / CI/CD
# 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
Headless Linux: If no D-Bus/keyring daemon is running (Docker, SSH), set PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring and use environment variables instead.

Provider auth types

ProviderAuth TypeFree?Register At
usgsUsername / Password✓ Freeers.cr.usgs.gov
copernicusUsername / Password (OAuth2)✓ Freedataspace.copernicus.eu
nasa_earthdataUsername / Password✓ Freeurs.earthdata.nasa.gov
nasa_earthdata_cloudUsername / Password + S3 creds✓ Freeurs.earthdata.nasa.gov
planetAPI KeySubscriptionplanet.com/account
sentinel_hubOAuth2 client credentialsFreemiumapps.sentinel-hub.com
opentopographyAPI Key✓ Free tierportal.opentopography.org
maxar_gbdxAPI TokenSubscriptiondevelopers.maxar.com
airbus_oneatlasAPI KeySubscriptiononeatlas.airbus.com
alaska_satellite_facilityEarthdata (same as NASA)✓ Freeurs.earthdata.nasa.gov
google_earth_engineService Account JSONFree tierconsole.cloud.google.com
terraboticsAPI KeySubscriptionterrabotics.earth
Search

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.

search examples
# 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

Flag
Type
Description
--bbox
string
Bounding box "minlon,minlat,maxlon,maxlat". Longitude first. Alternative to --geometry-file.
--geometry-file
path
GeoJSON file with search AOI polygon. Extracts bbox automatically.
--start-date
date
Temporal filter start. Format: YYYY-MM-DD.
--end-date
date
Temporal filter end. Defaults to today if omitted.
--cloud-cover
range
Cloud cover range min-max in percent. E.g. 0-20.
0-100
--resolution
range
Resolution range in metres min-max. E.g. 10-30.
--providers
list
Comma-separated provider IDs. E.g. aws_earth,copernicus,usgs.
--satellites
list
Comma-separated satellite names. E.g. Sentinel-2,Landsat-8.
--processing-level
string
Processing level. E.g. L2A, L2SP.
--max-results
int
Maximum results to return.
100
--sort-by
choice
datetime, cloud_cover, score, satellite.
datetime
--sort-order
choice
asc or desc.
desc
--cql2
string
CQL2 filter expression. Sent as CQL2-JSON to STAC APIs.
--output
path
Save results to this file.
--format
choice
table, json, stac, geojson, geoparquet, csv, ids.
table
--on-provider-failure
choice
skip, abort, retry.
skip
--timeout
int
Per-provider timeout in seconds.
60
--no-cache
flag
Bypass the in-memory result cache.

Output formats

table
--format table
Pretty terminal table. Default. ID, date, cloud%, score, satellite.
json
--format json
Full JSON array with all fields. Good for scripting and piping.
stac
--format stac
STAC 1.0 ItemCollection. Compatible with pystac-client.
geojson
--format geojson
GeoJSON FeatureCollection. Open in QGIS, ArcGIS, or Leaflet.
geoparquet
--format geoparquet
GeoParquet file. Requires geopandas. Best for large result sets.
csv
--format csv
CSV with id, provider, satellite, datetime, cloud_cover, bbox.
ids
--format ids
Scene IDs only, one per line. Good for shell scripting.

CQL2 filter examples

CQL2 — supported by Planetary Computer, Element84, AWS Earth
# 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'"
Download

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.

download examples
# 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

Flag
Type
Description
--from-search
path
GeoJSON results file from search run --output. Required.
--output
path
Output directory. Created automatically.
./pygeofetch_data
--parallel
int
Concurrent download workers.
2
--retry
int
Max retry attempts with exponential backoff.
3
--retry-delay
float
Base retry delay seconds. Doubles each attempt.
5.0
--verify-checksum
flag
SHA256 verification after each download. Auto-retries on mismatch.
--resume
flag
Resume interrupted downloads from last byte received.
on
--bandwidth-limit
string
Throttle bandwidth. E.g. 10MB, 500KB. 0 = unlimited.
--priority
choice
high, normal, low.
normal
--bands
list
Comma-separated band names. E.g. B02,B03,B04. Default: all data assets.
--post-process
string
Comma-separated processing chain. E.g. "unzip,reproject:EPSG:4326,cog".
--on-failure
choice
skip, abort, retry.
skip
--max-items
int
Limit to first N items in the results file.
--overwrite
flag
Overwrite files that already exist. Default: skip existing.
--notify
string
webhook:URL or email:ADDRESS. Repeatable for multiple targets.
--json
flag
Output results summary as JSON.

Band selection for Sentinel-2

BandsPurposeResolutionApprox Size/Scene
B02,B03,B04RGB (Blue, Green, Red)10m~150 MB
visualTrue colour composite (TCI pre-rendered)10m~200 MB
B04,B08NDVI (Red + NIR)10m~100 MB
B02,B03,B04,B08RGB + NIR (4-band)10m~200 MB
B11,B12SWIR (fire, burn scar, soil moisture)20m~50 MB
SCLScene Classification Layer (cloud mask)20m~20 MB
(omit --bands)All data bands (full scene)10/20/60m~600 MB

Post-processing actions

ActionSyntaxDescriptionRequires
unzipunzipExtract ZIP/TAR archives
reprojectreproject:EPSG:4326Reproject to target CRSrasterio
compresscompress:lzwGeoTIFF compression (lzw, deflate, zstd)rasterio
cogcogConvert to Cloud Optimized GeoTIFFrasterio
clipclip:file.geojsonClip raster to polygon boundaryrasterio
resampleresample:30Resample to target resolution (metres)rasterio
ndvindviCalculate NDVI from Red and NIR bandsrasterio
ndwindwiCalculate NDWI water indexrasterio
atmosphericatmospheric:sen2corAtmospheric correctionsen2cor
pan-sharpenpan-sharpenPan-sharpen multispectral with panchromaticrasterio
mergemergeMosaic overlapping scenesrasterio
Providers

22 Satellite Data Providers

Filter by capability. 10 providers require no authentication and work immediately.

planetary_computerOpen
Microsoft STAC catalog. Sentinel-1/2, Landsat 8/9, MODIS, NAIP, ALOS DEM. SAS tokens auto-generated.
STACSAR
aws_earthOpen
AWS Earth Open Data. Sentinel-2 COGs, Landsat Collection 2, NAIP. Direct S3 access.
STAC
element84Open
Element 84 Earth Search v1. Sentinel-2 L2A, Landsat Col 2, Sentinel-1 RTC, COP-DEM. All COG.
STACSAR
noaa_big_dataOpen
GOES-16/17/18 weather imagery and NEXRAD radar. AWS Open Data registry.
esa_scihubOpen
ESA Copernicus public mirrors. Sentinel-1/2/3/5P open archive access.
SAR
jaxa_earthOpen
JAXA ALOS 30m World 3D DSM and PALSAR-2 forest/non-forest global map.
SAR
isro_bhuvanOpen
ISRO Bhuvan portal. ResourceSat-2/2A (5.8m), Cartosat-1 (2.5m), Oceansat-2.
inpe_cbersOpen
Brazil INPE CBERS-4 and CBERS-4A. 5m to 40m optical bands. Free download.
digitalglobeOpen
Maxar Open Data Program. Sub-metre WorldView disaster response imagery for humanitarian use.
<1m
geoserver_genericOpen
Generic OGC WMS/WFS/WCS connector for any GeoServer or OGC-compliant service endpoint.
usgs🔐 Auth
USGS Earth Explorer. Landsat 1–9, ASTER, MODIS, EO-1. Machine-to-Machine API.
STAC
copernicus🔐 Auth
Copernicus Data Space Ecosystem. Sentinel-1/2/3/5P. Full STAC API, OAuth2.
STACSAR
nasa_earthdata🔐 Auth
NASA CMR. MODIS, VIIRS, ICESat-2, GEDI, ASTER. Free registration required.
STAC
nasa_earthdata_cloud🔐 Auth
Cloud-native NASA data on AWS. Temporary S3 credentials auto-refreshed.
STAC
opentopography🔐 Auth
SRTM 30/90m, COP-DEM 30m, NASADEM, global LiDAR point clouds. Free API key.
planet🔐 Auth
Planet Labs. PlanetScope (3m daily), SkySat (50cm), RapidEye. Subscription required.
STAC<1m
sentinel_hub🔐 Auth
Sentinel Hub Processing API. Sentinel-1/2/3, Landsat, custom evalscripts.
SAR
maxar_gbdx🔐 Auth
Maxar WorldView 1–4, GeoEye-1. 30cm–50cm resolution. Commercial subscription.
<1m
airbus_oneatlas🔐 Auth
Airbus Pléiades (50cm) and SPOT 6/7 (1.5m). OneAtlas STAC API.
STAC<1m
alaska_satellite_facility🔐 Auth
ASF DAAC. Sentinel-1 SLC/GRD, ALOS PALSAR, UAVSAR. Free with Earthdata login.
SAR
google_earth_engine🔐 Auth
GEE catalog proxy. Access multi-petabyte collection via service account.
SAR
terrabotics🔐 Auth
TerraBotics archive and tasking. Sub-metre commercial imagery. API key required.
<1m
Pipelines

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.

STEP 01
🔍
Search
Federated query across providers. Supports date ranges, cloud filters, CQL2.
STEP 02
🎯
Filter
Expression-based post-filter on results. Any property or scoring field.
STEP 03
⬇️
Download
Parallel, resumable download with checksum verification and retry.
STEP 04
📤
Export
Push to S3, GCS, local disk, or trigger webhook notification.

Full pipeline YAML example

weekly-sentinel2.yaml
# 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

pipeline management
# 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
Scheduling note: 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

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.

example.py — full workflow
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 dataclass
bbox
tuple[float,4]
Bounding box as (minlon, minlat, maxlon, maxlat). Longitude first (WGS84).
geometry
dict | None
GeoJSON geometry dict. Alternative to bbox for polygon AOIs.
start_date
str | date
Temporal filter start. ISO format string or date object.
end_date
str | date
Temporal filter end. Defaults to today.
cloud_cover_max
float
Maximum cloud cover percentage (0–100). Default: 100.
cloud_cover_min
float
Minimum cloud cover percentage. Default: 0.
resolution_min
float | None
Minimum spatial resolution in metres.
resolution_max
float | None
Maximum spatial resolution in metres.
satellites
list[str]
Satellite names to filter. E.g. ["Sentinel-2", "Landsat-8"].
processing_level
str | None
Processing level filter. E.g. "L2A".
max_results
int
Maximum number of results to return. Default: 100.
sort_by
str
"datetime", "cloud_cover", "score", "satellite". Default: "datetime".
sort_order
str
"asc" or "desc". Default: "desc".
cql2_filter
str | None
CQL2 expression string. Only applied to STAC-capable providers.

DownloadOptions parameters

DownloadOptions dataclass
parallel
int
Number of concurrent download workers. Default: 2.
retry
int
Max retry attempts with exponential backoff. Default: 3.
retry_delay
float
Base delay seconds between retries. Default: 5.0.
verify_checksum
bool
SHA256 verification after download. Default: False.
resume
bool
Resume incomplete downloads. Default: True.
bands
list[str]
Band names to download. E.g. ["B02", "B03", "B04"]. Default: all assets.
post_process
list[str]
Processing chain steps. E.g. ["reproject:EPSG:4326", "cog"].
bandwidth_limit
str | None
E.g. "10MB", "500KB". None = unlimited.
on_failure
str
"skip", "abort", or "retry". Default: "skip".
overwrite
bool
Overwrite existing files. Default: False (skip existing).

pygeofetch class methods

pygeofetch class
add_credentials(provider: str, *, username=None, password=None, api_key=None, client_id=None, client_secret=None) → None
Register credentials for a provider. Stored in system keyring. Overrides env vars.
search(query: SearchQuery, providers: list[str], timeout: int = 60, on_provider_failure: str = "skip") → list[SceneResult]
Execute federated search. Returns sorted, deduplicated list of SceneResult objects.
download(scenes: list[SceneResult], destination: Path, options: DownloadOptions) → list[DownloadResult]
Download scenes in parallel. Returns list of DownloadResult objects with success/error details.
providers() → list[ProviderInfo]
List all registered providers with authentication status and capabilities.
cache_stats() → dict
Return cache statistics: hit rate, size, entry count, TTL.
clear_cache(provider: str | None = None) → None
Clear search result cache. Pass provider name to clear one provider only.
Reference

Full CLI Reference

Complete listing of all commands, subcommands, and global options.

Global options

global flags (apply to every command)
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

GroupSubcommandsDescription
authadd, login, list, test, remove, exportManage provider credentials
providerslist, info, searchBrowse and inspect providers
searchrun, demoSearch for satellite scenes
downloadrun, demoDownload scenes to disk
cachestats, clear, ttl, location, pruneManage search result cache
pipelinerun, validate, schedule, list-scheduled, unschedule, logs, history, retryPipeline orchestration
configshow, get, set, path, resetRead and modify configuration
statusSystem status dashboard
doctorDiagnose installation and connectivity
versionShow version info

Cache commands

cache
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

providers
# 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

tab 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

Configuration Reference

pygeofetch uses a layered config system. Settings are merged in order of precedence from lowest to highest.

1️⃣
Built-in defaults
Sensible defaults baked into the package. Lowest priority.
2️⃣
~/.pygeofetch/config.yaml
User-level config. Applies to all projects on this machine.
3️⃣
.pygeofetch.yaml
Project config in current directory. Overrides user config.
4️⃣
Environment variables
pygeofetch_* env vars. Override file config.
5️⃣
CLI arguments
Flags passed on the command line. Highest priority.

Full configuration file

~/.pygeofetch/config.yaml
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

config 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

Security Model

pygeofetch is designed with credential safety, network security, and data integrity as first-class concerns.

🔑 Credential Handling
  • 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
🌐 Network Security
  • TLS 1.2+ enforced on all outbound connections
  • SSL certificate verification always on — no verify=False in codebase
  • Certificate pinning available for enterprise deployments
  • HTTP proxy support via HTTP_PROXY / HTTPS_PROXY
  • Connection timeouts enforced per provider
📦 Data Integrity
  • 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
🔒 Privacy
  • 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
Reporting vulnerabilities: Do not open public GitHub issues for security vulnerabilities. Email security@pygeofetch.dev. Response time: within 48 hours. Responsible disclosure policy: 90-day window.
Reference

Error Handling & Resilience

pygeofetch handles failures at every layer — provider outages, network interruptions, checksum mismatches, and partial failures are all managed gracefully.

Provider failures

failure policies
# 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

ProviderAuthError
→ Run: pygeofetch auth test PROVIDER
Credentials missing, expired, or rejected. Re-add with auth add or set the appropriate env var.
ProviderTimeoutError
→ Use: --timeout 120
Provider API did not respond within the timeout window. Increase --timeout or check provider status page.
ChecksumMismatchError
→ Use: --retry 5 --verify-checksum
Downloaded file hash does not match provider checksum. Automatic re-download triggered up to retry limit.
NoResultsError
→ Widen: --cloud-cover 0-30
Search returned zero scenes. Relax cloud cover filter, extend date range, or check bbox coordinates (lon first).
KeyringUnavailableError
→ Set: PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
No system keyring daemon available (Docker, headless SSH). Use environment variables or file-based auth storage.
RateLimitError
→ Use: --parallel 1 --bandwidth-limit 2MB
Provider API rate limit hit. Reduce parallelism, add delays, or use bandwidth limiting. Planet and Maxar are most restrictive.
PostProcessError
→ Run: pip install "pygeofetch[geo]"
Post-processing action failed. Usually missing rasterio or GDAL. Install the [geo] extra or verify rasterio installation.
CircuitBreakerOpen
→ Wait 60s or use: --on-provider-failure skip
Provider disabled after 5 consecutive failures. Circuit breaker auto-resets after 60 second cooldown period.

Download resilience internals

🔄
Exponential Backoff
Retries with 1s, 2s, 4s, 8s, 16s delays + random jitter. Configurable base delay and max cap. Prevents thundering herd against recovering providers.
⏸️
Resume Support
Interrupted downloads resume from the last received byte using HTTP range requests. Resume tokens stored per scene. No re-downloading of completed bytes.
🛡️
Atomic Writes
Files written to .tmp then renamed atomically on completion. Partial files never corrupt existing data. Temp files cleaned up on failure.
Circuit Breaker
Providers disabled after 5 consecutive failures, automatically retried after 60 second cooldown. Prevents slow cascading failures in multi-provider searches.
🗄️
Search Caching
Search results cached per query with configurable TTL (default 1 hour). Cache hits return instantly without API calls. Auto-invalidates on expiry.
Checksum Verification
SHA256 (or MD5/SHA512) verified post-download. Mismatches trigger automatic re-download. Configurable: disable for speed, enable for integrity-critical workflows.
Docker

Docker & Containers

pygeofetch ships an official Docker image for reproducible environments, CI/CD pipelines, and scheduled pipeline execution.

Quick start

Docker 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

docker-compose.yml
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

build from source
git clone https://github.com/appiahkubis14/pygeofetch
cd pygeofetch
docker build -t pygeofetch:local .
docker run pygeofetch:local doctor
Images available on Docker Hub (pygeofetch/pygeofetch) and GitHub Container Registry (ghcr.io/appiahkubis14/pygeofetch). Tags: latest, 1.0.0, slim (no rasterio).
Testing

Testing

pygeofetch ships with 60 tests covering unit, integration, property-based, and CLI end-to-end scenarios.

running tests
# 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

🧪
Unit Tests
Every provider, utility, and model has dedicated unit tests. Mocked HTTP responses using responses and httpx mocks. No network required.
📼
VCR Recordings
HTTP interactions recorded with pytest-vcr for deterministic replay. Cassettes checked into the repo — CI never hits real APIs.
🎲
Property-Based Testing
Edge cases generated automatically with hypothesis. Covers bbox validation, date parsing, band selection, and config merging.
🖥️
CLI Tests
Full workflow tests with Click's CliRunner. Search → save → download → post-process pipelines tested end-to-end without spawning subprocesses.
🌐
Integration Tests
Optional real-API tests gated behind --run-integration. Require credentials. Run in CI with secret injection from GitHub Actions.
📊
Coverage Gate
80% line coverage minimum enforced in CI. PRs failing the threshold are blocked. Coverage report uploaded to Codecov on each merge.

Contributing tests

test structure
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

Roadmap

Planned features by version. Vote on priorities at github.com/appiahkubis14/pygeofetch/discussions.

v1.0.0
Production Release
✓ Released — Q2 2025
  • 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
v0.2.0
Extended Providers
◐ In Progress — Q4 2024
  • BlackSky provider
  • SI Imaging Services (KOMPSAT)
  • Interactive search mode (--interactive)
  • Slack, Discord, Teams webhook templates
  • Streaming COG partial reads
v0.3.0
Dashboard & API Server
○ Planned — Q1 2025
  • 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
Providers22+10+STAC onlyLimitedSentinel only
Full CLIBasic
Pipeline / YAML
Keyring AuthPartial
Parallel Downloads✓ Adaptive
STAC Output✓ Native
GeoParquet
Docker
Cron Scheduler
Webhooks
Planet / Maxar