Upload a GeoTIFF and get an instant summary — dimensions, resolution, band count, CRS, NoData, and per-band min/max/mean. Free, runs entirely in your browser: the file never leaves your computer.
Published
September 6, 2026
Upload a .tif/.tiff file and get an instant summary of what’s actually in it — size, resolution, bands, coordinate reference system, and the value range of each band.
Tip
Private by design. Your file is processed entirely in your browser (Python via WebAssembly) — it’s never uploaded to any server, including ours. Nothing to configure, nothing to trust: the code never gets the chance to see your data.
The code itself isn’t shown here — it’s a fixed, non-editable summary using rasterio underneath. Want to see the same statistics built up step by step, in Python and R? Read First Look at a Raster File.
// "Load example" writes a small synthetic raster directly, instead of// decoding a pre-made GeoJSON string the way every vector tool's// example does (see geospatial-file-inspector.qmd) — a GeoTIFF is a// binary format, so the natural equivalent is a dedicated Python cell// that builds one with `rasterio` on demand, not a string constant.generateExample =async () => {awaitwindow.WebGeoDS.CodeCell.find("raster-generate-example-py").run();}
loadExampleButton = {const button =document.createElement("button"); button.className="webgeods-panel-btn"; button.dataset.variant="outline"; button.textContent="📋 Load example"; button.onclick=async () => { mutable uploadBusy =true; mutable uploadStatus ="⌛ Loading example...";try {awaitgenerateExample(); mutable uploadStatus ="⌛ Inspecting...";awaitautoInspect(); mutable uploadStatus ="✓ example data loaded — ready for all the cells below."; } finally { mutable uploadBusy =false; } };return button;}
// Downloads the computed summary itself (JSON) rather than a// modified copy of the raster — unlike the vector tools, there's no// natural "enriched" raster to hand back (the stats are page-level// scalars, not a per-pixel value to overlay), so a machine-readable// report of what's on screen is the closest equivalent.downloadButton = {const button =document.createElement("button"); button.className="webgeods-panel-btn"; button.dataset.variant="outline"; button.textContent="⬇ Download"; button.onclick= () => {const data = pyInspect?.summary;if (!data) return;const base = WebGeoDS.Upload.baseName(uploadedFiles); WebGeoDS.downloadBlob(JSON.stringify(data,null,2), base ?`${base}-stats.json`:"raster-stats.json","application/json", { tool:"raster-inspector" } ); };return button;}
First run loads the Python engine — expect 30-40 seconds. Instant after that, and again each time you come back to this page.
// Same reactive-on-a-dedicated-mutable pattern as// geospatial-file-inspector.qmd's statCard, for the same reason:// Reset has nothing to re-run, so reading straight from pyInspect// would leave stale numbers on screen after clicking it.statCard = {const s = inspectSummary;const box =document.createElement("div"); box.className="webgeods-stat-grid";const row = (label, value) => {const dt =document.createElement("div"); dt.className="webgeods-stat-label"; dt.textContent= label;const dd =document.createElement("div"); dd.className="webgeods-stat-value"; dd.textContent= value; box.append(dt, dd); };if (!s) {row("Dimensions","—");row("—","Upload a .tif/.tiff file or load the example above");return box; }const MAX_BANDS_SHOWN =6;const bandLines = s.bandStats.slice(0, MAX_BANDS_SHOWN).map((b) => b.min===null?`Band ${b.band}: all NoData`:`Band ${b.band}: ${b.min} to ${b.max} (mean ${b.mean})` );if (s.bandStats.length> MAX_BANDS_SHOWN) { bandLines.push(`… and ${s.bandStats.length- MAX_BANDS_SHOWN} more band(s)`); }row("Dimensions",`${s.width} × ${s.height} px`);row("Bands",String(s.bandCount));row("CRS", s.crsWarning?`${s.crs} ⚠️ ${s.crsWarning}`: s.crs);row("Resolution", s.resolution.join(" × "));row("Data type", s.dtype);row("NoData", s.nodata===null|| s.nodata===undefined?"None declared":String(s.nodata));row("Bounds", s.bounds.join(", "));row("Value range", bandLines.join(" · "));return box;}
sharedMapEl = sharedMap.element
This is the first tool in the Raster family. Read the companion article for the same statistics in Python and R, one cell at a time — a Calculator/Band Math tool is planned as the next step.