FEMA flood zones, as GeoParquet
The National Flood Hazard Layer, one file per county, kept current every day
FEMA publishes its flood maps one county at a time, as zipped shapefiles, and replaces a county whenever its map changes. Here they are as GeoParquet you query from a URL: one file per county delivery, checked against FEMA's list every morning, and replaced the day FEMA republishes it.
Flood zones are cut into pieces of at most 100 vertices, so finding the zone under a point reads one small row group, not a parish-sized polygon. Public domain, like FEMA's own data.
Not for official use. This is a repackaging, not the effective Flood Insurance Rate Map. Do not use it for flood zone determinations, insurance rating, regulatory or legal purposes: use FEMA's Flood Map Service Center for those. FEMA has not reviewed or endorsed it.
On the map
Each county is coloured by the date of the FEMA delivery it comes from. Zoom in past a city and the flood zones themselves appear, read straight from the county files by DuckDB running in your browser. Click anywhere for the zone under that point.
Updated every day
Every morning a job reads FEMA's list of county-wide deliveries, compares it with the published index, and runs the pipeline only on the counties FEMA republished: download, read the flood layer, normalize, cut into pieces, check rows and geometries, replace the file. A quiet day changes nothing. The last replacements, from changes.json:
| Checked | County | Delivery | FEMA date | Was |
|---|---|---|---|---|
| Loading… | ||||
FEMA often republishes a county without changing its zones: the date moves, the pieces stay the same. Deliveries that carry no flood layer at all are listed in skipped.json and tried again when FEMA replaces them. The first run of each month also freezes a copy of the whole dataset, and the last three are kept.
How it is built
- Read FEMA's listThe Flood Map Service Center lists every county-wide NFHL delivery with its date in the file name (
22071C_20261001.zip). If the list comes back much shorter than usual, the run stops: a truncated page is not a withdrawal. - Read the flood layer, in memoryLayer S_FLD_HAZ_AR is read from the ZIP without unpacking it, FEMA's fields mapped to plain columns, invalid geometries made valid, and three readings added:
risk,floodplainandsubzone. - Cut into piecesEach zone becomes pieces of at most 100 vertices (
ST_Subdivide). A row is a piece:piece_id = 0counts zones, and dissolving on (dfirm_id,source_feature_id) gives a zone's outline back. - Sort, check, publishEach county file is sorted along a Hilbert curve with a bbox column declared as the GeoParquet covering, checked against the pipeline's output (same rows, same geometry hashes), uploaded, then the index and manifests that name it.
The pipeline is public: nfhl-geoparquet-workshop. So is the packaging and the daily job: osm-geoparquet.
Get the data
https://parquetry.geomermaids.com/nfhl/latest/counties.parquet the index
https://parquetry.geomermaids.com/nfhl/latest/state=<XX>/<DFIRM_ID>.parquet one county
s3://parquetry/nfhl/latest/state=*/*.parquet (endpoint s3.geomermaids.com, anonymous)
The index has one row per county file: state, county, dfirm_id, fema_update_date, path, rows, size, sha256, and the file's bbox. Filter it, then read only the files it names.
The flood zone at a point
INSTALL httpfs; LOAD httpfs; INSTALL spatial; LOAD spatial;
SELECT path FROM read_parquet('https://parquetry.geomermaids.com/nfhl/latest/counties.parquet')
WHERE bbox.xmin <= -90.07 AND bbox.xmax >= -90.07
AND bbox.ymin <= 29.95 AND bbox.ymax >= 29.95;
-- state=LA/22071C.parquet, among others
SELECT flood_zone, zone_subtype, risk, static_bfe, fema_update_date
FROM read_parquet('https://parquetry.geomermaids.com/nfhl/latest/state=LA/22071C.parquet')
WHERE bbox.xmin <= -90.07 AND bbox.xmax >= -90.07
AND bbox.ymin <= 29.95 AND bbox.ymax >= 29.95
AND ST_Contains(geometry, ST_Point(-90.07, 29.95));
Zones by risk, every county at once
SET s3_endpoint = 's3.geomermaids.com'; SET s3_url_style = 'path';
SET s3_access_key_id = ''; SET s3_secret_access_key = '';
SELECT state, risk, count(*) FILTER (WHERE piece_id = 0) AS zones
FROM read_parquet('s3://parquetry/nfhl/latest/state=*/*.parquet')
GROUP BY ALL ORDER BY ALL;
- Browse the files: parquetry.geomermaids.com/nfhl/
- Portolan catalog (STAC, column docs, agent guide): nfhl/catalog/
- On a map, on your desktop: GeoPQ Workbench has it built in as a repository: pick a state, its counties load as layers.
- Monthly copies: snapshots.json
- Credits and what was changed: ATTRIBUTION.txt
Licence
The NFHL is a work of the US federal government, not subject to copyright in the United States (17 U.S.C. 105): no restriction on use or redistribution. Credit "FEMA National Flood Hazard Layer". The county outlines on the map are the US Census Bureau's cartographic boundaries, also public domain.
Need it tailored?
We also deliver it joined to your parcels or portfolio, with the zone history per county, on your own cadence, or into your bucket with freshness guarantees.