NFIP Flood Loss Risk Screener — Property Loss History Score
Pricing
from $4.40 / 1,000 results
NFIP Flood Loss Risk Screener — Property Loss History Score
Flood loss history by property from FEMA NFIP paid claims: count, total paid, repetitive-loss flag, recency and a 0-100 flood-loss score within a radius of each lat/lon.
Pricing
from $4.40 / 1,000 results
Rating
0.0
(0)
Developer
Kyle Maloney
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Turn a list of property coordinates into a flood loss history score built from FEMA National Flood Insurance Program (NFIP) paid claims. For each property (lat/lon) the actor summarizes past NFIP flood-insurance losses within a radius: claim count, total dollars paid, median and largest payout, repetitive-loss and severe-repetitive-loss signals, the most recent loss year and date, the dominant cause of damage, the dominant rated flood zone, the dominant named flood event, water depths, pre-FIRM exposure, Increased Cost of Compliance dollars, and a composite 0–100 flood-loss score.
Most tools republish the raw FEMA NFIP claims dump by state and year. This actor does the transform buyers actually want: asset-level loss history — "how much flood-insurance money has been paid out near THIS address, how often, how badly, how recently, and in what flood zone."
What changed in 1.2 (2026-08-04) — three defects that billed for wrong answers
1. The default radius is now 5 miles, and the input schema no longer carries a default
FEMA censors every claim to its census-tract centroid and rounds the coordinates to 0.1 degrees, so claim locations form a sparse lattice roughly 6.9 miles apart. Measured live 2026-08-04: 6,000 sampled claims across LA/TX/FL/NJ/MO/CA contained zero off-lattice coordinates, and a 0.2 x 0.2 degree window around New Orleans held exactly 3 distinct latitudes and 3 distinct longitudes.
1.1 shipped radiusMiles with "default": 1. An Apify input-schema default is
injected server-side into every run, so it silently ANDed itself into every
query from any caller who did not set the field. Reproduced live at
29.9276, -90.1053 (1234 Napoleon Ave, New Orleans), sinceYear: 2000:
| radius | 1.1 published | truth (1.2) |
|---|---|---|
| 1 mi | 0 claims, $0 — a billable "no flood loss history" in the most flood-claimed city in the US | 0 lattice nodes in range; verified_negative: null, radius_below_source_resolution: true, nearest published loss location 1.93 mi away |
| 2 mi | 1,829 claims / $32,700,255 | 23,233 claims |
| 5 mi | 638 claims / $5,478,371 — less than at 2 mi | 23,233 claims |
The four query-predicate inputs (radiusMiles, sinceYear, maxClaimsPerAsset,
maxResults) now carry prefill only, never default. Defaults are applied
in code, are documented here, and are covered by the offline suite.
Why 5? The worst-case distance from an arbitrary point to the nearest lattice node is half the lattice diagonal — 4.57 mi at New Orleans, up to 4.66 mi anywhere in the lower 48. A radius of 5 guarantees at least one lattice node is reachable, which is what makes a zero result meaningful.
2. Aggregates are now exact or null — never a sample
1.1 queried a padded square bounding box, capped the scan at
maxClaimsPerAsset, and distance-filtered whatever came back in arbitrary
server order. Because the box grows with the radius, a larger radius scanned a
smaller fraction of it, so the answer moved down as you asked for more area
(the 638-vs-1,829 row above). total_paid_usd was not a lower bound; it was a
random sample.
1.2 enumerates the lattice nodes inside the circle and queries those exact coordinates. A node is a point, so it is wholly inside or wholly outside — there is no arbitrary subset, and a larger radius can only add nodes. That makes the answer exact and monotonic, and far cheaper: the 5-mile New Orleans query went from 158,734 candidate rows to one node.
The exact in-radius total is read from the source's own row count before any
rows are fetched. If it exceeds maxClaimsPerAsset, every aggregate —
claim_count, total_paid_usd, avg_payout_usd, median_payout_usd,
max_single_payout_usd, repetitive_loss_flag, flood_loss_score and the rest —
is null, aggregate_status is not_measured_truncated, and
claims_in_radius_total carries the exact count so you still know the size of
the exposure. Raise maxClaimsPerAsset (up to 50,000) for an exact answer.
3. The retry budget was 17 seconds; it is now 3.5 minutes
1.1 retried 3 times with a 1,200 ms backoff across four probe combinations. In the run that flagged this actor Under maintenance, the probe started at 01:43:37.98 and had given up by 01:43:55.24 — 17.3 seconds against Apify's 5-minute allowance. OpenFEMA flaps: two scheduled checks failed on consecutive days while manual runs minutes later succeeded on an identical input and build.
1.2 uses a wall-clock deadline of 3.5 minutes with exponential backoff plus
full jitter, honours Retry-After, aborts any single request after 30 s so one
hung socket cannot eat the budget, and classifies failures: 429, 5xx, the
OpenFEMA HTML outage page, empty bodies, timeouts and network errors retry;
4xx other than 429 is terminal and stops immediately, because a malformed
filter is our bug and retrying it four times is exactly how 1.1 burned its
budget. The expected happy path gets 60% of the deadline, and one healthy
endpoint is enough to answer — the fallbacks are not probed just to prove they
are also down.
This does not weaken the fail-loudly contract. If OpenFEMA is down for the whole budget, the run still fails, emits nothing and bills nothing.
Also in 1.2
- Two live lattice assertions, run before any billable row and again per asset. (a) Every coordinate returned must sit exactly on the 0.1-degree lattice. (b) A padded bounding-box count must equal the union count over the lattice nodes inside that same box — verified live at four metros (New Orleans 244,785 = 244,785; Houston 123,086; New York 55,337; Minneapolis 756). If FEMA ever changes its rounding, both break and the run fails rather than silently under-counting.
- 9 new fields, all append-only. Nothing was removed or renamed.
- A new prefill built from three real geocoded addresses (see below).
- Assets are screened with bounded concurrency, so a realistic portfolio finishes well inside the auto-QA window.
What changed in 1.1 (2026-08)
- Moved to the current dataset. 1.0 queried OpenFEMA
v2/FimaNfipClaims, which FEMA has deprecated (removal 2026-10-15) and whose data has been frozen since 2026-06-01. 1.1 queriesv3/NfipClaimsand keeps v2 only as a fallback. Every row now carriesdataset_versionanddata_as_of. - A live drift probe runs before any billable row. The endpoint must resolve,
FEMA must echo the bounding-box
$filterback intact, a positive canary must return claims, a negative control must return exactly zero, required fields must be present, and the extract must not be stale. Any failure fails the run and bills nothing. - An asset that could not be screened no longer publishes
0claims and$0paid. In 1.0 an upstream outage produced a billable row readingclaim_count: 0, total_paid_usd: 0, repetitive_loss_flag: false— a confident "$0 in flood claims" answer that was never measured. Those fields are nownull, andnfip_claims_statussays why. - Silent truncation is now visible. A dense grid point can hold tens of
thousands of claims;
maxClaimsPerAssetstops the scan. 1.0 logged that and emitted the aggregate anyway. 1.1 publishesclaims_scanned,claims_in_bbox_total,scan_truncatedanddata_completeness, andverified_negativecan only betrueon a complete scan. - 41 new fields from data the actor was already entitled to fetch.
Who it's for
- P&C insurers & reinsurers — pre-bind flood exposure, repetitive-loss and severe-repetitive-loss screening, SFHA-vs-non-SFHA loss mix.
- Mortgage lenders & CRE due diligence — flood-loss history alongside Phase I and property condition.
- Real estate & appraisal — quantify neighborhood flood-loss burden and pre-FIRM exposure.
- Risk / cat modeling teams — a keyless historical-loss density signal by point.
Example input
{"assets": [{ "lat": 40.5716, "lon": -74.6107, "label": "100 N Bridge St, Somerville, NJ (Raritan River)", "state": "NJ" },{ "lat": 33.9848, "lon": -118.455, "label": "4200 Marina City Dr, Marina del Rey, CA", "state": "CA" },{ "lat": 40.7359, "lon": -106.2821, "label": "100 W Main St, Walden, CO (clean control)", "state": "CO" }],"radiusMiles": 5,"sinceYear": 2000,"maxClaimsPerAsset": 5000,"maxResults": 500}
Output fields (one row per asset)
Identity & scope
| Field | Meaning |
|---|---|
asset_label | Caller-supplied label for the property |
asset_lat | Latitude of the screened property |
asset_lon | Longitude of the screened property |
state | Optional 2-letter state supplied with the asset (metadata only) |
radius_miles | Radius used for the aggregation |
since_year | The sinceYear filter actually applied |
Did anyone actually check? (read these before the numbers)
| Field | Meaning |
|---|---|
nfip_claims_status | ok, unavailable, or invalid_input. Anything but ok means the loss figures were not measured |
nfip_claims_error | Null on success; the upstream failure message otherwise |
data_completeness | complete / truncated_by_cap / unverified / not_checked. Only complete carries measured aggregates |
verified_negative | true only when the source answered, the scan was complete, and the radius reached the source lattice. null means nobody could prove a negative — it is not a clean property |
claims_scanned | Claim records actually fetched and aggregated. Null when the scan was not affordable |
claims_in_bbox_total | FEMA's own total for the padded bounding box the lattice check was run against (a superset of the radius) |
scan_truncated | True when the exact in-radius total exceeded maxClaimsPerAsset, so every aggregate is null |
dataset_version | v3 (current) or v2 (deprecated, frozen) |
dataset_entity | The OpenFEMA entity queried |
dataset_deprecated | True when FEMA flags the answering dataset as deprecated |
dataset_deprecation_date | FEMA-published removal date, else null |
data_as_of | The asOfDate vintage of the NFIP extract behind this answer |
Loss history
| Field | Meaning |
|---|---|
claim_count | NFIP paid claims within the radius (on/after sinceYear) |
total_paid_usd | Sum of building + contents + ICC payments |
avg_payout_usd | Total paid divided by claim count |
median_payout_usd | Median single-claim payout (mean-skew resistant) |
max_single_payout_usd | Largest single-claim total payout |
total_icc_paid_usd | Increased Cost of Compliance dollars — only paid on substantial-damage / repetitive-loss determinations |
total_building_damage_usd | Reported gross building damage (not the payout) |
total_contents_damage_usd | Reported gross contents damage |
claims_with_unknown_payout | Claims where FEMA published no payment figure at all |
repetitive_loss_flag | True when ≥2 claims fall within the radius |
severe_repetitive_loss_signal | True when ≥4 claims fall within the radius (editorial, not FEMA's formal SRL designation) |
most_recent_loss_year | Year of the most recent nearby loss |
most_recent_loss_date | Exact date of the most recent nearby loss |
oldest_loss_year | Year of the oldest in-scope nearby loss |
distinct_loss_years | How many separate years produced a claim |
claims_last_10_years | Claims with a loss year in the last 10 calendar years |
flood_loss_score | Editorial 0–100 composite (count + total paid + recency) |
Hazard character
| Field | Meaning |
|---|---|
dominant_cause | Most frequent NFIP cause of damage (human-readable) |
dominant_rated_flood_zone | Most common rated flood zone (AE, VE, X, A07 …) |
dominant_flood_zone_class | Plain-English regulatory class of that zone |
sfha_claim_share_pct | Share of claims rated inside a Special Flood Hazard Area |
dominant_flood_event | Most frequent named FEMA flood event |
distinct_flood_events | How many separate named events produced claims |
max_water_depth_ft | Deepest reported flood water depth |
median_water_depth_ft | Median reported flood water depth |
Building stock
| Field | Meaning |
|---|---|
dominant_occupancy | Most common occupancy type, decoded |
claims_primary_residence | Claims flagged as a primary residence |
claims_elevated_building | Claims on elevated buildings |
claims_pre_firm | Claims on pre-FIRM construction (highest-risk segment) |
claims_post_firm | Claims on post-FIRM construction |
nfip_community_name | Most common NFIP participating community |
Nearest claim & diagnostics
| Field | Meaning |
|---|---|
nearest_claim_distance_miles | Distance to the closest in-radius claim centroid |
nearest_claim_year | Loss year of that closest claim |
nearest_claim_paid_usd | Payout on that closest claim |
nearest_claim_rated_flood_zone | Rated flood zone of that closest claim |
unknown_cause_codes | Cause codes FEMA published that this actor cannot label |
unknown_occupancy_codes | Occupancy codes FEMA published that this actor cannot label |
error | Null on success; a message when the asset could not be screened |
disclaimer | Usage disclaimer |
source_url | The OpenFEMA endpoint that answered |
checked_at | ISO timestamp of the run |
Grid-node query model (1.2)
| Field | Meaning |
|---|---|
spatial_query_mode | How nearby claims were located. grid_node_union = the actor enumerated the 0.1-degree lattice nodes inside the radius and queried those exact coordinates |
aggregate_status | exact = every figure on this row was computed over ALL in-radius claims. not_measured_truncated = the exact total exceeded maxClaimsPerAsset, so every aggregate is null (never a sample). not_measured_unverified = the source returned no total, so completeness could not be proven. not_checked = the asset was never screened |
grid_nodes_in_radius | How many FEMA lattice nodes fall inside the radius. 0 means FEMA publishes no loss location close enough to answer |
grid_node_coordinates | The exact censored coordinates queried, nearest first, as "lat,lon" strings — precisely where FEMA says the nearby losses occurred |
claims_in_radius_total | Exact count of NFIP claims on the in-radius lattice nodes, from the source's own row count. Populated even when the scan was too large to aggregate |
nearest_grid_node_distance_miles | Distance to the nearest lattice node, in or out of the radius — the closest any NFIP claim can possibly be reported to this address |
source_grid_resolution_miles | Worst-case distance from this latitude to the nearest lattice node (half the lattice diagonal). A radius below this cannot produce a verified negative |
radius_below_source_resolution | True when the radius is smaller than source_grid_resolution_miles. A zero at such a radius is not a clean property, so verified_negative is null |
source_grid_verified | True when the live lattice-equivalence check passed on this run, proving node enumeration is exhaustive. Null = the check did not run |
What verified_negative does and does not mean
verified_negative: true means all three of these held:
- FEMA answered and passed every live drift and lattice assertion;
- the scan was complete — the exact in-radius total was measured and every one of those claims was fetched and aggregated;
- the radius was at or above
source_grid_resolution_miles, so at least one lattice node was guaranteed to be reachable.
verified_negative: null means nobody checked, or the check could not prove a
negative. It is not a clean property. Read nfip_claims_status,
aggregate_status and radius_below_source_resolution to see which.
Even a true is a statement about FEMA's censored, tract-centroid data within
the radius — it is not a flood-zone determination, an Elevation Certificate, or
a statement that the parcel has never flooded. Uninsured losses and losses under
non-NFIP policies are not in this dataset at all.
What a truncated / null aggregate means
When aggregate_status is not_measured_truncated, the actor knows exactly
how many claims are in the radius (claims_in_radius_total) but could not afford
to fetch and aggregate them under maxClaimsPerAsset. Every derived figure is
null — deliberately. A partial sum over an arbitrary slice is not a lower bound
and not conservative; in 1.1 it moved down as the radius grew. Raise
maxClaimsPerAsset (maximum 50,000) or reduce the radius, and re-run.
Important: how FEMA locates claims (read this)
FEMA censors each loss to its census-tract centroid and rounds latitude/
longitude to 0.1 degrees. Claim locations are therefore a sparse lattice
about 6.9 miles apart, not exact addresses. Verified live 2026-08-04 across
6,000 sampled claims in six states: zero off-lattice coordinates.
Consequences:
- The actor queries the lattice nodes inside your radius by exact coordinate,
which is why the in-radius answer is exact and grows monotonically with the
radius.
grid_node_coordinatesshows you which nodes answered. - A radius below
source_grid_resolution_miles(up to 4.66 mi in the lower 48) can miss every node. KeepradiusMilesat 5 or above for real addresses; the default is 5. - Metrics describe a tract-level neighborhood, not one parcel.
- FEMA also publishes some claims with no coordinates at all (1 to 44 per 1,000 rows depending on the state). Those cannot be matched by any spatial query, by any method.
flood_loss_scoreis an editorial 0-100 composite (log-scaled claim count up to 40, log-scaled total paid up to 40, recency up to 20) - not a FEMA rating, flood-zone determination, or actuarial premium. It isnullwhenever the aggregate behind it was not exactly measured.
Inputs that populate the optional columns
Every value below was measured live on 2026-08-04 at radiusMiles: 5,
sinceYear: 2000.
- A real loss history (
total_paid_usd,median_payout_usd,dominant_flood_event,max_water_depth_ft,claims_pre_firm,total_icc_paid_usd):{"lat": 40.5716, "lon": -74.6107}(100 N Bridge St, Somerville NJ) - 1,717 claims, $90,888,480 paid, 2 lattice nodes. - A moderate coastal history:
{"lat": 33.9848, "lon": -118.455}(Marina del Rey CA) - 138 claims, $1,562,047. verified_negative: true:{"lat": 40.7359, "lon": -106.2821}(100 W Main St, Walden CO) - 0 claims, complete scan, 3 lattice nodes actually queried.radius_below_source_resolution: trueandverified_negative: null: any real address atradiusMiles: 1- e.g.{"lat": 29.9276, "lon": -90.1053}(1234 Napoleon Ave, New Orleans), whose nearest published loss location is 1.93 mi away.aggregate_status: "not_measured_truncated",claims_in_radius_total, and null aggregates:{"lat": 29.9276, "lon": -90.1053}atradiusMiles: 5withmaxClaimsPerAsset: 100- the exact in-radius total is 23,233.dataset_deprecated: true: only when v3 is unavailable and the run falls back to the deprecated v2 endpoint.
Use as an MCP tool
This actor is a clean, chainable tool for AI agents via mcp.apify.com: pass one or
more {lat, lon, label} assets and get back a structured, field-described flood-loss
history row per property — ideal for underwriting copilots and property-risk agents.
Agents should read nfip_claims_status and data_completeness before trusting any
figure, and must treat verified_negative: null as "unknown", never as "clean".
Pricing
Pay-per-result: one billable Result per asset row, unchanged in 1.2. Rows are buffered and the billing gate runs before anything is pushed — if every asset failed to screen, the run fails and nothing is billed. A truncated row is still one Result, and it still tells you the exact in-radius total.
FAQ
Where does the data come from? FEMA OpenFEMA v3/NfipClaims (the NFIP
Redacted Claims v3 release). Keyless, public, historical. The older
v2/FimaNfipClaims is kept only as a fallback until FEMA removes it on
2026-10-15.
Is this a FEMA flood zone / FIRM lookup? No. It measures historical paid losses near a point, and reports the flood zones those historical claims were rated in — not the current regulatory flood zone of your parcel. Pair it with a FIRM/flood-zone determination.
Why did my run fail instead of returning zero rows? Because a zero that was never measured is worse than a failure. If FEMA is unreachable, or its response fails the live drift check, or every asset errored, the run fails loudly and bills nothing.
Why is claim_count sometimes null? Dense flood metros can hold tens of
thousands of claims at one lattice node — a single node in New Orleans holds
23,233 since 2000. When the exact in-radius total exceeds maxClaimsPerAsset,
every aggregate is null rather than a partial sum, because a partial sum over
an arbitrary slice is not a lower bound (in 1.1 it fell as the radius grew).
claims_in_radius_total still gives you the exact size of the exposure. Raise
maxClaimsPerAsset (max 50,000) or reduce the radius for an exact aggregate.
Nothing came back for my address. Check radius_below_source_resolution
first: FEMA's lattice is ~6.9 miles apart, so a radius under about 4.7 miles can
miss every published loss location. nearest_grid_node_distance_miles tells you
how far the nearest one is. Then widen sinceYear. Only verified_negative: true
means genuinely clear.
Why did the answer change between 1.1 and 1.2? Because 1.1 was wrong. It scanned a padded square box, capped it, and aggregated whatever the server happened to return first — so a 5-mile query could report less money than a 2-mile one at the same address. 1.2 queries the censored coordinates directly and either returns an exact aggregate or none at all. No field was removed or renamed; existing values changed only where the old value was not measurable.
Related actors
- FEMA NRI County Risk Profile — forward-looking modeled risk to pair with this backward-looking loss history.
- EPA Contaminated Site Screener and Site Due Diligence Bundle — the rest of a Phase I / CRE diligence stack on the same coordinates.
Each is a screening tool, not a determination.