Introduction

The Google Earth Engine (GEE) Python API provides access to Google’s multi-petabyte catalog of satellite imagery, climate data, and geospatial datasets. Earth Engine performs computation on Google’s servers, so you can analyze datasets spanning decades of global satellite observations without downloading anything to your local machine.

Earth Engine is used extensively in environmental science, agriculture, forestry, disaster response, and urban planning. Its server-side computation model means that even complex analyses over massive datasets run efficiently, since the data never leaves Google’s infrastructure until you request a final result.

In this guide, you will learn how to authenticate with Earth Engine, query image collections, perform computations on satellite data, and export results.

Overview

Key features of the Earth Engine API:

  • Massive data catalog: Access to Landsat, Sentinel, MODIS, and hundreds of other datasets going back decades
  • Server-side computation: All processing happens on Google’s cloud infrastructure
  • Image and ImageCollection: Core abstractions for working with raster data
  • FeatureCollection: Vector data support for points, polygons, and other geometries
  • Reducers and aggregations: Built-in statistical operations for spatial and temporal analysis
  • Export capabilities: Export results to Google Drive, Cloud Storage, or as Earth Engine assets

Use cases:

  • Land cover and land use change detection
  • Vegetation health monitoring (NDVI, EVI)
  • Climate and weather data analysis
  • Flood and wildfire mapping
  • Agricultural yield estimation

Getting Started

Install the Earth Engine Python API:

pip install earthengine-api

Authenticate and initialize:

import ee

# Authenticate (opens a browser for OAuth, only needed once)
ee.Authenticate()

# Initialize the API
ee.Initialize(project='your-cloud-project-id')

# Verify the connection by querying an elevation dataset
dem = ee.Image('USGS/SRTMGL1_003')
info = dem.getInfo()
print(f"Dataset type: {info['type']}")
print(f"Bands: {[b['id'] for b in info['bands']]}")

Core Concepts

Images and ImageCollections

An ee.Image represents a single raster image (potentially with multiple bands). An ee.ImageCollection is a stack of images, typically filtered by date, location, or metadata:

import ee

ee.Initialize(project='your-cloud-project-id')

# Load a Sentinel-2 image collection
collection = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED') \
    .filterDate('2024-06-01', '2024-08-31') \
    .filterBounds(ee.Geometry.Point(-122.4194, 37.7749)) \
    .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))

print(f"Number of images: {collection.size().getInfo()}")

# Get the median composite
composite = collection.median()

Geometry and Filtering

Earth Engine provides geometry objects for spatial operations:

import ee

# Define a region of interest as a rectangle
roi = ee.Geometry.Rectangle([-122.5, 37.7, -122.3, 37.85])

# Define a point
point = ee.Geometry.Point(-122.4194, 37.7749)

# Filter an image collection by region and date
landsat = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') \
    .filterBounds(roi) \
    .filterDate('2023-01-01', '2023-12-31')

print(f"Landsat scenes over ROI: {landsat.size().getInfo()}")

Computing NDVI

A common operation is computing the Normalized Difference Vegetation Index:

import ee

ee.Initialize(project='your-cloud-project-id')

# Load a Landsat 8 image
image = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') \
    .filterDate('2023-06-01', '2023-08-31') \
    .filterBounds(ee.Geometry.Point(-96.0, 41.0)) \
    .median()

# Compute NDVI: (NIR - Red) / (NIR + Red)
# Landsat 8 L2: SR_B5 = NIR, SR_B4 = Red
ndvi = image.normalizedDifference(['SR_B5', 'SR_B4']).rename('NDVI')

# Sample the NDVI value at a point
point = ee.Geometry.Point(-96.0, 41.0)
value = ndvi.sample(point, scale=30).first().getInfo()
print(f"NDVI at point: {value['properties']['NDVI']:.3f}")

Practical Examples

Example 1: Time Series Analysis of Vegetation

import ee

ee.Initialize(project='your-cloud-project-id')

# Define a region and time range
region = ee.Geometry.Point(-89.4, 43.07).buffer(5000)

# Load Landsat 8 and compute monthly NDVI
def compute_ndvi(image):
    ndvi = image.normalizedDifference(['SR_B5', 'SR_B4']).rename('NDVI')
    return ndvi.set('system:time_start', image.get('system:time_start'))

monthly_ndvi = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') \
    .filterBounds(region) \
    .filterDate('2023-01-01', '2023-12-31') \
    .filter(ee.Filter.lt('CLOUD_COVER', 30)) \
    .map(compute_ndvi)

# Reduce to mean NDVI over the region for each image
def extract_mean(image):
    mean = image.reduceRegion(
        reducer=ee.Reducer.mean(),
        geometry=region,
        scale=30
    )
    return ee.Feature(None, {
        'date': image.date().format('YYYY-MM-dd'),
        'mean_ndvi': mean.get('NDVI')
    })

results = monthly_ndvi.map(extract_mean).getInfo()

for feature in results['features']:
    props = feature['properties']
    if props['mean_ndvi'] is not None:
        print(f"{props['date']}: NDVI = {props['mean_ndvi']:.3f}")

Example 2: Exporting a Composite Image to Google Drive

import ee

ee.Initialize(project='your-cloud-project-id')

roi = ee.Geometry.Rectangle([-122.5, 37.7, -122.3, 37.85])

# Create a cloud-free Sentinel-2 composite
composite = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED') \
    .filterBounds(roi) \
    .filterDate('2024-06-01', '2024-08-31') \
    .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 10)) \
    .median() \
    .select(['B4', 'B3', 'B2'])  # RGB bands

# Export to Google Drive
task = ee.batch.Export.image.toDrive(
    image=composite,
    description='sentinel2_composite',
    folder='EarthEngine',
    region=roi,
    scale=10,
    maxPixels=1e9
)

task.start()
print(f"Export task started: {task.status()}")

Best Practices

  • Use server-side operations: Keep computations on the server using ee objects and methods. Avoid calling .getInfo() in loops, as each call is a round trip to the server.
  • Filter early and aggressively: Apply .filterDate(), .filterBounds(), and metadata filters before any computation to reduce the amount of data processed.
  • Use scale parameter: Always specify a scale (in meters) when using reduceRegion or sample to control the resolution of your analysis.
  • Handle cloud masking: Use quality assessment bands to mask cloudy pixels before computing composites or statistics.
  • Export large results: For results that cover large areas or long time series, use ee.batch.Export rather than .getInfo() to avoid timeouts.

Common pitfalls:

  • Calling .getInfo() on large collections or images will time out. Use reducers or export tasks for large-scale results.
  • Forgetting to call ee.Initialize() before any API calls will raise an error.
  • Earth Engine computations are lazy. Nothing runs until you request a result with .getInfo(), .evaluate(), or an export task.

Conclusion

The Google Earth Engine Python API opens up planetary-scale geospatial analysis to anyone with a Python environment. Its server-side computation model, massive data catalog, and rich set of spatial and temporal operations make it an essential tool for environmental monitoring, land use analysis, and climate research.

Resources:


Powered by Jekyll & Minimal Mistakes.

About this article. This article was generated by the Best-of-the-Best autonomous AI digest and reviewed by Ruslan Magana Vsevolodovna. Package metadata was last checked on 15 January 2026. See the data leaderboard and the GitHub repository for sources.