# NOAA Tropical Cyclone Best-Track Records - HURDAT2 (`nexgensignal/noaa-tropical-cyclone-track-records`) Actor

NOAA NHC HURDAT2 tropical-cyclone best-track database (Atlantic + NE/Central Pacific) as clean per-fix records - position, status, wind, pressure and wind radii, stamped with storm id, name and basin. Public domain. $0.05 per record.

- **URL**: https://apify.com/nexgensignal/noaa-tropical-cyclone-track-records.md
- **Developed by:** [NexGen Signal](https://apify.com/nexgensignal) (community)
- **Categories:** Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $33.50 / 1,000 track-fix records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## NOAA Tropical Cyclone Best-Track Records - HURDAT2

NOAA's HURDAT2 tropical-cyclone **best-track** database - the National Hurricane Center's official post-storm
reanalysis - as clean, per-fix records. **One row per best-track fix** (a cyclone's position and intensity at
a synoptic or special time), carrying its storm id, storm name and basin, across the North Atlantic and
NE/Central Pacific basin files.

### What one record represents

The source is **NOAA NHC HURDAT2**, published as two basin text files. Each file lists storms as a header
line - storm id, name and number of fixes - followed by that many **track-fix lines**. This Actor parses the
header/child structure and emits **one record per track fix**, stamping each fix with its storm's id, name
(`UNNAMED` where none was assigned), basin and season year. Each record carries the fix date and UTC time, a
record identifier (e.g. `L` for landfall), the system status (HU, TS, TD, EX, SD, SS, LO, WV, DB), latitude
and longitude (verbatim and as signed decimal degrees), maximum sustained wind, minimum central pressure, the
34/50/64-knot wind radii in all four quadrants, and the radius of maximum wind.

### Sample output

![Sample output — NOAA Tropical Cyclone Best-Track Records - HURDAT2](https://api.apify.com/v2/key-value-stores/IXCaMKjxSmUTLHhmq/records/noaa-tropical-cyclone-track-records.png)

*Real rows from a live run of this actor (first 5 rows, selected columns).*

One full record from the same run, exactly as delivered:

```json
{
  "storm_id": "AL011851",
  "storm_name": "UNNAMED",
  "basin": "AL",
  "basin_name": "North Atlantic",
  "storm_year": 1851,
  "fix_date": "18510625",
  "fix_time_utc": "0000",
  "record_identifier": null,
  "status": "HU",
  "latitude": "28.0N",
  "longitude": "94.8W",
  "latitude_deg": 28,
  "longitude_deg": -94.8,
  "max_wind_kt": 80,
  "min_pressure_mb": null,
  "r34_ne": null,
  "r34_se": null,
  "r34_sw": null,
  "r34_nw": null,
  "r50_ne": null,
  "r50_se": null,
  "r50_sw": null,
  "r50_nw": null,
  "r64_ne": null,
  "r64_se": null,
  "r64_sw": null,
  "r64_nw": null,
  "radius_max_wind_nm": null,
  "record_id": "AL011851:18510625:0000:0",
  "source": "NOAA NHC - HURDAT2 best track",
  "source_dataset": "AL",
  "licence": "U.S. Government work - NOAA National Hurricane Center HURDAT2 best-track database. Public domain (17 U.S.C. 105); no copyright. NWS/NOAA disclaimer: provided 'as is' with no warranty; not for use as the sole basis for safety-of-life decisions. Attribution to NOAA/NHC requested.",
  "attribution": "NOAA National Hurricane Center - HURDAT2 best-track database",
  "caveat": "One record per best-track fix (position/intensity at a synoptic or special time) across the North Atlantic (AL) and NE/Central Pacific (EP) basin files, each in its 2025-season edition (revised 27 Feb 2026). Every fix carries its storm id, name (UNNAMED where none was assigned; never a person) and basin. Wind radii and pressure use null where the source records -999/-99 (missing). Radius of maximum wind exists only from the 2021 season onward.",
  "observed_at": "2026-09-25T17:24:42Z"
}
```

### Coverage and volume

The two basin files, in their 2025-season editions (revised 27 February 2026), together carry
**87,631 track fixes** - **55,605** in the North Atlantic file (`hurdat2-1851-2025-02272026.txt`, seasons
1851-2025) and **32,026** in the NE/Central Pacific file (`hurdat2-nepac-1949-2025-02272026.txt`, seasons
1949-2025). Those counts were measured live from the files fetched at build time.

**Sol's Wave-3 index put this door at about 87,631 track-fix rows; measured live at build time the two basin files carry exactly 87,631 fixes (55,605 Atlantic + 32,026 NE/Central Pacific).**

Both editions were confirmed as the newest published files in the NHC HURDAT directory at build time. The
Actor delivers the fixes in file order (storm by storm, fix by fix) and stops as soon as your **Maximum
records** cap is met.

### Format and parsing

The record layout is quoted from the NHC HURDAT2 format document (https://www.nhc.noaa.gov/data/hurdat/hurdat2-format-atl-1851-2021.pdf). A header line reads,
verbatim from that document:

> AL (Spaces 1 and 2) - Basin - Atlantic; 09 - ATCF cyclone number for that year; 2021 - Year; IDA - Name,
> if available, or else "UNNAMED"; 40 - Number of best track entries - rows - to follow

and each data line carries date (YYYYMMDD), time (HHMM UTC), record identifier, status, latitude, longitude,
maximum sustained wind (knots), minimum pressure (mb), the 34/50/64-knot wind radii (NE, SE, SW, NW), and the
radius of maximum wind. Where the source records `-999`/`-99` (missing), the Actor delivers `null`. The
radius of maximum wind exists only from the 2021 season onward and is null before then.

### Licence and attribution

HURDAT2 is a **U.S. Government work in the public domain** (17 U.S.C. 105) - no copyright. The full notice,
including the NWS/NOAA disclaimer, travels on every record:

> U.S. Government work - NOAA National Hurricane Center HURDAT2 best-track database. Public domain (17 U.S.C. 105); no copyright. NWS/NOAA disclaimer: provided 'as is' with no warranty; not for use as the sole basis for safety-of-life decisions. Attribution to NOAA/NHC requested.

Attribution to NOAA/NHC is requested and stamped on every record. The data is provided "as is"; it is a
historical reanalysis, not a real-time or safety-of-life product.

### Person-data policy

HURDAT2 carries **no personal data**. Storm names are tropical-cyclone names (or `UNNAMED`, or a number such
as "TEN"), never persons; a per-record assertion rejects any forecaster/analyst/person field (verified with a
planted-field test). No natural-person data is processed.

### Interpretation caveat

One record per best-track fix across the North Atlantic (AL) and NE/Central Pacific (EP) basin files, each in its 2025-season edition (revised 27 Feb 2026). Every fix carries its storm id, name (UNNAMED where none assigned; never a person) and basin. Wind radii and pressure use null where the source records -999/-99 (missing). Radius of maximum wind exists only from the 2021 season onward.

Values are reproduced verbatim from the best-track files; the Actor never rewrites a field. Latitude and
longitude are delivered both as the source's verbatim strings (e.g. `28.0N`, `94.8W`) and as signed decimal
degrees for direct numeric use. A fix's `record_identifier` is blank for ordinary synoptic times and set (for
example `L`) at landfalls and intensity maxima.

### Data quality and freshness

Wind, pressure, the twelve wind-radii fields and the radius of maximum wind are delivered as real numbers
(null where missing); latitude/longitude have both string and numeric forms. The `record_id` composes storm
id, date, time and a per-storm sequence, so every fix is uniquely keyed and the dataset is safe to diff,
deduplicate or upsert. HURDAT2 is republished on NHC's post-season reanalysis cycle; re-running the Actor
picks up new seasons and any reanalysis revisions, and each record's `observed_at` stamp dates the snapshot.
The run's `RUN_RECEIPT` records the source URLs, how many records were delivered and charged, and confirms
`charge_equals_delivered`.

### Provenance and compliance

Every run reads `www.nhc.noaa.gov/robots.txt` at runtime; the gate result (URL, status, byte length, SHA-256
of the policy) is written to the run's `RUN_RECEIPT`, and both basin file paths are confirmed crawlable before
any fetch. The Actor never bypasses a block or fetches through a mirror.

### Inputs

- **Maximum records** (`maxRecords`) - hard cap on track-fix records delivered and billed. You are billed
  only for records actually delivered. The two files together carry ~87,600 fixes.

### Output

Records land in the Actor's default dataset and export as JSON, CSV, Excel or via the Apify API. A tabular
**overview view** surfaces storm id, storm name, basin, fix date/time, status, latitude, longitude, maximum
wind and minimum pressure.

### Fields in detail

The record leads with `record_id`, `storm_id`, `storm_name`, `basin`, `basin_name` and `storm_year`, then the
fix: `fix_date`, `fix_time_utc`, `record_identifier`, `status`, `latitude`/`longitude` (verbatim) and
`latitude_deg`/`longitude_deg` (signed decimals), `max_wind_kt`, `min_pressure_mb`, the twelve wind-radii
columns (`r34_ne` ... `r64_nw`) and `radius_max_wind_nm`. The provenance block closes every record. Because
each record carries its storm id and basin, you can regroup the fixes into storm tracks or aggregate to
per-storm intensity with a single group-by.

### Scaling and limits

Set **Maximum records** low to sample cheaply or high to pull the full best-track history. The Actor streams
the two files and delivers incrementally, so memory stays flat, and you are billed only for what is delivered.
Because HURDAT2 is a fixed historical reanalysis republished each post-season, re-running keeps a downstream
climatology current with new seasons and revisions, and each record's `observed_at` stamp dates the snapshot.
To build a per-storm panel, group the fixes on `storm_id`; to compare basins, filter on `basin`.

### Typical uses

Insurance, catastrophe-modelling and climatology teams use this cell as the authoritative track history for
Atlantic and eastern-Pacific cyclones - one flat table of every reanalysed fix, with intensity and wind
structure, that regroups into storm tracks on `storm_id` or aggregates to per-storm peak intensity with a
single group-by. Because latitude and longitude come as signed decimals, the fixes drop straight into a GIS
or a spatial join against exposure data, and the landfall record identifier isolates the fixes that matter
for coastal impact. Researchers use the full 1851-onward Atlantic record for long-period trend work, with
the caveat that pre-satellite seasons carry more missing wind-radii and pressure values (delivered as null,
never as a guessed number). A scheduled run keeps a downstream climatology current as NHC publishes each
post-season reanalysis.

### Sibling Actors

It sits beside the fleet's NOAA Storm Events database records and natural-hazard event records, which are distinct datasets (event catalogues, not best-track fixes). It shares its text-file engineering - the runtime robots gate, verbatim-value discipline
and push-then-charge billing - with the fleet's other NOAA records Actors, from which it stays distinct as a
best-track fix feed (position/intensity every few hours) rather than an event catalogue.

# Actor input Schema

## `maxRecords` (type: `integer`):

Maximum track-fix records delivered and billed. You are billed only for records delivered. The two basin files together carry ~87,600 track fixes.

## Actor input object example

```json
{
  "maxRecords": 500
}
```

# Actor output Schema

## `results` (type: `string`):

The delivered NOAA tropical cyclone best-track fix record.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "maxRecords": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("nexgensignal/noaa-tropical-cyclone-track-records").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "maxRecords": 500 }

# Run the Actor and wait for it to finish
run = client.actor("nexgensignal/noaa-tropical-cyclone-track-records").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "maxRecords": 500
}' |
apify call nexgensignal/noaa-tropical-cyclone-track-records --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nexgensignal/noaa-tropical-cyclone-track-records"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/9unNdz7FnE7SUneXu/builds/RVhaJoA01RWLX6Cqf/openapi.json
