Developers

Storms API

Every active tropical cyclone on the planet — typhoons, cyclones and hurricanes — with the official forecast track from the agency responsible for it, as JSON. Plus a curated archive of real historical tracks from NOAA IBTrACS. Free, with a key.

Get a free key

We email it to you. 1,000 requests a day, 60 a minute.

Quick start

Send the key in the X-API-Key header (or Authorization: Bearer).

curl -H "X-API-Key: bgy_…" https://bagyo.io/v1/storms

Endpoints

GET /v1/stormsEvery active storm in every basin, each with its current fix and full forecast track. Refreshed from the agencies every five minutes; an empty list when nothing is active.
GET /v1/storms/{id}One active storm, by the id in the list (TC2630, IO0126, AL132026). 404 once it has dissipated.
GET /v1/storms/historicalThe archive: selected real storms with six-hourly IBTrACS tracks.
GET /v1/storms/historical/{id}One archived storm, by archive id (katrina-2005) or IBTrACS SID.

The full schema is at /v1/openapi.json (OpenAPI 3.1), ready for code generators and API clients.

What a storm looks like

{
  "data": [
    {
      "id": "TC2630",
      "name": "CHAMPI",
      "philippineName": "Rosal",
      "developing": false,
      "basin": "wpac",
      "agency": "JMA",
      "agencyName": "Japan Meteorological Agency",
      "designation": "2630",
      "updatedAt": "2026-10-20T15:45:00.000Z",
      "advisoryUrl": "https://www.data.jma.go.jp/…",
      "current": {
        "time": "2026-10-20T15:00:00.000Z",
        "kind": "analysis",
        "lat": 17, "lon": 133,
        "windMps": 55, "windKt": 107,
        "pressureHpa": 925,
        "uncertaintyRadiusKm": 0,
        "galeRadiusKm": 650
      },
      "track": [ … ]
    }
  ],
  "meta": {
    "retrievedAt": "2026-10-20T15:52:10.000Z",
    "stale": false,
    "partial": false,
    "sources": ["Japan Meteorological Agency", "Joint Typhoon Warning Center", "National Hurricane Center"],
    "attribution": "Storm data from the Japan Meteorological Agency, …"
  }
}

Limits and errors

1,000 requests per key per UTC day, and 60 per minute. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; over the limit you get 429 with Retry-After. Storm data changes every few minutes at most, so polling /v1/storms once a minute is plenty. Errors are JSON: {"error": {"code": "…", "message": "…"}}.

Calls from a browser are allowed from any origin. A key in front-end code is visible to anyone who looks; for anything public, call the API from your server.

Terms