Short answer
gdalinfo is the single fastest way to find out whether a raster is what it claims to be. In one call it reports the driver, dimensions, coordinate reference system, geotransform, corner coordinates, per-band data type and NoData, color interpretation, overviews, internal block size, and metadata. Before any conversion, reprojection, or analysis, run gdalinfo and read it line by line — most raster failures are visible in this output and cost nothing to catch here, versus hours to debug later.
The discipline is simple: never assume a raster's CRS, resolution, or value range. gdalinfo is how you replace assumptions with facts in under a second.
A full read of the output
Run the richer form:
gdalinfo -stats dem.tif
Here is how to interpret the blocks that matter.
Driver and size
Driver: GTiff/GeoTIFF
Size is 10980, 10980
The driver tells you the actual format regardless of file extension — a .tif reported as Driver: GTiff is fine, but a download that reports Driver: HFA/Erdas Imagine despite a .tif name signals a mislabelled file. Size is W, H is in pixels.
Coordinate system
Coordinate System is:
PROJCRS["WGS 84 / UTM zone 31N", ... ID["EPSG",32631]]
The ID["EPSG",32631] at the end is the authoritative answer to "what CRS is this?". If this block reads Coordinate System is: (unknown), the raster has no spatial reference — it will not overlay anything, and you must assign or recover the CRS before use.
Geotransform: Origin and Pixel Size
Origin = (600000.000, 5800020.000)
Pixel Size = (10.000, -10.000)
Origin is the map coordinate of the upper-left corner of the upper-left pixel. Pixel Size is (X, Y); the negative Y is normal because raster rows increase downward (north to south). Read these together:
- Equal magnitudes (10, -10) means square pixels — expected for most analytical rasters.
- Mismatched magnitudes (e.g. 30, -25) means anisotropic pixels, which will distort slope and area calculations unless intended.
- A positive Y pixel size means the raster is stored bottom-up and is often a sign of a broken geotransform.
Corner coordinates
Corner Coordinates:
Upper Left ( 600000.000, 5800020.000) ( 3d 0' 0.00"E, 52d20'...N)
GDAL prints both the native CRS coordinates and their lon/lat equivalent. A fast sanity check: do the lon/lat corners land where you expect on Earth? Corners at (0,0) lon/lat for a dataset that should be in the Alps means the georeferencing is wrong.
Bands, data type, NoData, statistics
Band 1 Block=512x512 Type=Float32, ColorInterp=Gray
Minimum=210.4, Maximum=2104.9, Mean=812.3, StdDev=341.0
NoData Value=-9999
Type=Float32confirms you are not about to truncate continuous data by casting to Byte.Block=512x512is the internal tiling.Block=W x 1means strip storage — bad for streaming and slow for windowed reads.NoData Value=-9999must be present for DEMs and masked imagery. If it is missing, the statistics line was computed over fill pixels and the Minimum/Mean are meaningless.- Statistics only appear with
-stats(or if pre-computed). A Minimum of -9999 next to a missing NoData declaration is the classic "NoData is leaking into the data" symptom.
Useful flags
-stats— compute and print min/max/mean/stddev (writes a.aux.xmlsidecar to cache them).-hist— per-band histogram, useful for spotting bimodal value distributions or saturated tails.-mm— force a min/max scan without full statistics.-checksum— a per-band checksum, ideal for verifying a format-only conversion preserved values.-json— structured output for automation (see below).-nogcp -nomd— suppress ground control points and metadata when you only want the geometry summary.-proj4/-wkt_format WKT2— control how the CRS is printed.
Worked example: a CI gate in JSON
Scraping human text is fragile. Use JSON:
gdalinfo -json -stats dem.tif > info.json
Then assert the things that must be true with jq:
# CRS must be UTM 31N
jq -e '.stac.["proj:epsg"] == 32631' info.json
# NoData must be declared on band 1
jq -e '.bands[0].noDataValue != null' info.json
# Pixel size must be 10 m square
jq -e '.geoTransform[1] == 10 and .geoTransform[5] == -10' info.json
geoTransform in JSON is the six-element array [originX, pixelWidth, rowRotation, originY, columnRotation, pixelHeight]. Elements [2] and [4] are rotation terms; for a north-up raster they must both be 0 — a non-zero value means the raster is rotated/skewed and most tools will mishandle it.
Common pitfalls and why they happen
- Trusting the file extension over the driver line. Vendors and download portals frequently mislabel containers; the
Driver:line is ground truth. - Reading statistics without checking NoData. GDAL caches stats in a
.aux.xmlfile; if that was computed before NoData was set, the cached Mean is wrong. Delete the sidecar and re-run-statsafter assigning NoData. - Ignoring block size. A raster that loads fine in QGIS can be unusably slow behind a tile server because it is strip-stored. The
Block=field warns you before deployment. - Missing overviews. No
Overviews:line under a band means zoomed-out views will read full resolution. Add them withgdaladdofor any raster used interactively. - Assuming north-up. Non-zero rotation terms in the geotransform are rare but catastrophic if missed, because area and slope tools silently assume an axis-aligned grid.
Validation checklist
Before a raster enters a pipeline, confirm from gdalinfo:
- Driver matches the expected format.
- CRS has an EPSG identity, not "(unknown)".
- Pixel size is the resolution you expect, with the correct sign and square where it should be.
- Rotation terms are zero.
- NoData is declared and is not inside the valid value range.
- Data type matches the analysis (Float for continuous, integer for classified).
- Block size is tiled and overviews exist for interactive use.
- Corner lon/lat land in the right part of the world.
Bathyl perspective
We make gdalinfo -json the first step of every raster ingest, wired into a CI check that fails the build when CRS, NoData, or pixel size drift from spec. Catching a mislabelled CRS or a leaking NoData value at ingest is cheap; catching it after it has propagated into a published map is not.
Related reading
- gdal_translate for Raster Conversion
- gdalwarp for Raster Reprojection
- GDAL Build VRT Explained
- Shapefile vs GeoPackage vs GeoJSON
- Spatial data products