Skip to content

Landsat 8-9 Level-2

Available now Collection id landsat-ot-l2. Aliases include landsat-c2-l2 (Earth Search and Planetary Computer, here limited to Landsat 8 and 9) and LOTL2 (Sentinel Hub), matched without regard to case.

Landsat 8 and 9 each carry the Operational Land Imager (OLI, or OLI-2 on Landsat 9), with nine reflective bands, and the Thermal Infrared Sensor (TIRS, TIRS-2), with two thermal bands. USGS processes their scenes to Collection 2 Level-2: surface reflectance for the seven OLI bands below 2.3 µm, and surface temperature from TIRS band 10, plus quality layers.

satellitedata.net finds scenes through Element 84’s Earth Search landsat-c2-l2 index and reads the files from the USGS usgs-landsat bucket in AWS us-west-2. That bucket is requester-pays: the API pays for its own reads, and asset href values in items are s3://usgs-landsat/... URLs, so a client that reads them directly pays its own request charges. Earth Search’s index also holds Landsat 4, 5 and 7; this collection returns Landsat 8 and 9 only. Item ids are USGS product ids, for example LC09_L2SP_198032_20260825_02_T1.

Mission references: USGS pages on Landsat 8, Landsat 9, Collection 2 Level-2 science products and quality assessment bands.

Satellites Landsat 8 (launched February 2013) and Landsat 9 (launched September 2021); item platform is landsat-8 or landsat-9
Spatial resolution 30 m for every band in Level-2; thermal is acquired at 100 m and resampled to 30 m
Revisit 16 days per satellite, 8 days with both
Swath 185 km
Tiling WRS-2 path and row; one item per scene, such as path 198 row 032 (grid:code = WRS2-198032)
Processing level Collection 2 Level-2: surface reflectance (LaSRC) and surface temperature
Temporal extent in the API From 18 March 2013, as the live collection document reports
Zoom range for tiles 7 to 14
Credit line Landsat data courtesy of the U.S. Geological Survey

Spectral and thermal bands, with the wavelengths and bandwidths Earth Search publishes in each item’s eo:bands:

Band Common name Earth Search asset Also accepted Centre (µm) Bandwidth (µm) Resolution Type Scale Offset Nodata
SR_B1 coastal coastal B01 0.44 0.02 30 m uint16 0.0000275 −0.2 0
SR_B2 blue blue B02 0.48 0.06 30 m uint16 0.0000275 −0.2 0
SR_B3 green green B03 0.56 0.06 30 m uint16 0.0000275 −0.2 0
SR_B4 red red B04 0.65 0.04 30 m uint16 0.0000275 −0.2 0
SR_B5 nir08 nir08 B05 0.87 0.03 30 m uint16 0.0000275 −0.2 0
SR_B6 swir16 swir16 B06 1.61 0.09 30 m uint16 0.0000275 −0.2 0
SR_B7 swir22 swir22 B07 2.20 0.19 30 m uint16 0.0000275 −0.2 0
ST_B10 lwir11 lwir11 B10 10.9 0.59 30 m (100 m native) uint16 0.00341802 149.0 0

ST_B10 converts to kelvin, not reflectance. OLI’s panchromatic band 8 and cirrus band 9, and TIRS band 11, are not in Level-2; they are in Level-1, which is coming later.

Quality and surface temperature auxiliary layers:

Layer Earth Search asset Also accepted Content Type Scale Offset Nodata
QA_PIXEL qa_pixel BQA Pixel quality bit field (bits) uint16 none 0 1
QA_RADSAT qa_radsat Saturation and terrain occlusion bit field (bits) uint16 none 0 none
SR_QA_AEROSOL qa_aerosol Aerosol retrieval quality bit field uint8 none 0 1
ST_QA qa lwir_qa Surface temperature uncertainty, K int16 0.01 0 −9999
ST_CDIST cdist Distance to the nearest cloud, km int16 0.01 0 −9999
ST_ATRAN atran Atmospheric transmittance int16 0.0001 0 −9999
ST_EMIS emis Emissivity of band 10 int16 0.0001 0 −9999
ST_EMSD emsd Emissivity standard deviation int16 0.0001 0 −9999
ST_DRAD, ST_URAD, ST_TRAD drad, urad, trad Downwelled, upwelled and thermal radiance, W/(m² sr µm) int16 0.001 0 −9999

Every layer is 30 m. In POST /v1/process, a band resolves by native name, common name, asset name or alias, without regard to case, with one gap: the three radiance layers and ST_EMSD resolve by asset name only (drad, urad, trad, emsd). The GeoTIFF’s band descriptions are the asset names.

Landsat has one near-infrared band, SR_B5, so nir fails here with unknown-band and a hint to use nir08. That makes a request written with nir08 work on Sentinel-2 and Landsat alike.

