NOAA Storm Events Peril Climatology — County Risk Scores avatar

NOAA Storm Events Peril Climatology — County Risk Scores

Pricing

from $4.40 / 1,000 results

Go to Apify Store
NOAA Storm Events Peril Climatology — County Risk Scores

NOAA Storm Events Peril Climatology — County Risk Scores

County-level severe-weather climatology from NOAA's Storm Events Database. For any US county or state and year range, get per-peril event frequency, casualties, and property/crop damage, plus a composite peril risk score. Built for P&C underwriting, reinsurance, and catastrophe siting. Keyless.

Pricing

from $4.40 / 1,000 results

Rating

0.0

(0)

Developer

Kyle Maloney

Kyle Maloney

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

NOAA Storm Events County Peril Climatology

Turns NOAA/NCEI's Storm Events Database into a per-county, per-peril climatology: how often each severe-weather peril has hit each county, what it cost, who it killed or injured, and how bad the worst year was — in one row per (county x peril).

Built directly from NCEI's authoritative bulk .csv.gz archive (1950 to the current year), not a scraped front-end. No API key.

What one row is

One county, one peril type, over the year range you asked for. For example "Yuma County, Colorado — Thunderstorm Wind, 2023-2024: 55 events across 23 distinct storm episodes, max gust 87 kt, $147,140 in reported damage, peril score 54.18."

Read this before you use it: county vs forecast zone

NOAA records some perils against counties (CZ_TYPE = "C") and others against NWS forecast zones (CZ_TYPE = "Z"). This is not a minor detail: 43% of all national Storm Events records are zone-typed, and across the full 2023, 2024 and 2025 national files 37 of NOAA's 54 peril types have ZERO county-typed events, with seven more -- Wildfire, Drought, Heat, Heavy Snow, High Wind, Strong Wind and Winter Storm -- recording a handful of county events against thousands of zone events (Drought: 1 county vs 12,570 zone).

Among the perils a county-only run cannot see:

Wildfire · Excessive Heat · Heat · Winter Storm · Heavy Snow · Blizzard · Ice Storm · Drought · Hurricane (Typhoon) · Tropical Storm · Storm Surge/Tide · Coastal Flood · High Wind · Strong Wind · Dense Fog · Dense Smoke · Extreme Cold/Wind Chill · Avalanche · Rip Current

includeZones is off by default, which keeps every row tied to a real county FIPS. When it is off:

  • every output row reports zone_events_excluded (how many in-scope events were dropped) and excluded_zone_perils (which perils were dropped by name);
  • if you filter eventTypes to perils NOAA only zone-types, the run fails with an actionable message instead of handing you an empty dataset.

Set "includeZones": true to include them; those rows carry geography_basis: "forecast_zone" and are keyed to the zone's FIPS.

Who this is for

  • Property & casualty underwriters — hail, wind and tornado frequency and severity per county, with max hail diameter and max gust.
  • CRE / infrastructure siting — a peril profile for a candidate county before committing capital.
  • Cat modellers and reinsurance analysts — a free, reproducible baseline built from the authoritative NCEI archive.
  • Climate and resilience researchers — county-level event, casualty and loss history back to 1950.
  • AI agents — one call per state, one row per (county x peril), with explicit completeness fields so the agent knows what it does and does not know.

Example input

{
"states": ["Colorado"],
"counties": [],
"startYear": 2023,
"endYear": 2025,
"eventTypes": [],
"includeZones": false,
"maxResults": 2000
}

counties accepts either a 5-digit FIPS ("08031") or a bare county name matched case-insensitively ("Denver"). states accepts "CO" or "Colorado", as an array or a comma-separated string.

Output — every field

Identity

FieldMeaning
county_fips5-digit county FIPS, built as pad2(STATE_FIPS) + pad3(CZ_FIPS).
county_nameNOAA's CZ_NAME.
stateState name in NOAA's uppercase form.
state_abbrTwo-letter postal code.
event_typeThe NOAA peril type.
geography_basiscounty (CZ_TYPE=C), forecast_zone (CZ_TYPE=Z), or mixed.

Frequency and severity

FieldMeaning
event_countNOAA event records in scope.
episode_countDistinct NOAA storm episodes behind them. One storm system can log many events in one county, so this is the better "how often did a distinct storm hit here" measure.
events_per_yearevent_count divided by n_years.
deaths, injuries, casualtiesCombined totals.
deaths_direct, deaths_indirect, injuries_direct, injuries_indirectNOAA's own direct/indirect split.
worst_yearYear with the highest combined damage.
worst_year_damage_usdDamage in that year.
first_event_date, last_event_dateEarliest and latest event begin date in scope.
max_magnitudeLargest NOAA magnitude - hail diameter in inches, or wind gust in knots.
magnitude_typeWhat max_magnitude measures: EG/MG (gust), MS/ES (sustained), or empty for hail.
max_tornado_ef_scaleStrongest EF/F rating recorded.
max_tornado_length_miles, max_tornado_width_yardsLargest tornado path recorded.
flood_causesDistinct NOAA flood causes.
report_sourcesWho reported the events (Trained Spotter, Emergency Manager, ASOS, ...).
nws_officesNWS Weather Forecast Offices that logged them.
peril_scoreEDITORIAL 0-100 composite: annualized frequency (0.40), casualties (0.25), total damage (0.35), each log-saturating. A triage heuristic, not an actuarial loss estimate.

