API Guide

How to actually use each endpoint. Real queries, practical tips, and things to watch for. For the formal spec, see the interactive docs.

Authentication & pricing

Three tiers, no signup required for the free ones:

EndpointAuth requiredTier
GET /v1/statistics/* (summary, states, hotspots, trends)NoFree
GET /v1/intelligence/location-risk (incl. AADT block)NoFree
GET /v1/reports/intersection/previewNoFree
GET /v1/crashes (search/list)API key$19/mo
GET /v1/crashes/{st_case}/{year} (single crash + road exposure)API key$19/mo
GET /v1/reports/intersection (full report)Stripe token$9/each

Free endpoints are rate-limited to 60 requests/minute per IP. Pass an API key to lift the limit.

Getting an API key

POST /v1/auth/keys Content-Type: application/json {"email": "[email protected]"} # Response: {"key": "fars_abc123...", "plan": "free", ...}

Pass it on every request as a header or query param:

# Header (recommended) curl -H "X-API-Key: fars_abc123..." https://farsapi.com/v1/crashes?state=Texas # Or query param curl https://farsapi.com/v1/crashes?state=Texas&api_key=fars_abc123...

Searching crashes

GET /v1/crashes is the main endpoint. All filters are optional and combine with AND logic. Paginated - default 50 results, max 200.

By state and year

The simplest query. State is matched by name (case-insensitive) or FIPS code.

# Texas crashes in 2023 GET /v1/crashes?state=Texas&year_from=2023&year_to=2023 # Same thing with FIPS code GET /v1/crashes?state_code=48&year_from=2023&year_to=2023 # Partial county name match GET /v1/crashes?state=Texas&county=Harris

Tip: County names in FARS include the FIPS code, like "HARRIS (201)". Searching "Harris" matches it. Don't include the code in your search.

By location (radius search)

This is the feature NHTSA's own API doesn't have. Pass latitude, longitude, and radius in miles.

# All fatal crashes within 5 miles of downtown Austin GET /v1/crashes?lat=30.267&lng=-97.743&radius_miles=5 # Tight radius for intersection analysis GET /v1/crashes?lat=30.267&lng=-97.743&radius_miles=0.1

Tip: 0.1 miles = ~530 feet, roughly one intersection. For broader corridor analysis, use 1-5 miles. Queries over 50 miles will be slow - narrow with state or year filters.

Tip: About 0.4% of crashes have no GPS coordinates and won't appear in radius queries. If you need complete coverage for a state, use ?state= instead.

By vehicle

Filter by make, model, body type, or rollover. These use subqueries on the vehicle table - the crash is returned if any involved vehicle matches.

# Ford F-150 crashes GET /v1/crashes?vehicle_make=Ford&vehicle_model=F-150 # Large truck rollovers GET /v1/crashes?vehicle_body_type=Truck&rollover=true # Motorcycle crashes in California GET /v1/crashes?vehicle_body_type=Motorcycle&state=California

Tip: Make and model are partial matches. "Ford" matches "Ford", "vehicle_model=F-1" matches "F-150" and "F-100". Body type matches against NHTSA's verbose labels - "Truck" matches "Light Pickup", "Single-unit straight truck", etc.

Tip: About 3.4% of vehicles have numeric codes instead of model names (older cars, unidentified vehicles). These won't match model name searches.

By conditions

# Rain crashes at night GET /v1/crashes?weather=Rain&light=Dark # Drunk driver crashes GET /v1/crashes?drunk_driver=true # Hit-and-run pedestrian crashes GET /v1/crashes?hit_and_run=true&pedestrian_involved=true # Head-on collisions GET /v1/crashes?manner_of_collision=Front-to-Front

Tip: Weather and light are partial matches. "Dark" matches "Dark - Not Lighted", "Dark - Lighted", and "Dark - Unknown Lighting". "Rain" matches "Rain" and "Freezing Rain or Drizzle".

Tip: drunk_driver=true means at least one vehicle had an impaired driver (derived from the vehicle-level DR_DRINK field). It doesn't mean the drunk driver caused the crash - they were involved.

Pagination

# First page (default 50 results) GET /v1/crashes?state=Texas&limit=100&offset=0 # Second page GET /v1/crashes?state=Texas&limit=100&offset=100 # Response includes total count: {"total": 15435, "limit": 100, "offset": 0, "data": [...]}

Tip: Max 200 per page. To pull all Texas crashes (15k+), paginate with limit=200 and increment offset. The total field tells you when to stop.

Crash detail

GET /v1/crashes/{st_case}/{year} returns a single crash with full vehicle records, person records, and (new) the FHWA HPMS road exposure data for the segment the crash was matched to.

GET /v1/crashes/480100/2023 Header: X-API-Key: fars_abc123... # Returns crash + all vehicles + all persons + road_exposure: { "case_id": "Texas-2023-480100", "date": "2023-01-12", "fatalities": 1, "vehicles": [ {"make": "Chevrolet", "model": "Tahoe", "model_year": 2014, ...}, {"make": "Ford", "model": "F-250", "model_year": 2001, ...} ], "persons": [ {"person_type": "Driver", "age": 16, "sex": "Female", "injury_severity": "Fatal Injury (K)", ...}, ... ], "road_exposure": { "aadt": 47000, # vehicles per day on this segment "aadt_truck": 4200, "f_system": 3, "f_system_label": "Principal Arterial - Other", "lanes": 4, "segment_speed_limit": 55, "snap_distance_m": 3.2, # crash was 3.2m from the centerline "hpms_year": 2017 } }

Tip: The st_case is NHTSA's case identifier. It's unique within a state and year. You can use it to cross-reference with NHTSA's own source CSVs if you need to verify a data point.

About road_exposure: Returned for ~80% of crashes. Returns null when the crash didn't snap to a HPMS segment within 80m, or snapped to a segment with AADT=0 (typically ramps without a traffic count, or HPMS sample sections in low-coverage states like Delaware and North Carolina). Source: FHWA HPMS 2017 public release. See data coverage for state-by-state match rates.

Intersection reports

Two endpoints: a free preview and a paid full report.

Free preview

No auth needed. Returns crash count, top collision types, and worst hours. Use this to check if a location has data before buying.

GET /v1/reports/intersection/preview?lat=33.749&lng=-84.388&radius_feet=2640

Tip: 2640 feet = half a mile. Good default for intersection analysis. Use 500-1000 feet for a single intersection, 2640-5280 for a corridor or road segment.

Full report

Purchase via the checkout flow, then access with your token. The example report shows what you get: map, pattern analysis, charts, and every crash record with vehicle and person detail.

# 1. Create checkout POST /v1/auth/reports/checkout {"email": "[email protected]", "latitude": 33.749, "longitude": -84.388, "radius_feet": 2640} # 2. After payment, access the report GET /v1/reports/intersection?token=your_token_here # Or view the rendered HTML report https://farsapi.com/report/view?token=your_token_here

Statistics (free, no auth)

Aggregate endpoints for analysis and benchmarking. No API key needed.

Summary

Breakdowns by year, month, hour, road type, weather, and collision type. Filter by state and/or year.

# National summary, all years GET /v1/statistics/summary # Texas 2023 GET /v1/statistics/summary?state=Texas&year=2023 # Response includes by_month, by_hour, by_road_type, by_weather, by_collision_type

Tip: The by_hour breakdown is useful for fleet safety - it shows which hours have the most fatal crashes. Peak is typically 8pm-10pm nationally.

States ranking

# All states ranked by fatalities, 2023 GET /v1/statistics/states?year=2023 # Returns: state, crashes, fatalities, drunk_driver_crashes, avg_fatalities_per_crash

Tip: Useful for insurance pricing - compare a state's fatality rate against the national average. Texas, California, and Florida consistently lead.

Trends

# Fatality trend for Florida GET /v1/statistics/trends?state=Florida&metric=fatalities # Drunk driving trend nationally GET /v1/statistics/trends?metric=drunk_driver_crashes # Available metrics: fatalities, crashes, drunk_driver_crashes

Tip: Response includes yoy_change_pct - year-over-year percentage change. Nationally, fatalities spiked +10.8% in 2021 (post-COVID driving behavior change) and have been declining since.

Hotspots

# Crash clusters within 10 miles of downtown LA GET /v1/statistics/hotspots?lat=34.052&lng=-118.243&radius_miles=10 # Returns locations with 2+ crashes, ranked by density

Tip: Hotspots are grouped into ~100-meter grid cells. A "hotspot" with 5 crashes means 5 fatal crashes occurred within roughly one block. This is useful for identifying dangerous corridors that individual crash queries might not reveal.

Location intelligence (free, no auth)

Risk analysis for any location - crash count, county percentile ranking, road-type benchmarks, AADT-adjusted Expected vs Actual fatal crashes, contributing factors, and a narrative assessment. This is what powers the "Location context" and "Expected vs Actual" sections in intersection reports.

# Location risk analysis - is this intersection dangerous? GET /v1/intelligence/location-risk?lat=34.052&lng=-118.243&radius_feet=2640 # Returns: # - crashes + fatalities at this location # - county percentile ranking ("top 2% in California") # - road-type benchmarks (state + national averages) # - aadt block: traffic volume + Expected vs Actual fatal crashes # (e.g. "17 observed vs 0.5 expected = 34x more than expected # for an Interstate of this AADT") # - top crash events ("Ran off road -> Hit barrier -> Rollover") # - contributing factors (impairment, distraction, violation) # - narrative assessment paragraph

Tip: This endpoint is free and doesn't require an API key. Use it to check whether a location has meaningful crash data before purchasing a full intersection report. The assessment paragraph is designed to be quotable in legal filings and safety reports (with appropriate disclaimers).

Tip: The county percentile tells you how this location's county compares to others in the same state. "Top 2%" means only 2% of counties in that state have more fatal crashes - useful for establishing that a location is in a high-crash area.

The aadt block: traffic-volume-adjusted analysis

For locations where at least one crash matched a FHWA HPMS road segment with non-zero AADT (~80% of US fatal crashes), the response includes a top-level aadt block with the Expected vs Actual computation:

# Example aadt block for the Atlanta Downtown Connector { "stats": { "matched_crashes": 17, "avg_aadt": 70630, "max_aadt": 314000, "primary_road_label": "Interstate", "n_distinct_routes": 12, "segments": [...] # grouped by class + lane bucket }, "rate": { "expected_vs_actual_available": true, "actual_crashes": 17, "expected_crashes": 0.5, # for an Interstate of this AADT "multiple_of_expected": 34.1, # 34x more than expected "rate_per_100M_vmt": 10.99, "baseline_rate_per_100M_vmt": 0.322, "primary_f_system_label": "Interstate" }, "year_min": 2018, "year_max": 2023, "year_span": 6 }

About the baselines: Per-class fatal crash rates per 100M VMT computed from all matched FARS crashes 2017-2023 nationally. Interstates are the safest road class per VMT (0.322), Major Collectors are the deadliest (1.886). The Expected vs Actual ratio uses these baselines as the comparison anchor - this avoids the selection bias of comparing FARS-queried locations to a fleet-wide national average that includes millions of zero-crash road miles.

When AADT data is missing: The aadt field is null when no crash in the radius matched a HPMS segment with non-zero AADT (about 20% of fatal crashes nationally). State coverage ranges from 64% (Delaware) to 94% (DC). See data coverage for details.

Code examples

Python

import requests API_KEY = "fars_your_key_here" BASE = "https://farsapi.com" # Search crashes r = requests.get(f"{BASE}/v1/crashes", params={ "state": "Texas", "year_from": 2023, "drunk_driver": True, "limit": 100, }, headers={"X-API-Key": API_KEY}) data = r.json() print(f"Found {data['total']} drunk driver crashes in TX 2023") for crash in data["data"]: print(f" {crash['date']} - {crash['location']['county']} - {crash['fatalities']} fatalities") # Free: AADT-adjusted Expected vs Actual at any location r = requests.get(f"{BASE}/v1/intelligence/location-risk", params={ "lat": 33.749, "lng": -84.388, "radius_feet": 2640, }) risk = r.json() if risk["aadt"] and risk["aadt"]["rate"]["expected_vs_actual_available"]: rate = risk["aadt"]["rate"] print(f"Observed: {rate['actual_crashes']} fatal crashes") print(f"Expected: {rate['expected_crashes']} for a " f"{rate['primary_f_system_label']} of this AADT") print(f"= {rate['multiple_of_expected']}x more than expected") # Free statistics (no key needed) r = requests.get(f"{BASE}/v1/statistics/summary", params={"state": "Texas", "year": 2023}) stats = r.json() print(f"TX 2023: {stats['totals']['crashes']} crashes, {stats['totals']['fatalities']} fatalities")

JavaScript

const API_KEY = 'fars_your_key_here'; const BASE = 'https://farsapi.com'; // Radius search const res = await fetch( `${BASE}/v1/crashes?lat=30.267&lng=-97.743&radius_miles=5&limit=50`, { headers: { 'X-API-Key': API_KEY } } ); const data = await res.json(); console.log(`${data.total} crashes within 5mi of Austin`); // Free: intersection preview (no key) const preview = await fetch( `${BASE}/v1/reports/intersection/preview?lat=30.267&lng=-97.743` ).then(r => r.json()); console.log(`${preview.total_crashes} crashes near this intersection`);

curl

# Search with auth curl -H "X-API-Key: fars_your_key" \ "https://farsapi.com/v1/crashes?state=Florida&year_from=2023&limit=10" # Free stats curl "https://farsapi.com/v1/statistics/states?year=2023"

Rate limits

Best practices

Interactive API docs (Swagger)