Some scenes are processed to surface reflectance only, marked L2SR in the id (LC09_L2SR_086110_20261011_02_T2) and landsat:correction: L2SR in the properties, instead of L2SP. USGS does this when it lacks the inputs for surface temperature. These scenes have no lwir11 and none of the ST layers, and asking for one answers 422 unknown-band. Prefer lwir11 over ST_B10 in code: the common name will survive renaming in a later Landsat collection.

surface reflectance = DN × 0.0000275 − 0.2
surface temperature (K) = DN × 0.00341802 + 149.0

The same scale and offset apply to Landsat 8 and 9 and to every date: Landsat has no baseline offset like Sentinel-2’s, so harmonize: "offset_removed" changes nothing here.

units Spectral bands lwir11 Sample type
REFLECTANCE (default) reflectance kelvin FLOAT32, nodata NaN
DN stored integers, with scale and offset in the GeoTIFF stored integers UINT16, nodata 0
  • With REFLECTANCE the ST auxiliary layers get their scale too: ST_CDIST in km, ST_QA in K, ST_ATRAN and ST_EMIS as fractions. The QA bit fields always come back as stored.
  • clipNegative: true sets reflectance below zero to zero. It has no effect with DN, which is never negative.
  • output.sampleType, if given, must be FLOAT32 for REFLECTANCE and UINT16 for DN.
  • KELVIN and CELSIUS as separate units are coming later.

Valid surface reflectance DN run from 7,273 (reflectance 0) to 43,636 (reflectance 1). The true-color preset stretches DN 7,273 to 18,182, which is reflectance 0 to 0.3.

Items carry eo:cloud_cover for the whole scene and landsat:cloud_cover_land for its land part. Filter scenes on eo:cloud_cover as for Sentinel-2.

QA_PIXEL is a 16-bit field from the CFMask algorithm. Test a bit with (qa >> bit) & 1, and a two-bit confidence with (qa >> bit) & 3.

Bit Meaning when set
0 Fill, no data
1 Dilated cloud
2 Cirrus (high confidence)
3 Cloud
4 Cloud shadow
5 Snow
6 Clear: set when neither the cloud bit nor the dilated cloud bit is set
7 Water
8-9 Cloud confidence
10-11 Cloud shadow confidence
12-13 Snow and ice confidence
14-15 Cirrus confidence

Confidence values: 0 none, 1 low, 2 medium, 3 high. For snow and ice, and for cirrus, USGS uses 0 none, 1 low and 3 high (2 is reserved). Two values come up often: 21824 is clear land and 21952 is clear water, both with low confidence in every class.

A strict clear-pixel test keeps pixels where bit 6 is set and bits 0 to 4 are clear:

import numpy as np
clear = ((qa >> 6) & 1).astype(bool) & ((qa & 0b11111) == 0)
Bit Meaning when set
0 to 6 Band 1 to band 7 saturated (bit 0 is band 1)
7 Not used
8 Band 9 saturated
9-10 Not used
11 Terrain occlusion
12-15 Not used

A pixel saturated in a band you use holds a clipped value; drop it from quantitative work.

Lean v1 applies no pixel cloud mask: tiles and previews show every pixel of the scenes they mosaic, and processing.cloudMask is rejected. The unified cloud mask, built from QA_PIXEL with a choice of confidence level, is planned.

  • Landsat 8 from March 2013 and Landsat 9 from late 2021, onwards, as Earth Search indexes them.
  • Both Tier 1 and Tier 2 scenes are in the collection. Tier 1 meets USGS’s geometric accuracy requirement; Tier 2 does not, often because of cloud. For Tier 1 only, add "landsat:collection_category": {"eq": "T1"} to query.
  • New scenes appear once USGS publishes the Level-2 product. The example scene of 25 August 2026 was in the index the next day.
  • Before relying on a period, run /v1/search for your area and dates.

These properties work in the query extension:

Property Example Notes
eo:cloud_cover {"eo:cloud_cover": {"lte": 20}} Whole-scene cloud percentage
platform {"platform": {"in": ["landsat-9"]}} Only landsat-8 and landsat-9 match in this collection
landsat:wrs_path, landsat:wrs_row {"landsat:wrs_path": {"eq": "198"}, "landsat:wrs_row": {"eq": "032"}} Strings with leading zeros
landsat:collection_category {"landsat:collection_category": {"eq": "T1"}} T1 or T2

From GET /v1/presets, the web map’s recipes for this collection:

Preset Assets Stretch
true-color red, green, blue DN 7,273 to 18,182, reflectance 0 to 0.3
false-color nir08, red, green DN 7,273 to 21,818, reflectance 0 to 0.4
ndvi nir08, red (b1 - b2) / (b1 + b2 - 14545.45), −0.2 to 0.8 on rdylgn

