Sentinel-2 Indices: The Big Cheat Sheet (Formulas, Uses, and Pitfalls)
2025-09-22 · 7 min read · Sentinel-2 · Indices · NDVI · NDRE · NBR · NDMI · NDVI vs NDRE · Water Indices · Snow Indices · Urban Indices · B8 vs B8A · Formulas

TL;DR: This is a copy-ready list of remote sensing indices that work well on Sentinel-2. Formulas assume reflectance scaled to 0–1 (divide by 10,000 if you ingest L1C/L2A integer DN). Prefer L2A (BOA) for cross-date analytics; reach for L1C (TOA) when correction struggles (heavy aerosols, very low sun, snow). Mind the B8 vs B8A choice (wide vs narrow NIR) and keep your grid/resampler consistent across time.
Before you copy–paste
- Band naming (Sentinel-2 MSI). 10 m: B2, B3, B4, B8 · 20 m: B5, B6, B7, B8A, B11, B12 · 60 m: B1, B9, B10. B8 is the wide NIR (842 nm @ 10 m); B8A is the narrow NIR (865 nm @ 20 m).
- B8 vs B8A. Use B8 for standard NDVI/EVI2 at 10 m. Use B8A for red-edge-leaning indices or when you want closer alignment to Landsat’s NIR (~865 nm). Don’t mix them in one time series without re-tuning thresholds.
- Scaling (read me). Sentinel-2 L1C (TOA) and L2A (BOA) are distributed as reflectance already (not radiance), but the pixel values in SAFE/JP2 are integers scaled by 10 000. Many libraries/tileservers auto-convert to float reflectance 0–1 for you. If you ingest raw SAFE/JP2 yourself, convert with
reflectance = DN / 10000.0
before using indices that include constants (e.g., EVI2, OSAVI, WI2015). For simple ratios/differences where both terms share the same units, multiplicative scaling cancels (details below). - Masks. You’ll get cleaner time series if you mask cloud/shadow/snow (SCL from L2A, or your preferred QA).
- BRDF (bidirectional reflectance distribution function). Low sun and view geometry can nudge indices. Be consistent with season/time, or use BRDF-aware methods if you need cross-season comparability.
- SRFs (spectral response functions — the per-band sensitivity curves). S2A/S2B/S2C differ slightly (nm-level); ESA cross-calibration keeps them interchangeable for most workflows. If you rely on very narrow spectral features, consider SRF-convolving external spectra.
Vegetation / canopy vitality
Index | Formula (Sentinel-2) | Why/When |
---|---|---|
NDVI | (B8 - B4) / (B8 + B4) | Classic vigor/greenness at 10 m. |
EVI2 (Jiang 2008) | 2.5 * (B8 - B4) / (B8 + 2.4*B4 + 1) | NDVI alternative that dampens soil/background; no Blue needed. |
NDRE | (B8A - B5) / (B8A + B5) | Red-edge vitality; sensitive in dense canopies. Swap B5→B6/B7 to probe deeper. |
NIRv | B8 * ((B8 - B4) / (B8 + B4)) | Links to GPP proxies; robust with B8 at 10 m. |
ClRE (chlorophyll proxy) | (B6 - B5) / (B6 + B5) | Simple red-edge contrast (qualitative). |
OSAVI (Rondeaux 1996) | (1.16) * (B8 - B4) / (B8 + B4 + 0.16) | Soil-adjusted NDVI; steadier over sparse canopies/bright soils. |
GCI (Gitelson 2003) | (B8 / B3) - 1 | “Green Chlorophyll” proxy; simple NIR/Green ratio. |
MTCI (Dash & Curran 2004) | (B6 - B5) / (B5 - B4) | Chlorophyll/Red-edge gradient (qualitative on S2). |
VARI (Gitelson 2002) | (B3 - B4) / (B3 + B4 - B2) | Visible-only greenness; handy when NIR is unreliable or missing. |
B8 or B8A here? NDVI/EVI2: use B8 (10 m). Red-edge indices: prefer B5/B6/B7 with B8A (narrow NIR) for consistency; resample 20→10 m if you need pixel alignment.
Moisture & drought
Index | Formula | Why/When |
---|---|---|
NDMI (Gao-style on S2) | (B8 - B11) / (B8 + B11) | Vegetation moisture; SWIR1 is sensitive to water content. |
MSI | B11 / B8 | Simple moisture stress ratio (higher = drier). |
NDWI (McFeeters 1996) | (B3 - B8) / (B3 + B8) | “Green vs NIR” flavor; flags water/veg moisture contrasts. |
NDWI (Gao 1996) | (B8 - B11) / (B8 + B11) | Same algebra as NDMI on S2; name varies in literature—pick one and stay consistent. |
Burn severity & char
Index | Formula | Why/When |
---|---|---|
NBR (USGS/USFS) | (B8 - B12) / (B8 + B12) | Post-fire severity; SWIR2 is very responsive to char/ash. |
NBR2 (USGS) | (B11 - B12) / (B11 + B12) | Moisture/thermal sensitivity useful in burn recovery. |
dNBR (USGS/USFS) | NBR_pre - NBR_post | Severity change metric from before/after scenes. |
BAI | 1 / ((0.1 - B4)^2 + (0.06 - B8)^2) | Burn scar highlight; sensitive to noise and calibration. |
Water detection & turbidity
Index | Formula | Why/When |
---|---|---|
MNDWI (Xu 2006) | (B3 - B11) / (B3 + B11) | Urban/wetland water extraction; SWIR suppresses built-up/sediments. |
AWEIsh (Feyisa 2014) | B2 + 2.5*B3 - 1.5*(B11 + B12) - 0.25*B8 | Shadow-robust water index (“sh” variant). |
AWEInsh (Feyisa 2014) | 4*(B3 - B11) - (0.25*B8 + 2.75*B12) | Non-shadow variant. |
WI2015 (Fisher 2016) | 1.7204 + 171*(B2 + B3 + B4) - 3*(B2*B3) - 1.8*(B2*B4) - 48*(B3*B4) - 0.8*(B8*B11) | Empirical; helps in complex scenes (urban/shadow). |
Turbidity proxy | B3 / B2 | Green/Blue ratio rises with suspended matter (qualitative). |
Snow & ice
Index | Formula | Why/When |
---|---|---|
NDSI (Hall 1995) | (B3 - B11) / (B3 + B11) | Snow vs land (Green vs SWIR1). |
NDSII (ice) | (B3 - B12) / (B3 + B12) | Helps separate snow/ice and wet impurities (qualitative). |
Urban & bare soil
Index | Formula | Why/When |
---|---|---|
NDBI | (B11 - B8) / (B11 + B8) | Built-up vs vegetation. |
IBI | (NDBI - NDVI) / (NDBI + NDVI) | Dampens vegetation influence. |
SAVI (Huete 1988) | (1.5) * (B8 - B4) / (B8 + B4 + 0.5) | Vegetation with soil adjustment (L=0.5). |
BSI | ((B11 + B4) - (B8 + B2)) / ((B11 + B4) + (B8 + B2)) | Highlights bright bare soils; separates from veg & water. |
BI (brightness idx) | sqrt( (B4^2 + B11^2) / 2 ) | Large on bright bare ground (qualitative). |
Practical tips that save time
- Pick one grid and resampler for the whole project (e.g., bring 20 m → 10 m once). Use bilinear/cubic for reflectance, nearest for masks.
- Clamp divisions to avoid NaNs/Inf: e.g.,
idx = num / max(den, 1e-6)
. - Season consistency beats micro-tweaks. If you compare across seasons/latitudes, expect BRDF/illumination to matter.
- Cross-sensor warning. Landsat OLI NIR (~865 nm) behaves more like Sentinel-2 B8A than B8. If you port thresholds from Landsat, either use B8A (resampled) or re-validate when using B8.
FAQ
›Do I need L2A (BOA) for indices, or is L1C (TOA) fine?
For cross-date analytics, L2A is the safer default because it reduces illumination and aerosol effects. If L2A is unstable in your season (e.g., heavy smoke, very low sun), L1C can be more predictable. Just keep that choice consistent across the series.
›Should I use B8 or B8A in my index?
Use B8 (10 m) for NDVI/EVI2 at parcel scale. Use B8A (20 m) with red-edge bands (B5/B6/B7) when you want a narrower NIR or closer alignment to Landsat’s NIR (~865 nm). Avoid mixing them without re-tuning thresholds.
›Do I always need to divide by 10,000?
Sentinel-2 L1C (TOA) and L2A (BOA) are delivered as quantized reflectance with a scale factor of 10,000.
If your reader/API already returns floats in 0–1, you’re set. If you read SAFE/JP2 yourself, divide DN by 10,000.
For normalized-difference forms like (A − B) / (A + B)
the multiplicative scale cancels if both bands use the
same scale; however, indices with additive constants (e.g., EVI2, OSAVI, WI2015) expect 0–1 inputs.
Best practice: convert to 0–1 first.
›What changed with ESA processing baselines and 'harmonized' data?
Since Processing Baseline 04.00, ESA introduced a small radiometric offset in S2 products to better
handle negative/near-zero reflectance after correction. Practically, some L1C/L2A bands carry an ADD_OFFSET
(e.g., ±1000 in DN units) in metadata; you subtract it, then apply the usual /10000
scale. To simplify life,
some providers publish harmonized collections that remove the offset and align older/newer scenes—e.g.,
Google Earth Engine’s “Sentinel-2 Harmonized” collections. If you work directly from SAFE, honor the offset; if you use a
harmonized feed, it’s already handled.
References: ESA Sentinel-2 Processing Baselines & Collection-1 notes; Google Earth Engine S2 (Harmonized) docs.
›Why do some moisture indices have different names but similar formulas?
Naming varies (e.g., NDMI vs NDWI–Gao), but on Sentinel-2 many reduce to
(NIR − SWIR1) / (NIR + SWIR1)
. Pick one name, document it, and stay consistent.
›My index map has holes or seams—what did I miss?
Check cloud/shadow/snow masks, confirm your resampling (20→10 m once), and ensure you applied the scale factor (divide DN by 10,000 and subtract any offsets when reading SAFE). Low sun/BRDF differences can also nudge values.
ClearSKY in practice
ClearSKY delivers Sentinel-2–style stacks at 10 m with optional ready-to-use indices in one go. Add indices via the Bandnames
field (e.g., B8,B4,[B8_B4]
for NDVI) and receive aligned layers in a single GeoTIFF or cloud-optimized output. If you want red-edge indices, we’ll resample the 20 m inputs (B5/B6/B7/B8A) to your target grid consistently. For timeliness, you can request Level-1C–style inputs; for comparability, Level-2A–style. Either way, keep that choice consistent within a time series.