Build a surface fuel grid from LANDFIRE
You are viewing in-progress documentation for v2 (Beta). Switch to the stable version for the current production release.
A physics-based fire model needs surface fuel loads — how much fuel sits in each size class, per unit area. FastFuels builds them from LANDFIRE in two steps:
- Fetch the FBFM40 fuel-model grid — a categorical grid of Scott &
Burgan 40 fire-behavior fuel-model codes (
fbfm), pulled from LANDFIRE. - Look up fuel parameters — translate each fuel-model code into continuous loads (1hr/10hr/100hr, live herbaceous/woody) and fuel depth.
The split is deliberate: the FBFM grid is a reusable categorical input, and the lookup turns it into the continuous bands a model consumes. You can run the lookup again with a different band selection without re-fetching LANDFIRE.
Prerequisites
Section titled “Prerequisites”-
An API key. Set it once — it propagates to every code block: my-api-key.
-
A domain within CONUS. LANDFIRE covers the conterminous United States. Plug your domain id in once: your-domain-id. See Create a domain.
The whole flow in one script:
import time
import requests
API_KEY = "my-api-key"DOMAIN_ID = "your-domain-id"BASE = "https://api-v2-prod-nyvjyh5ywa-uw.a.run.app"HEADERS = {"api-key": API_KEY}
def poll(grid_id: str) -> dict: while True: grid = requests.get( f"{BASE}/domains/{DOMAIN_ID}/grids/{grid_id}", headers=HEADERS ).json() if grid["status"] in ("completed", "failed"): return grid time.sleep(5)
# Step 1: FBFM40 fuel-model grid from LANDFIRE (categorical `fbfm` band).fbfm = requests.post( f"{BASE}/domains/{DOMAIN_ID}/grids/fbfm40/landfire", headers=HEADERS, json={"name": "FBFM40 fuel model (LANDFIRE 2024)", "version": "2024"},).json()fbfm = poll(fbfm["id"])assert fbfm["status"] == "completed", fbfm
# Step 2: look up surface fuel loads + depth from the FBFM codes.loads = requests.post( f"{BASE}/domains/{DOMAIN_ID}/grids/lookup/fbfm40", headers=HEADERS, json={ "name": "Surface fuel loads (FBFM40 lookup)", "source_grid_id": fbfm["id"], "source_band": "fbfm", "bands": [ "fuel_load.1hr", "fuel_load.10hr", "fuel_load.100hr", "fuel_load.live_herb", "fuel_load.live_woody", "fuel_depth", ], },).json()loads = poll(loads["id"])print(loads["id"], loads["status"]) # -> <grid id> completedThe rest of this page walks the two calls individually.
Step 1 — Fetch the FBFM40 fuel-model grid
Section titled “Step 1 — Fetch the FBFM40 fuel-model grid”curl -X 'POST' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/grids/fbfm40/landfire' \ -H 'accept: application/json' \ -H 'api-key: my-api-key' \ -H 'Content-Type: application/json' \ -d '{ "name": "FBFM40 fuel model (LANDFIRE 2024)", "version": "2024"}'{ "id": "your-fbfm40-grid-id", "domain_id": "your-domain-id", "name": "FBFM40 fuel model (LANDFIRE 2024)", "description": "", "status": "pending", "progress": null, "created_on": "2026-05-25T18:44:14.779948", "modified_on": "2026-05-25T18:44:14.779948", "source": { "name": "landfire", "product": "fbfm40", "version": "2024", "description": "LANDFIRE FBFM40 fuel model codes (Scott-Burgan 40 classification)", "extent_buffer_cells": 0, "alignment": { "target": "domain", "resolution": null, "method": null }, "remove_non_burnable": null }, "modifications": [], "bands": [ { "key": "fbfm", "type": "categorical", "unit": null, "index": 0 } ], "georeference": null, "error": null, "chunks": { "shape": [512, 512], "count": null, "count_by_axis": null }, "tags": []}version selects the LANDFIRE release (2019, 2020, 2022, 2023,
2024; default 2024). The grid carries a single categorical band, fbfm.
Record its id — you’ll pass it to the lookup: your-fbfm40-grid-id.
Poll until completed:
curl -X 'GET' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/grids/your-grid-id' \ -H 'accept: application/json' \ -H 'api-key: my-api-key'{ "id": "your-fbfm40-grid-id", "domain_id": "your-domain-id", "name": "FBFM40 fuel model (LANDFIRE 2024)", "description": "", "status": "completed", "progress": { "percent": 100, "message": "Complete" }, "created_on": "2026-05-25T18:44:14.779948Z", "modified_on": "2026-05-25T18:44:38.534385Z", "source": { "name": "landfire", "description": "LANDFIRE FBFM40 fuel model codes (Scott-Burgan 40 classification)", "remove_non_burnable": null, "alignment": { "target": "domain", "method": null, "resolution": null }, "version": "2024", "product": "fbfm40", "extent_buffer_cells": 0 }, "modifications": [], "bands": [ { "key": "fbfm", "type": "categorical", "unit": null, "index": 0 } ], "georeference": { "crs": "EPSG:32611", "transform": [ 29.438767164252283, 0.0, 720227.9398802927, 0.0, -29.438767164262632, 5190646.487014395 ], "shape": [30, 45] }, "error": null, "chunks": { "shape": [512, 512], "count": 1, "count_by_axis": { "x": 1, "y": 1 } }, "tags": []}Step 2 — Look up surface fuel loads
Section titled “Step 2 — Look up surface fuel loads”Point the lookup at the completed FBFM grid. source_band is the band
holding the codes (fbfm), and bands is the list of parameters to compute.
curl -X 'POST' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/grids/lookup/fbfm40' \ -H 'accept: application/json' \ -H 'api-key: my-api-key' \ -H 'Content-Type: application/json' \ -d '{ "name": "Surface fuel loads (FBFM40 lookup)", "source_grid_id": "your-fbfm40-grid-id", "source_band": "fbfm", "bands": [ "fuel_load.1hr", "fuel_load.10hr", "fuel_load.100hr", "fuel_load.live_herb", "fuel_load.live_woody", "fuel_depth" ]}'{ "id": "your-grid-id", "domain_id": "your-domain-id", "name": "Surface fuel loads (FBFM40 lookup)", "description": "", "status": "pending", "progress": null, "created_on": "2026-05-25T18:44:51.210747", "modified_on": "2026-05-25T18:44:51.210747", "source": { "name": "lookup", "table": "fbfm40", "source_grid_id": "your-fbfm40-grid-id", "source_band": "fbfm" }, "modifications": [], "bands": [ { "key": "fuel_load.1hr", "type": "continuous", "unit": "kg/m**2", "index": 0 }, { "key": "fuel_load.10hr", "type": "continuous", "unit": "kg/m**2", "index": 1 }, { "key": "fuel_load.100hr", "type": "continuous", "unit": "kg/m**2", "index": 2 }, { "key": "fuel_load.live_herb", "type": "continuous", "unit": "kg/m**2", "index": 3 }, { "key": "fuel_load.live_woody", "type": "continuous", "unit": "kg/m**2", "index": 4 }, { "key": "fuel_depth", "type": "continuous", "unit": "m", "index": 5 } ], "georeference": { "crs": "EPSG:32611", "transform": [ 29.438767164252283, 0.0, 720227.9398802927, 0.0, -29.438767164262632, 5190646.487014395 ], "shape": [30, 45] }, "error": null, "chunks": { "shape": [512, 512], "count": null, "count_by_axis": null }, "tags": []}Poll this grid the same way. When complete, it carries the six continuous bands you asked for, with units resolved from the lookup table:
{ "id": "your-grid-id", "domain_id": "your-domain-id", "name": "Surface fuel loads (FBFM40 lookup)", "description": "", "status": "completed", "progress": { "percent": 100, "message": "Complete" }, "created_on": "2026-05-25T18:44:51.210747Z", "modified_on": "2026-05-25T18:44:54.656088Z", "source": { "name": "lookup", "source_band": "fbfm", "source_grid_id": "your-fbfm40-grid-id", "table": "fbfm40" }, "modifications": [], "bands": [ { "key": "fuel_load.1hr", "type": "continuous", "unit": "kg/m**2", "index": 0 }, { "key": "fuel_load.10hr", "type": "continuous", "unit": "kg/m**2", "index": 1 }, { "key": "fuel_load.100hr", "type": "continuous", "unit": "kg/m**2", "index": 2 }, { "key": "fuel_load.live_herb", "type": "continuous", "unit": "kg/m**2", "index": 3 }, { "key": "fuel_load.live_woody", "type": "continuous", "unit": "kg/m**2", "index": 4 }, { "key": "fuel_depth", "type": "continuous", "unit": "m", "index": 5 } ], "georeference": { "crs": "EPSG:32611", "transform": [ 29.438767164252283, 0.0, 720227.9398802927, 0.0, -29.438767164262632, 5190646.487014395 ], "shape": [30, 45] }, "error": null, "chunks": { "shape": [512, 512], "count": 1, "count_by_axis": { "x": 1, "y": 1 } }, "tags": []}This is a finished surface fuel grid: every cell’s FBFM code is mapped to its
loads. On the Blue Mountain domain the codes present (grass, shrub, and
timber-litter models, plus non-burnable 91) map fuel_load.1hr across
0.0 (non-burnable) up to 1.3 kg/m**2 — distinct values per fuel model,
exactly as the lookup table prescribes.
Next steps
Section titled “Next steps”The fuel-load grid is ready to use:
- Clean it up — mask roads and water to zero before a run.
- Inspect the values — fetch and stream the grid data.
- Align it to another grid’s resolution with resample.
Common pitfalls
Section titled “Common pitfalls”- Domain outside CONUS. LANDFIRE is conterminous-US only; a domain elsewhere has no coverage and the FBFM fetch fails. Check that your AOI is within the lower 48.
- Running the lookup before the FBFM grid is
completed. The lookup reads the source grid’s data — it needssource_grid_idto point at a finished grid. Poll step 1 tocompletedfirst. - Wrong
source_band.source_bandmust name the categorical FBFM band on the source grid (fbfm). Pointing it at a non-existent band fails the lookup. - Empty
bands. At least one band is required. Pick from the fuel-load, SAVR, depth, and combustion parameters listed above.