Accessing DEMs and Sentinel-1 Data from the Planetary Computer catalogs
In this post, I reproduce the process of obtaining satellite data from the Microsoft Planetary Computer, focusing on Digital Elevation Models (DEMs) and Synthetic Aperture Radar (SAR) imagery. I also show how to access, visualize, and combine multiple items. The code examples DEM_getting.ipynb and sentinel-1_GRD_getting.ipynb are based on the official Microsoft Planetary Computer documentation: Reading Data from the STAC API.
Libraries
We’ll use the following Python libraries, including planetary_computer and pystac for accessing and managing data assets.
import matplotlib.pyplot as plt
import xarray as xr
import pystac
import planetary_computer
import rioxarray
import numpy as np
import rasterio
from rasterio.merge import mergeAccessing an individual item’s data assets
DEMs
The Planetary Computer platform provides code examples for retrieving an item’s data assets:

item_url = "https://planetarycomputer.microsoft.com/api/stac/v1/collections/cop-dem-glo-30/items/Copernicus_DSM_COG_10_N06_00_W077_00_DEM" # item 1
# item_url = "https://planetarycomputer.microsoft.com/api/stac/v1/collections/cop-dem-glo-30/items/Copernicus_DSM_COG_10_N06_00_W078_00_DEM" # item 2
# Load the individual item metadata and sign the assets
item = pystac.Item.from_file(item_url)
signed_item = planetary_computer.sign(item)
# Open one of the data assets
asset_href = signed_item.assets["data"].href
ds = rioxarray.open_rasterio(asset_href)We can then plot the DEM data:
plt.figure()
plt.imshow(ds[0, ...], cmap=cmap_terrain_crust, vmin=0, vmax=4500)
plt.colorbar()
plt.show()
SARs
To access a Sentinel-1 SAR dataset:
item_url = "https://planetarycomputer.microsoft.com/api/stac/v1/collections/sentinel-1-grd/items/S1C_IW_GRDH_1SDV_20250922T232209_20250922T232234_004244_0086B0" # item 1
# item_url = "https://planetarycomputer.microsoft.com/api/stac/v1/collections/sentinel-1-grd/items/S1C_IW_GRDH_1SDV_20250922T232144_20250922T232209_004244_0086B0" # item 2
# Load the individual item metadata and sign the assets
item = pystac.Item.from_file(item_url)
signed_item = planetary_computer.sign(item)
# Open one of the data assets (other asset keys to use: 'vv')
asset_href = signed_item.assets["vh"].href
ds = rioxarray.open_rasterio(asset_href)Reproject the raster to a CRS:
ds_reprojected = ds.rio.reproject("EPSG:4326")And save it as a GeoTIFF (compatible with GIS software):
filename = '../../data/SAR/sentinel-1_GRD_VH_1.tif'
ds_reprojected.rio.to_raster(filename)If the dataset is very large, you can subsample it:
sampling = 10
SAR = ds_reprojected.isel(
x=slice(None, None, sampling),
y=slice(None, None, sampling)
)And plot the subsampled data:
raster_plotting.plot_raster_data(SAR.x, SAR.y, SAR[0], vmax=400)
Combining two individual item’s data assets.
DEMs
If we already have the dataset ds for the first DEM item, we can combine it with another as follows:
item_url = "https://planetarycomputer.microsoft.com/api/stac/v1/collections/cop-dem-glo-30/items/Copernicus_DSM_COG_10_N06_00_W078_00_DEM" # item 2
item = pystac.Item.from_file(item_url)
signed_item = planetary_computer.sign(item)
asset_href = signed_item.assets["data"].href
ds2 = rioxarray.open_rasterio(asset_href)
# Ensure both datasets have CRS information
ds_crs = ds.rio.write_crs("EPSG:4326", inplace=False)
ds2_crs = ds2.rio.write_crs("EPSG:4326", inplace=False)
combined_ds = xr.combine_by_coords([ds_crs, ds2_crs])
SARs
We can merge two saved GeoTIFFs as follows:
# Paths to the GeoTIFF files to be mosaicked
tiff1 = '../../data/SAR/sentinel-1_GRD_VH_1.tif'
tiff2 = '../../data/SAR/sentinel-1_GRD_VH_2.tif'
# Open the files as rasterio objects
src_files_to_mosaic = []
for path in [tiff1, tiff2]:
src = rasterio.open(path)
src_files_to_mosaic.append(src)Mosaic the rasters and define metadata:
# Mosaic the rasters
mosaic, out_trans = merge(src_files_to_mosaic)
# Copy metadata from the first raster
out_meta = src.meta.copy()
out_meta.update({
"driver": "GTiff",
"height": mosaic.shape[1],
"width": mosaic.shape[2],
"transform": out_trans
})Finally, save the merged result:
with rasterio.open("../../data/SAR/sentinel-1_GRD_VH.tif", "w", **out_meta) as dest:
dest.write(mosaic)Reading Combined Dataset
filename = '../../data/SAR/sentinel-1_GRD_VH.tif'
SAR = rioxarray.open_rasterio(filename)Optionally, sample and plot the result:
sampling = 10
SAR_sampled = SAR.isel(
x=slice(None, None, sampling),
y=slice(None, None, sampling)
)
raster_plotting.plot_raster_data(SAR_sampled.x, SAR_sampled.y, SAR_sampled[0], vmax=400)
Accessing Multiple Items
The Planetary Computer platform also provides methods for retrieving multiple data items by defining a search query.

