Satellite imagery is a powerful resource that provides valuable information about Earth. With Python and Google Earth Engine, we can efficiently access, visualize, and analyze this data. In this tutorial, we’ll cover the main types of satellite imagery, focus on optical images, and show how to visualize them using Google Earth Engine in Python.
1. Types of Satellite Imagery
Satellite images are generally of two types:
-
Optical Images
-
Capture reflected sunlight in visible and near-infrared wavelengths
-
Typically 3 to 13 bands (Sentinel-2 has 13 bands)
-
Sensitive to clouds, haze, and atmospheric effects
-
-
Radar Images (SAR)
-
Capture data using radio waves
-
Penetrates clouds and works day and night
-
Typically 2–3 polarizations (e.g., VV, VH)
-
2. Where to Get Satellite Data
Top Free Optical and Radar Data Sources
- Copernicus Data Space Ecosystem: The main official platform for accessing European Copernicus Sentinel data.
Data: Sentinel-1 (C-band SAR radar), Sentinel-2 (optical multispectral at 10 m / 20 m / 60 m), Sentinel-3 (ocean and land monitoring), Sentinel-5P (atmospheric composition).
Best for: Free global coverage with frequent revisits (Sentinel-2: 10 m optical; Sentinel-1: ~10 m in IW mode). - USGS EarthExplorer: The primary source for U.S. Geological Survey satellite archives.
Data: All Landsat missions (1–9), MODIS, ASTER, SRTM, and many other datasets.
Best for: Long historical records of optical imagery (Landsat archive back to 1972). - NASA Earthdata Search: NASA’s central gateway for Earth science data.
Data: MODIS, VIIRS, SMAP, ASTER, Sentinel-1 (via ASF DAAC), and many atmosphere, land, cryosphere, and ocean datasets.
Best for: Comprehensive scientific datasets across Earth systems. - Sentinel Hub (EO Browser) – It will be deprecated March 20, 2026–: A web-based tool for easy exploration and visualization.
Data: Sentinel-1, Sentinel-2, Landsat, MODIS, DEMs, and more.
Best for: Fast visualization, band combinations, indices (e.g., NDVI), and quick downloads without coding. - JAXA Global ALOS 3D World: A global elevation dataset from Japan’s ALOS satellite.
Data: Digital Surface Model (DSM) at 30 m resolution (AW3D30), derived from optical stereo imagery (PRISM sensor), plus orthorectified mosaics.
Best for: Global elevation data and terrain analysis. - Maxar Open Data Program (Not Free) but Provides high-resolution optical satellite imagery for selected natural disaster and emergency events around the world. The imagery is released into the public domain for crisis response, showing before and after data for major events. Scenes are usually very high resolution (often sub-meter) but only for areas affected by the specific events covered.
3. Copernicus: European Satellite Data
What Is Copernicus?
As mentioned before in Section 2, Copernicus is the European Union’s Earth observation system that continuously monitors the planet using a fleet of Sentinel satellites.
These satellites collect optical imagery, radar data, thermal measurements, and atmospheric composition data at a global scale.
The data are processed into different levels, from raw sensor measurements to analysis-ready products like surface reflectance or sea-surface temperature.
Copernicus data are freely available and accessible programmatically via APIs for scientific, environmental, and operational purposes. However, in the rest of this tutorial, we will use Google Earth Engine (GEE), which hosts Copernicus satellite imagery on Google’s servers, allowing us to access and visualize the data directly without downloading it locally.
You can explore data through the Copernicus Browser: https://browser.dataspace.copernicus.eu/