Damage — and how complete it is

NOAA leaves DAMAGE_PROPERTY empty on 21.6% of events (2024 national file): no dollar figure was ever estimated. That is not the same as $0.

FieldMeaning
property_damage_usdSum of reported property damage. null when NOAA costed none of this row's events.
crop_damage_usdSame, for crops.
total_damage_usdProperty + crop. null when neither was ever reported.
damage_per_year_usdtotal_damage_usd divided by n_years, or null.
events_with_damage_reportedHow many events carry a NOAA dollar figure.
events_missing_damage_reportHow many do not.
damage_report_completeness_pctThe percentage. 0 means the damage columns are null.
damage_is_lower_boundtrue when some but not all events were costed, so the sum is a floor.

peril_score deliberately treats an unreported figure as $0 so scores stay comparable across rows, even where the damage columns are null.

Coverage and provenance — read these before trusting a row

FieldMeaning
years_coveredThe years this row is actually built from.
years_requestedThe range you asked for.
years_retrievedComma-separated list of years whose NCEI file was downloaded and parsed.
years_missingRequested years that were absent from the index or failed to download. null when nothing was missing.
data_completetrue only when every requested year was retrieved.
source_statusok or partial.
n_yearsDenominator for the per-year metrics - the count of retrieved years, not requested ones.
zone_events_excludedIn-scope events dropped because they are zone-typed and includeZones is off.
excluded_zone_perilsThe peril types dropped for that reason, by name.
source_filesThe exact NCEI .csv.gz filenames used.
source_urlThe NCEI directory.

How it works

  1. Fetches the NCEI csvfiles/ directory index and asserts it live: it must still list at least 60 years back to 1960 or earlier, or the run fails before anything is billed. The year bounds you can request are derived from that index rather than hard-coded.
  2. Resolves each year's StormEvents_details-ftp_v1.0_d{YEAR}_c{DATE}.csv.gz by the newest creation date, and logs which one it used.
  3. Downloads and gunzips each annual file, with retry and backoff, and stream-filters it to your states while parsing - the full ~75,000-row national array is never materialised, because building it exhausts a 4 GB run.
  4. Asserts the file's shape live: 25 required columns present, the national event count inside a measured band, and CZ_TYPE still a two-value vocabulary. Any of those failing fails the run and bills nothing. A previously-unseen EVENT_TYPE is reported as a warning, not a failure.
  5. Aggregates to one row per (county x peril), scores, sorts by score, and applies maxResults.
  6. Gates before writing: if no year could be retrieved, if the state matched nothing, or if the filters matched no rows, the run fails with a message naming the cause - nothing is emitted and nothing is billed.

Use as an MCP tool

Available through mcp.apify.com. One call per state; one row per (county x peril). An agent should read data_complete, source_status and damage_report_completeness_pct before quoting a number, and read excluded_zone_perils before concluding a county has no history of a peril.

Pricing

Pay-per-result: one dataset row = one billed result. A failed run emits nothing and costs nothing beyond the platform's Actor-start event. Volume tiers apply automatically on paid Apify plans.

FAQ

Why did I get no Wildfire / Excessive Heat / Winter Storm rows? Because NOAA records those against NWS forecast zones, not counties, and includeZones is off by default. Set it to true. Your rows already name the exclusions in excluded_zone_perils.

Why is total_damage_usd null on some rows? Because NOAA published no dollar estimate for any event in that row. Publishing $0 there would be a factual claim the source never made. Check damage_report_completeness_pct.

Why does years_covered differ from what I asked for? Because at least one annual file could not be retrieved. years_missing names them and data_complete is false.

Is peril_score an actuarial number? No. It is a transparent, documented, absolute composite for triage and ranking. The inputs are all on the row, so you can build your own.

How far back does it go? The NCEI archive starts in 1950, but pre-1996 files only carry tornado, thunderstorm-wind and hail.

  • fema-nri-county-risk-profile - FEMA's National Risk Index for the same county, at county and tract resolution.
  • wildfire-asset-exposure-screener - live and historical wildfire perimeters and Wildfire Hazard Potential for a coordinate.
  • nfip-flood-loss-risk-screener - paid NFIP flood-claim history near a point.