The NDVI expression removes both −0.2 offsets (2 × 7,272.7 DN) from the denominator, so Landsat NDVI matches Sentinel-2’s.

Tiles exist from zoom 7 to 14. Outside that range a tile answers 400 zoom-out-of-range.

Routes marked anonymous need no key; the others send X-API-Key. The area is west of Tarragona, Spain, on WRS-2 path 198, row 032.

Terminal window
curl -s -X POST https://api.satellitedata.net/v1/search \
-H "X-API-Key: $SDN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"collections": ["landsat-ot-l2"],
"bbox": [0.7, 40.7, 0.8, 40.8],
"datetime": "2026-08-01T00:00:00Z/2026-08-31T23:59:59Z",
"limit": 10,
"query": {"eo:cloud_cover": {"lte": 20}}
}'

Anonymous.

Terminal window
curl -s https://api.satellitedata.net/v1/collections/landsat-ot-l2/items/LC09_L2SP_198032_20260825_02_T1

A Landsat 5 or 7 id under this collection answers 404 not-found.

Terminal window
curl -s -o preview.jpg \
-H "X-API-Key: $SDN_API_KEY" \
"https://api.satellitedata.net/v1/collections/landsat-ot-l2/items/LC09_L2SP_198032_20260825_02_T1/preview.jpg?preset=false-color&max_size=256"

The TileJSON is anonymous; the tiles need the key.

Terminal window
curl -s "https://api.satellitedata.net/v1/tiles/ndvi/WebMercatorQuad/tilejson.json?collection=landsat-ot-l2&datetime=2026-08-01/2026-08-31&maxCloudCoverage=40"
{
"tilejson": "3.0.0",
"name": "ndvi",
"attribution": "Landsat data courtesy of the U.S. Geological Survey",
"tiles": ["https://api.satellitedata.net/v1/tiles/ndvi/WebMercatorQuad/{z}/{x}/{y}.png?collection=landsat-ot-l2&datetime=2026-08-01%2F2026-08-31&maxCloudCoverage=40"],
"minzoom": 7,
"maxzoom": 14
}

(Shortened.) One tile at zoom 11:

Terminal window
curl -s -o tile.png -H "X-API-Key: $SDN_API_KEY" \
"https://api.satellitedata.net/v1/tiles/ndvi/WebMercatorQuad/11/1027/767.png?collection=landsat-ot-l2&datetime=2026-08-01%2F2026-08-31&maxCloudCoverage=40"

For a MapLibre page, see the Quickstart; set the collection to landsat-ot-l2 and start at zoom 7 or more.

red, nir08 and lwir11 over a 2 km box, as float32: reflectance for the first two, kelvin for the third.

Terminal window
curl -s -L -X POST https://api.satellitedata.net/v1/process \
-H "X-API-Key: $SDN_API_KEY" \
-H "Content-Type: application/json" \
-o landsat.tif \
-d '{
"input": {
"bounds": {"bbox": [0.73815, 40.71096, 0.76185, 40.72904]},
"data": [{
"type": "landsat-ot-l2",
"dataFilter": {"timeRange": {"from": "2026-08-01T00:00:00Z", "to": "2026-08-31T23:59:59Z"}}
}]
},
"bands": ["red", "nir08", "lwir11"],
"output": {"width": 200, "height": 150, "crs": "EPSG:32631"}
}'

Without mosaickingOrder the most recent scenes in the month come first. Add "maxCloudCoverage": 20 and "mosaickingOrder": "leastCC" to the dataFilter for the clearest scene instead. If the chosen scene is an L2SR one, the request fails with unknown-band for lwir11.

The same request with "processing": {"units": "DN", "harmonize": "none"} in the data source returns UINT16 DN, with the scale and offset written into the GeoTIFF for GDAL and rasterio.

The same body as for Sentinel-2, with a Landsat scene id:

Terminal window
curl -s -i -X POST https://api.satellitedata.net/v1/process/jobs \
-H "X-API-Key: $SDN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"bounds": {"bbox": [0.63147, 40.62956, 0.86853, 40.81044]},
"data": [{
"type": "landsat-ot-l2",
"dataFilter": {"ids": ["LC09_L2SP_198032_20260825_02_T1"]}
}]
},
"bands": ["blue", "green", "red", "nir08", "swir16", "swir22"],
"output": {"width": 3000, "height": 3000, "crs": "EPSG:32631"}
}'
curl -s -H "X-API-Key: $SDN_API_KEY" https://api.satellitedata.net/v1/process/jobs/$JOB_ID

Poll until status is done, then download each files[].url within the hour.