4. Sentinel-2 Optical Data
For the rest of this tutorial, we’ll work with optical imagery from Sentinel-2.
Sentinel-2 provides multispectral images across 13 bands, each designed for different applications :
Key Bands and Their Uses
B01 : Coastal aerosol (60 m)
Used for atmospheric correction over coastal areas. Rarely used directly for land analysis.
B02 : Blue (10 m)
Sensitive to water and haze. Used in true-color images and water mapping.
B03 : Green (10 m)
Represents vegetation reflectance in green wavelengths.
B04 : Red (10 m)
Strongly absorbed by healthy vegetation. Essential for NDVI.
B05 to B07 : Red Edge Bands (20 m)
Detect vegetation stress, chlorophyll content, and biomass.
B08 : Near Infrared (10 m)
Strongly reflected by healthy plants. Core band for vegetation analysis.
B8A : Narrow NIR (20 m)
More precise NIR measurements for advanced indices.
B09 : Water vapor (60 m)
Used for atmospheric correction.
B10 : Cirrus (60 m)
Detects high-altitude thin clouds.
B11 and B12 : SWIR (20 m)
Useful for soil moisture, drought monitoring, burned areas, and geology.
Processing Levels
You will encounter two main processing levels:
Level-1C (L1C)
-
Top-of-atmosphere reflectance
-
Atmospheric effects still present
Level-2A (L2A)
-
Atmosphere-corrected surface reflectance
-
Includes cloud masks
-
Better for analysis
In this tutorial, we will use Level-2A (L2A) products.
5. Setting Up the Anaconda Environment
We need to install the necessary libraries.
1. Create a Google Earth Engine Account
Google Earth Engine (GEE) is a cloud platform that hosts massive satellite datasets and enables large-scale geospatial analysis. It also stores Copernicus satellite imagery, including radar and optical data from Sentinel-1 and Sentinel-2, among others. In this tutorial, we will focus on using Sentinel-2 optical images.
-
Sign in with your Google account here: https://earthengine.google.com/signup/
2. Create a fresh Anaconda environment
We will use Anaconda in this tutorial. You can download it from: https://www.anaconda.com/download
After downloading, open the command prompt and run the following commands to create a new environment in Anaconda called satellite and activate it:
# Create and activate the environment conda create -n satellite python=3.11 conda activate satellite # Install ipykernel in the environment conda install ipykernel # Add the environment to Jupyter Notebook as a kernel python -m ipykernel install --user --name=satellite --display-name "Python (satellite)"
3. Install Necessary Libraries
These are the core packages needed to visualize imagery from Earth Engine:
# Install core geospatial libraries with conda (ensures compiled dependencies are handled) conda install -c conda-forge numpy=1.26 pandas=2.1 matplotlib geopandas shapely=2.0 folium notebook -y # Install Python-only packages with pip pip install earthengine-api geemap georeader-spaceml
4. Authenticate Earth Engine
Run the following command once in your command prompt to link your Google account:
earthengine authenticate
A browser window will open, prompting you to log in and authorize access. Once completed, your Python scripts will be able to access Google Earth Engine.
5. Launch Jupyter Notebook
After setting up your environment and authenticating Earth Engine, launch Jupyter Notebook by running the following command in your command prompt:
jupyter notebook
This will open the Jupyter interface in your browser, where you can start writing and running Python code.
5. Visualizing Sentinel-2 Imagery
In this section, we visualize Sentinel-2 optical images over a specified area in Morocco (Area of Interest) directly from Google Earth Engine using Python:
# =========================
# Import Libraries
# =========================
import ee
# Authenticate once if needed:
# ee.Authenticate()
ee.Initialize(project='id_of _you_project_in_gee') #put the id of your project in Google Earth Engine
import geopandas as gpd
from shapely.geometry import shape
from datetime import datetime, timezone
import geemap
import matplotlib.pyplot as plt
from georeader.readers import ee_query
# =========================
# Define Area of Interest (AOI)
# =========================
aoi = shape({
'type': 'Polygon',
'coordinates': (((-6.453954025338924, 32.530447002052426),
(-6.423890509569403, 32.52988323861328),
(-6.425201107676793, 32.51777274579041),
(-6.455264623446316, 32.51678037980431),
(-6.453954025338924, 32.530447002052426)),)
})
# GeoPandas version
aoi_gpd = gpd.GeoDataFrame(
{"geometry": [aoi]},
crs="EPSG:4326"
)
# Earth Engine geometry (IMPORTANT)
aoi_ee = ee.Geometry.Polygon(aoi.__geo_interface__["coordinates"])
# =========================
# Define Time Range
# =========================
tz = timezone.utc
start_period = datetime(2025, 12, 30, tzinfo=tz)
end_period = datetime(2026, 1, 10, tzinfo=tz)
# =========================
# Query Satellite Data
# =========================
flood_images_gee, flood_collection = ee_query.query(
area=aoi,
date_start=start_period,
date_end=end_period,
producttype="S2",
return_collection=True,
add_s2cloudless=False
)
# =========================
# Create Map
# =========================
m = geemap.Map(
center=aoi.centroid.coords[0][::-1],
zoom=8
)
m.add_basemap("SATELLITE")
# =========================
# Prepare Data for Visualization
# =========================
flood_images_gee["localdatetime_str"] = (
flood_images_gee["localdatetime"]
.dt.strftime("%Y-%m-%d %H:%M:%S")
)
showcolumns = [
"geometry",
"overlappercentage",
"cloudcoverpercentage",
"localdatetime_str",
"solarday",
"satellite"
]
colors = [
"#ff7777", "#fffa69", "#8fff84", "#52adf1",
"#ff6ac2", "#1b6d52", "#fce5cd", "#705334"
]
# =========================
# Add Product Footprints
# =========================
for i, ((day, satellite), images_day) in enumerate(
flood_images_gee.groupby(["solarday", "satellite"])
):
gdf = images_day[showcolumns]
m.add_gdf(
gdf,
layer_name=f"{satellite}: {day} outline",
style={"color": colors[i % len(colors)], "fillOpacity": 0}
)
# =========================
# Add Satellite Imagery Layers
# =========================
for (day, satellite), images_day in flood_images_gee.groupby(
["solarday", "satellite"]
):
image_col_day_sat = flood_collection.filter(
ee.Filter.inList("title", images_day.index.tolist())
)
bands = (
["B11", "B8", "B4"] # Sentinel-2 SWIR composite
if satellite.startswith("S2")
else ["B6", "B5", "B4"] # Landsat 8 SWIR composite
)
m.addLayer(
image_col_day_sat,
{
"min": 0,
"max": 3000 if satellite.startswith("S2") else 0.3,
"bands": bands
},
f"{satellite}: {day}",
True # ← SHOW IMAGES
)
# =========================
# Add AOI Outline
# =========================
m.add_gdf(
aoi_gpd,
layer_name="AOI",
style={"color": "black", "fillOpacity": 0}
)
# =========================
# Add Layer Control
# =========================
m.add_layer_control()
# Display map
m

In the next article, we will explore deeper applications of optical satellite data. From vegetation monitoring and water quality assessment to urban mapping and disaster analysis, we’ll show how these datasets can be harnessed to extract meaningful insights and drive decision-making.
Hey there! I am the creator of AI Decoder.
I am a data scientist by training and a Ph.D. student in AI. In this blog, I try to explain the knowledge I learn in simple words and help someone somewhere.