from pystac_client import Client
import planetary_computer as pc
# Search against the Planetary Computer STAC API
catalog = Client.open(
"https://planetarycomputer.microsoft.com/api/stac/v1",
modifier=planetary_computer.sign_inplace,
)
# Define your area of interest
aoi = {
"type": "Polygon",
"coordinates": [
[
[-78, 5],
[-76.5, 5],
[-76.5, 8.5],
[-78, 8.5],
[-78, 5]
]
]
}
# Define your temporal range
daterange = {"timestamp": "2021-04-22"}
# Define your search with CQL2 syntax
search = catalog.search(filter_lang="cql2-json", filter={
"op": "and",
"args": [
{"op": "s_intersects", "args": [{"property": "geometry"}, aoi]},
{"op": "=", "args": [{"property": "datetime"}, daterange]},
{"op": "=", "args": [{"property": "collection"}, "cop-dem-glo-30"]}
]
})
items = search.item_collection()
print("Number of items found:", len(items))Number of items found: 10
Now, we can load the DEM tiles that we want to select, in this case we load all of them:
dem_arrays = []
for i, item in enumerate(items):
print(f"Loading item {i+1}/{len(items)}: {item.id}")
# open the DEM tile
dem_tile = rioxarray.open_rasterio(item.assets["data"].href)
# CRS information
dem_tile_crs = dem_tile.rio.write_crs("EPSG:4326", inplace=False)
# append to list
dem_arrays.append(dem_tile_crs)
print(f"Loaded {len(dem_arrays)} DEM tiles")Loading item 1/10: Copernicus_DSM_COG_10_N08_00_W078_00_DEM
Loading item 2/10: Copernicus_DSM_COG_10_N08_00_W077_00_DEM
Loading item 3/10: Copernicus_DSM_COG_10_N07_00_W078_00_DEM
Loading item 4/10: Copernicus_DSM_COG_10_N07_00_W077_00_DEM
Loading item 5/10: Copernicus_DSM_COG_10_N06_00_W078_00_DEM
Loading item 6/10: Copernicus_DSM_COG_10_N06_00_W077_00_DEM
Loading item 7/10: Copernicus_DSM_COG_10_N05_00_W078_00_DEM
Loading item 8/10: Copernicus_DSM_COG_10_N05_00_W077_00_DEM
Loading item 9/10: Copernicus_DSM_COG_10_N04_00_W078_00_DEM
Loading item 10/10: Copernicus_DSM_COG_10_N04_00_W077_00_DEM
Loaded 10 DEM tiles
And finally, combine all tiles into a single dataset:
# Combine all DEM tiles into a single xarray DataArray
print("Combining DEM tiles...")
combined_dem = xr.combine_by_coords(dem_arrays)
print(f"Combined DEM shape: {combined_dem.shape}")
print(f"Combined DEM bounds: x({combined_dem.x.values.min():.4f}, {combined_dem.x.values.max():.4f}), y({combined_dem.y.values.min():.4f}, {combined_dem.y.values.max():.4f})")
combined_dem;Combining DEM tiles...
Combined DEM shape: (1, 18000, 7200)
Combined DEM bounds: x(-78.0000, -76.0003), y(4.0003, 9.0000)



