Skip to content

USGS API (Earth Explorer)

Overview

The sat_download.api.usgs module provides the SatelliteAPI implementation for the USGS Earth Explorer using the Machine-to-Machine (M2M) API, allowing searching and downloading of Landsat 8 images.


API Reference

USGSAPI

USGSAPI(username, password)

Bases: SatelliteAPI

Implementation of SatelliteAPI for the USGS Earth Explorer API.

This class provides methods to search and download satellite imagery from the USGS Earth Explorer service using their Machine-to-Machine (M2M) API.

Parameters:

Name Type Description Default
username str

Username for authentication with the USGS Earth Explorer API

required
password str

API token for authentication (not the user's password)

required

Attributes:

Name Type Description
API_URL str

Base URL for the USGS M2M API

LOGIN_ENDPOINT str

Endpoint for authentication

SEARCH_ENDPOINT str

Endpoint for searching scenes

DOWNLOAD_REQUEST_ENDPOINT str

Endpoint for requesting download URLs

DOWNLOAD_OPTIONS_ENDPOINT str

Endpoint for fetching download options

Notes

Authentication is performed using API tokens which must be generated through the USGS Earth Explorer portal. The password parameter should actually be the API token, not the user's password.

See Also

sat_download.api.base.SatelliteAPI : Base class defining the API interface sat_download.api.odata.ODataAPI : Implementation for Copernicus Data Space API

Initialize USGS API client and authenticate with the service.

Parameters:

Name Type Description Default
username str

Username for authentication with the USGS Earth Explorer API

required
password str

API token for authentication (not the user's password)

required
Notes

Automatically calls the __login method to authenticate with USGS.

Source code in sat_download\api\usgs.py
def __init__(self, username, password):
    """
    Initialize USGS API client and authenticate with the service.

    Parameters
    ----------
    username : str
        Username for authentication with the USGS Earth Explorer API
    password : str
        API token for authentication (not the user's password)

    Notes
    -----
    Automatically calls the __login method to authenticate with USGS.
    """
    super().__init__(username, password)
    self.__login()

Functions

search

search(filters: SearchFilters) -> SearchResults

Search for satellite imagery using specified filters.

Parameters:

Name Type Description Default
filters SearchFilters

The search filters to apply to the search

required

Returns:

Type Description
SearchResults

Dictionary mapping product IDs to SatelliteImage objects

Raises:

Type Description
Exception

If the API request fails

Notes

Implementation of the abstract search method for the USGS Earth Explorer API. Additional filtering is performed client-side on the returned results.

Source code in sat_download\api\usgs.py
def search(self, filters: SearchFilters) -> SearchResults:
    """
    Search for satellite imagery using specified filters.

    Parameters
    ----------
    filters : SearchFilters
        The search filters to apply to the search

    Returns
    -------
    SearchResults
        Dictionary mapping product IDs to SatelliteImage objects

    Raises
    ------
    Exception
        If the API request fails

    Notes
    -----
    Implementation of the abstract search method for the USGS Earth Explorer API.
    Additional filtering is performed client-side on the returned results.
    """
    query = self.__prepare_query(filters)

    response = requests.post(f"{self.API_URL}{self.SEARCH_ENDPOINT}", query, headers=self.api_key)
    response = json.loads(response.text)

    if response["errorCode"] is None and bool(response["data"]["results"]):
        scenes = response["data"]
        metadata = self.__request_download_metadata(filters.collection, scenes)

        results = {}

        for scene in scenes["results"]:
            if filters.is_set('processing_level') and (not filters.processing_level in scene["displayId"]):
                continue

            if filters.is_set('tile_id') and (not f'_{filters.tile_id}_' in scene['displayId']):
                continue

            image_id = scene["entityId"]

            url = next(
                (met["url"] for met in metadata["availableDownloads"] if met["entityId"] == image_id),
                None
            )

            if url:
                results[url] = get_satellite_image(COLLECTIONS(filters.collection), {'Name' : scene["displayId"]})

        return results

    else:
        raise Exception(response["errorCode"])

download

download(
    image_id: str, outname: str, verbose: int
) -> str | None

Download a satellite image by its ID (URL).

Parameters:

Name Type Description Default
image_id str

The download URL for the image (not entity ID)

required
outname str

The output filename where the image will be saved

required
verbose int

Verbosity level for logging the download process. 0 = silent, >0 = progress bar,

required

Returns:

Type Description
None

The file is saved to the specified location on success

Notes

Implementation of the abstract download method for USGS API. Uses tqdm to display a progress bar during download. Unlike other APIs, the image_id parameter is actually the download URL.

Source code in sat_download\api\usgs.py
def download(self, image_id : str, outname : str, verbose : int) -> str | None:
    """
    Download a satellite image by its ID (URL).

    Parameters
    ----------
    image_id : str
        The download URL for the image (not entity ID)
    outname : str
        The output filename where the image will be saved
    verbose : int
        Verbosity level for logging the download process. 0 = silent, >0 = progress bar,

    Returns
    -------
    None
        The file is saved to the specified location on success

    Notes
    -----
    Implementation of the abstract download method for USGS API.
    Uses tqdm to display a progress bar during download.
    Unlike other APIs, the image_id parameter is actually the download URL.
    """
    MB = (1024 * 1024)

    try:        
        response = requests.get(image_id, stream=True)

        if response.status_code == 200:
            disposition = response.headers['content-disposition']

            total_size = int(response.headers.get('Content-Length', 0)) // MB

            filename = re.findall("filename=(.+)", disposition)[0].strip("\"")
            with open(outname, 'wb') as new_file:
                if verbose == 0:
                    for chunk in response.iter_content(chunk_size = MB):
                        new_file.write(chunk)
                else:
                    for chunk in tqdm(response.iter_content(chunk_size = MB), total = total_size,
                                      unit = 'MB', desc = f"Downloading image at {os.path.basename(outname)}"):
                        new_file.write(chunk)

            return outname
        else:
            raise Exception(f"Error en la descarga: {response.status_code}")
    except Exception as e:
        print(f"Failed to download from {image_id}. {e}.")

Endpoints

Constant Value Description
API_URL https://m2m.cr.usgs.gov/api/api/json/stable/ Base API URL
LOGIN_ENDPOINT login-token Authentication endpoint
SEARCH_ENDPOINT scene-search Scene search endpoint
DOWNLOAD_REQUEST_ENDPOINT download-request Download request endpoint
DOWNLOAD_OPTIONS_ENDPOINT download-options Download options endpoint

Supported Filters

Filter Type Description Example
collection str Satellite collection "landsat_ot_c2_l1"
start_date str Start date (YYYY-MM-DD) "2024-01-01"
end_date str End date (YYYY-MM-DD) "2024-01-31"
processing_level str Processing tier "T1"
geometry str WKT geometry "POINT(-100 40)"
tile_id str Path/Row identifier "203033"

Usage Examples

from sat_download.api.usgs import USGSAPI
from sat_download.data_types.search import SearchFilters
from sat_download.enums import COLLECTIONS

# IMPORTANT: password must be an API Token, not your password
api = USGSAPI(
    username="your_username",
    password="your_api_token_here"
)

filters = SearchFilters(
    collection=COLLECTIONS.LANDSAT_8.value,
    processing_level="T1",
    start_date="2024-01-01",
    end_date="2024-01-31",
    tile_id="203033"
)

results = api.search(filters)

for download_url, image in results.items():
    print(f"{image.date}: {image.filename}")

Search by Geometry

# Search by point
filters = SearchFilters(
    collection=COLLECTIONS.LANDSAT_8.value,
    start_date="2024-01-01",
    end_date="2024-01-31",
    geometry="POINT(-100.0 40.0)"
)

results = api.search(filters)

Download Images

# Search for images
results = api.search(filters)

# Download all images
for download_url, image in results.items():
    filepath = api.download(
        image_id=download_url,
        outname=f"./images/{image.filename}",
        verbose=1
    )

    if filepath:
        print(f"Downloaded: {filepath}")

Authentication

Important: Use API Token

The password parameter must be an API Token, not your user password.

Obtaining API Token

  1. Go to https://ers.cr.usgs.gov/
  2. Log in with your credentials
  3. Go to My ProfileAccess
  4. Click Generate Application Token
  5. Copy the token and use it as the password parameter
# Correct usage
api = USGSAPI(
    username="your_username",
    password="your_api_token_here"  # NOT your password!
)

Search Results

Keys are Download URLs

Unlike ODataAPI, the SearchResults dictionary keys are direct download URLs, not product IDs.

results = api.search(filters)

for download_url, image in results.items():
    # download_url is the direct URL to download
    # image is SatelliteImage with metadata
    print(f"URL: {download_url}")
    print(f"File: {image.filename}")

M2M API Flow

sequenceDiagram
    participant Client
    participant USGSAPI
    participant M2M as USGS M2M API

    Client->>USGSAPI: __init__(username, token)
    USGSAPI->>M2M: login-token
    M2M-->>USGSAPI: API Key

    Client->>USGSAPI: search(filters)
    USGSAPI->>M2M: scene-search
    M2M-->>USGSAPI: Scene IDs
    USGSAPI->>M2M: download-options
    M2M-->>USGSAPI: Download URLs
    USGSAPI-->>Client: SearchResults

    Client->>USGSAPI: download(url, path, verbose)
    USGSAPI->>M2M: HTTP GET (stream)
    M2M-->>USGSAPI: Binary data
    USGSAPI-->>Client: File path

Landsat Collections

Collection ID Satellite Description
landsat_ot_c2_l1 Landsat 8/9 Collection 2 Level-1
landsat_ot_c2_l2 Landsat 8/9 Collection 2 Level-2
landsat_etm_c2_l1 Landsat 7 ETM+ Collection 2 Level-1
landsat_tm_c2_l1 Landsat 4/5 TM Collection 2 Level-1

References