What Is GRIB2?
GRIB — General Regularly-distributed Information in Binary — is the binary format standard used by nearly every major numerical weather prediction (NWP) center for storing and distributing gridded meteorological data. Defined by the World Meteorological Organization (WMO) as FM 92 GRIB, it is the format in which ECMWF, NOAA, DWD (Germany), the Met Office (UK), and Météo-France distribute their operational model output to meteorological services worldwide.
GRIB Edition 2 (GRIB2) — introduced in 2003 and now the dominant version — added support for JPEG2000 and PNG compression, expanded grid type options, and a more systematic product classification system. The earlier GRIB Edition 1 (GRIB1) still appears in legacy datasets but is being phased out.
Why GRIB2 Instead of NetCDF?
Both GRIB2 and NetCDF-4 store gridded array data with metadata. The difference is operational:
- GRIB2 is optimized for operational meteorology: compact, single-field messages that can be efficiently extracted one parameter at a time, supporting the real-time streaming of forecast data
- NetCDF-4 is optimized for scientific analysis: multi-variable self-describing files with rich CF metadata, better for long archival runs and complex multi-dimensional analysis
- ECMWF distributes its HRES and ENS forecast output in GRIB2; the ERA5 reanalysis is available in both GRIB2 (via MARS) and NetCDF-4 (via CDS)
GRIB2 Message Structure
A GRIB2 file is a concatenation of independent messages — one message per meteorological field. Each message consists of nine sections:
| Section | Name | Contents |
|---|---|---|
| 0 | Indicator | Magic bytes "GRIB", edition number (2), total message length |
| 1 | Identification | Originating center, reference time, significance of reference time |
| 2 | Local Use | Center-specific data (optional) |
| 3 | Grid Definition | Grid type, number of points, coordinate values |
| 4 | Product Definition | Parameter, level type, level value, forecast step |
| 5 | Data Representation | Packing method (simple, JPEG2000, PNG, spectral) |
| 6 | Bitmap | Optional bitmask for undefined/land-sea mask points |
| 7 | Data | Compressed data values |
| 8 | End | Literal "7777" terminating the message |
A single 00Z GFS run (global forecast to 384 hours at 0.25° resolution) produces thousands of GRIB2 messages — each field (temperature, wind U, wind V, geopotential height) at each level and each forecast step is a separate message appended to the file.
Key GRIB2 Parameters and Identifiers
GRIB2 uses a parameter table system to identify meteorological variables. The key identifiers:
# eccodes keys for a typical GRIB2 message
shortName = "2t" # 2-metre temperature
name = "2 metre temperature"
typeOfLevel = "heightAboveGround"
level = 2 # metres above ground
dataDate = 20240315 # YYYYMMDD
dataTime = 0000 # HHMM UTC
stepRange = "0" # analysis (step 0) or "6" (6-hour forecast)
gridType = "regular_ll" # regular lat/lon grid
Ni = 1440 # points in longitude direction
Nj = 721 # points in latitude direction
latitudeOfFirstGridPointInDegrees = 90.0
longitudeOfFirstGridPointInDegrees = 0.0
jDirectionIncrementInDegrees = 0.25
iDirectionIncrementInDegrees = 0.25
packingType = "grid_jpeg" # JPEG2000 compression
The GRIB2 parameter tables are maintained by WMO — Table 4.2 lists all standard parameters organized by discipline (meteorological, hydrological, oceanographic, space, etc.).
Working with GRIB2 in Python
cfgrib (xarray backend) is the highest-level interface:
import xarray as xr
# Open a GRIB2 file as xarray Dataset
# cfgrib automatically selects compatible messages
ds = xr.open_dataset("gfs_0p25_2024031500.grib2",
engine="cfgrib",
backend_kwargs={"filter_by_keys": {"typeOfLevel": "isobaricInhPa",
"shortName": "t"}})
print(ds)
# Dimensions: latitude (721), longitude (1440), isobaricInhPa (37)
# Temperature at 500 hPa over Europe
t500 = ds["t"].sel(isobaricInhPa=500)
europe = t500.sel(latitude=slice(71, 35), longitude=slice(-10, 40))
print(f"Mean T500 over Europe: {float(europe.mean()):.2f} K")
eccodes-python (low-level, direct access to all GRIB2 keys):
import eccodes
# Iterate over all messages in a GRIB2 file
with open("forecast.grib2", "rb") as f:
while True:
msg = eccodes.codes_grib_new_from_file(f)
if msg is None:
break
name = eccodes.codes_get(msg, "name")
level = eccodes.codes_get(msg, "level")
step = eccodes.codes_get(msg, "stepRange")
values = eccodes.codes_get_values(msg) # 1D array of grid values
print(f"{name} level={level} step={step} min={values.min():.2f} max={values.max():.2f}")
eccodes.codes_release(msg)
CDO (Climate Data Operators) for GRIB2 processing:
# Convert GRIB2 to NetCDF
cdo -f nc copy forecast.grib2 forecast.nc
# Extract 2m temperature only
cdo select,shortName=2t forecast.grib2 t2m.grib2
# Extract a specific pressure level
cdo select,typeOfLevel=isobaricInhPa,level=500 forecast.grib2 t500.grib2
# Compute 24-hour forecast minus analysis (anomaly)
cdo sub fc024.grib2 analysis.grib2 anomaly.grib2
# Regrid from 0.25° to 1°
cdo remapbil,r360x181 gfs_0p25.grib2 gfs_1deg.nc
Major GRIB2 Producers
| Center | Model | Resolution | Coverage |
|---|---|---|---|
| ECMWF | IFS HRES | 0.1° (~9 km) | Global, 10-day |
| ECMWF | ENS (51 members) | 0.2° (~18 km) | Global, 15-day |
| NOAA | GFS | 0.25° (~25 km) | Global, 16-day |
| NOAA | NAM | 3 km | North America |
| DWD | ICON-Global | 0.125° (~13 km) | Global |
| DWD | ICON-EU | 0.0625° (~7 km) | Europe |
| Met Office | UM Global | 0.1° | Global |
| CMA | GRAPES | 0.25° | Global |
ECMWF's HRES is widely considered the world's most accurate NWP model. Raw GRIB2 output is freely available to WMO member state meteorological services; a subset is available publicly via open data portals.
GRIB2 Index Files and Inventory
Because a GRIB2 file is a concatenation of independent messages, tools create index files to enable random access without scanning the entire file:
# wgrib2 — the primary GRIB2 inspection tool
wgrib2 gfs_0p25.grib2 | head -20
# Output: message:offset:date:shortName:level:stepRange
# 1:0:d=2024031500:TMP:2 m above ground:anl
# 2:523144:d=2024031500:UGRD:10 m above ground:anl
# Extract one field by grep and redirect
wgrib2 gfs.grib2 -match ":TMP:500 mb:" -grib t500.grib2
# Create a small extract for a bounding box
wgrib2 gfs.grib2 -small_grib -10:40 35:70 europe_gfs.grib2
GRIB2 Grid Types
Beyond regular lat/lon grids, GRIB2 supports:
| Grid Type | Code | Use Case |
|---|---|---|
| Regular Gaussian | 4 | Spectral models (ECMWF IFS) |
| Lambert Conformal | 30 | North American high-res models (NAM, HRRR) |
| Polar Stereographic | 20 | Arctic/Antarctic models |
| Space View | 90 | Geostationary satellite imagery (EUMETSAT) |
| Mercator | 10 | Oceanic models |
| Rotated Lat/Lon | 1 | Limited-area models with equatorial pole rotation |
The rotated lat/lon grid is particularly common in European regional models — rotating the coordinate system so the equator passes through the domain center minimizes grid distortion.
Related conversions
Frequent conversions across the catalogue: