A local, pip-installable proxy around the NTSB public CAROL API that:
- simplifies the complex
FileExportpayloads into simple parameters - lets you download raw ZIPs or directly get parsed JSON
- does not store or host any data – everything runs on the user's machine
You install this library, run the server locally, and your code/CLI talks to
http://localhost:8000. All requests to data.ntsb.gov go directly from your machine.
pip install ntsbpip install -e .[server]Start the FastAPI server (which proxies and parses NTSB data):
ntsb-serverOr equivalently, using uvicorn directly:
python -m uvicorn ntsb_api.server.main:app --host 127.0.0.1 --port 8000The server exposes:
- Download (ZIP) endpoints:
/api/v1/download/* - Streaming JSON endpoints:
/api/v1/cases,/api/v1/cases/search,/api/v1/stats
Meta endpoints:
GET /health– health checkGET /docs– Swagger UIGET /redoc– ReDoc
Rate limiting and logging are in-process and exist only to be a good citizen towards NTSB.
from ntsb_api import NTSBClient
client = NTSBClient(base_url="http://localhost:8000", timeout=60)Make sure ntsb-server is running before you call the client.
# Month ZIP
zip_bytes = client.download_month(2025, 4, mode="Aviation")
# Save to disk
with open("ntsb_2025_04.zip", "wb") as f:
f.write(zip_bytes)
# Date range ZIP
zip_bytes_range = client.download_date_range(
start_date="2025-04-01",
end_date="2025-04-30",
mode="Aviation",
)cases_response = client.get_cases(
start_date="2025-04-01",
end_date="2025-04-30",
mode="Aviation",
limit=100,
)
for case in cases_response["data"]:
print(case["cm_ntsbNum"], case.get("cm_eventDate"))This calls /api/v1/cases, which internally:
- Hits NTSB
FileExportwith a date-range payload. - Parses the ZIP in memory (no disk I/O).
- Applies pagination/sorting.
- Returns a JSON envelope:
{"data": [...], "pagination": {...}, "metadata": {...}}.
stats = client.get_statistics(
start_date="2025-04-01",
end_date="2025-04-30",
mode="Aviation",
)
print(stats["totals"])This maps to /api/v1/stats and returns aggregate counts
computed over the parsed cases (fatalities, injuries, by state, etc.).
The package installs a ntsb-api CLI.
# Download raw ZIP
ntsb-api download --year 2025 --month 4 \
--mode Aviation \
-o data/ntsb_2025_04.zip
# Download and immediately extract JSON to disk
ntsb-api download --year 2025 --month 4 \
--mode Aviation \
-o data/ntsb_2025_04.json \
--extract-json# ZIP
ntsb-api download-range \
--start-date 2025-04-01 \
--end-date 2025-04-30 \
--mode Aviation \
-o data/ntsb_2025_04_range.zip
# JSON
ntsb-api download-range \
--start-date 2025-04-01 \
--end-date 2025-04-30 \
--mode Aviation \
-o data/ntsb_2025_04_range.json \
--extract-jsonUnder the hood these commands:
- call your local proxy server (
http://localhost:8000/api/v1/download/...) - download the NTSB
FileExportZIP - optionally extract the first
*.jsonfile inside and write it to disk.
Use the proxy's in-memory parsing instead of writing files:
ntsb-api cases \
--start-date 2025-04-01 \
--end-date 2025-04-30 \
--mode Aviation \
--limit 50This hits /api/v1/cases on the local server, which:
- builds an NTSB
FileExportpayload for the date range + mode - downloads + parses the ZIP in memory
- applies sorting/pagination
- returns clean JSON (and the CLI prints a short summary).
- No persistence: the proxy never stores NTSB data in a database.
- No hosting: you run the FastAPI app locally; the author (me) does NOT HOST IT.
- No long-term cache: each request hits the live NTSB API; any in-memory state is per-process and short-lived.
- Good citizen: a simple in-process rate limiter and retry logic are used to avoid hammering NTSB or failing hard on transient network issues.