How to Calculate NDVI in QGIS from Sentinel-2, and the Offset Most Tutorials Miss
Step-by-step NDVI in QGIS with Sentinel-2 L2A bands 8 and 4, the 1,000 offset since 2022 that most tutorials miss, cloud masking with SCL, and styling.

In brief
- To calculate NDVI in QGIS from Sentinel-2 Level-2A data, use band 8 (near-infrared) and band 4 (red), both at 10 m, in the Raster Calculator.
- Since processing baseline 04.00 (January 2022), Sentinel-2 L2A pixel values include an offset of 1,000. Subtract it before you calculate NDVI, or your values will be biased, most visibly over water and shadow.
- The product name tells you the baseline: N0400 or higher means the offset applies. Confirm the value in the product metadata.
- Mask clouds with the scene classification (SCL) band before you trust the result.
Most NDVI tutorials for QGIS were written before 2022, and they divide band 8 minus band 4 by band 8 plus band 4 straight from the file. With current Sentinel-2 data that gives a slightly wrong answer, because ESA added a radiometric offset to Level-2A products. The scale factor cancels out in the NDVI ratio; the offset does not. This walkthrough calculates NDVI correctly, step by step, with free tools. For what the values mean, see NDVI explained.
Step 1: download a Sentinel-2 L2A scene
Open the Copernicus Browser (a free Copernicus Data Space Ecosystem account is needed), search your area, choose Sentinel-2 L2A, and filter by cloud cover. Pick a clear date and download the product. Inside the .SAFE folder, the 10 m bands are under GRANULE, then IMG_DATA, then R10m: you need the files ending _B04_10m.jp2 and _B08_10m.jp2. The 20 m scene classification band, ending _SCL_20m.jp2, is in the R20m folder.
Look at the product name. A part such as N0511 is the processing baseline (here 05.11). Anything from N0400 upwards carries the offset. The exact value is in the product’s MTD_MSIL2A.xml file, as BOA_ADD_OFFSET: for L2A it is −1000 for every band.
Step 2: load the bands and clip to your area
Drag both .jp2 files into QGIS. If you have a boundary for your study area, clip each band first with Raster, then Extraction, then Clip Raster by Mask Layer. Working on a small area makes every later step faster and keeps the colour stretch meaningful.
Step 3: calculate NDVI with the offset removed
Open Raster, then Raster Calculator. Replace the layer names below with yours (QGIS lists them in the Raster Bands box). The expression subtracts 1,000 from each band, then applies the NDVI formula. The division by 10,000 is left out because it cancels in the ratio.
( ("B08_10m@1" - 1000) - ("B04_10m@1" - 1000) )
/
( ("B08_10m@1" - 1000) + ("B04_10m@1" - 1000) )For scenes processed before baseline 04.00 (product names N0300 and similar), drop the “− 1000” terms. Save the output as a GeoTIFF; QGIS writes it as 32-bit floating point, which is what you want for values between −1 and 1.
| Band 4 (red) | Band 8 (NIR) | NDVI | |
|---|---|---|---|
| Raw file values | 1,450 | 2,600 | 0.28 (wrong) |
| After subtracting 1,000 | 450 | 1,600 | 0.56 (correct) |
The illustrative pixel above shows how large the error can be on sparse vegetation and bright soil. Over dense crops the difference is smaller; over water and shadow, where values are low, it is largest. A quick check: compare one pixel against the NDVI layer in the Copernicus Browser for the same date.
Step 4: mask clouds and shadow
Load the SCL band. Its classes include 3 (cloud shadow), 8 and 9 (cloud, medium and high probability) and 10 (thin cirrus). Build a mask that keeps everything else, resample it to 10 m with Raster, then Projections, then Warp, and multiply it with your NDVI layer, or use it to set those pixels to no data. Skipping this step is the most common reason an NDVI map shows “dead vegetation” that is really a cloud edge.
Step 5: style and read the map
In the layer properties choose Singleband pseudocolor with the RdYlGn colour ramp, and set the range from about −0.2 to 0.9 so the colours are comparable between dates. Roughly: below 0 is water, snow or cloud; 0 to 0.2 is bare soil and built-up land; 0.2 to 0.5 is sparse or stressed vegetation; above 0.6 is dense, healthy vegetation. Always compare dates from the same season.
Frequently asked questions
Which Sentinel-2 bands are used for NDVI?
Band 8 (near-infrared, 842 nm) and band 4 (red, 665 nm), both at 10 m resolution.
Do I need to subtract 1000 from Sentinel-2 bands?
For Level-2A products from processing baseline 04.00 onwards (January 2022), yes: the files include an offset of 1,000. Check BOA_ADD_OFFSET in the product metadata.
Why are my Sentinel-2 NDVI values too low or odd over water?
Most often because the offset was not removed, or because clouds and shadow were not masked with the SCL band.
Should I use Level-1C or Level-2A for NDVI?
Level-2A, which is corrected for the atmosphere, so values are comparable between dates.
Get the climate stories that matter, explained, every Sunday.
One email a week: new explainers, data and free tools. No spam, unsubscribe any time.
More from climaRevolt

Google Earth Engine NDVI Time Series: A Sentinel-2 Script with Cloud Score+

EUDR 2026: What the EU Deforestation Regulation Requires from 30 December
