Project: NHTSA complaints database

The National Highway Traffic Safety Administration (part of the US Department of Transportation) maintains a database of vehicle safety complaints: you can file a complaint here.


NHTSA database web API

The NHTSA database can be accessed using a web API. The basic API functionality is as follows.

  • Request a list of all possible model years of vehicles in the database:

http://www.nhtsa.gov/webapi/api/Complaints/vehicle

Example:

[7]:
import requests
url = "http://www.nhtsa.gov/webapi/api/Complaints/vehicle"
years = requests.get(url).text
print(years)
{"Count":69,"Message":"Results returned successfully","Results":[{"ModelYear":"9999"},{"ModelYear":"2022"},{"
ModelYear":"2021"},{"ModelYear":"2020"},{"ModelYear":"2019"},{"ModelYear":"2018"},{"ModelYear":"2017"},{"Mode
lYear":"2016"},{"ModelYear":"2015"},{"ModelYear":"2014"},{"ModelYear":"2013"},{"ModelYear":"2012"},{"ModelYea
r":"2011"},{"ModelYear":"2010"},{"ModelYear":"2009"},{"ModelYear":"2008"},{"ModelYear":"2007"},{"ModelYear":"
2006"},{"ModelYear":"2005"},{"ModelYear":"2004"},{"ModelYear":"2003"},{"ModelYear":"2002"},{"ModelYear":"2001
"},{"ModelYear":"2000"},{"ModelYear":"1999"},{"ModelYear":"1998"},{"ModelYear":"1997"},{"ModelYear":"1996"},{
"ModelYear":"1995"},{"ModelYear":"1994"},{"ModelYear":"1993"},{"ModelYear":"1992"},{"ModelYear":"1991"},{"Mod
elYear":"1990"},{"ModelYear":"1989"},{"ModelYear":"1988"},{"ModelYear":"1987"},{"ModelYear":"1986"},{"ModelYe
ar":"1985"},{"ModelYear":"1984"},{"ModelYear":"1983"},{"ModelYear":"1982"},{"ModelYear":"1981"},{"ModelYear":
"1980"},{"ModelYear":"1979"},{"ModelYear":"1978"},{"ModelYear":"1977"},{"ModelYear":"1976"},{"ModelYear":"197
5"},{"ModelYear":"1974"},{"ModelYear":"1973"},{"ModelYear":"1972"},{"ModelYear":"1971"},{"ModelYear":"1970"},
{"ModelYear":"1969"},{"ModelYear":"1968"},{"ModelYear":"1967"},{"ModelYear":"1966"},{"ModelYear":"1965"},{"Mo
delYear":"1964"},{"ModelYear":"1963"},{"ModelYear":"1962"},{"ModelYear":"1961"},{"ModelYear":"1960"},{"ModelY
ear":"1959"},{"ModelYear":"1958"},{"ModelYear":"1957"},{"ModelYear":"1955"},{"ModelYear":"1949"}]}
  • Request a list of vehicle makers by providing a specific vehicle model year:

http://www.nhtsa.gov/webapi/api/Complaints/vehicle/modelyear/{YEAR}

Example:

[8]:
url = "http://www.nhtsa.gov/webapi/api/Complaints/vehicle/modelyear/1965"
makers = requests.get(url).text
print(makers)
{"Count":4,"Message":"Results returned successfully","Results":[{"ModelYear":"1965","Make":"FORD"},{"ModelYea
r":"1965","Make":"HARLEY-DAVIDSON"},{"ModelYear":"1965","Make":"INTERNATIONAL HARVESTER"},{"ModelYear":"1965"
,"Make":"VOLKSWAGEN"}]}
  • Request a list of vehicle models by providing the vehicle model year and maker.

http://www.nhtsa.gov/webapi/api/Complaints/vehicle/modelyear/{YEAR}/make/{MAKE}

Example:

[9]:
url = "http://www.nhtsa.gov/webapi/api/Complaints/vehicle/modelyear/1965/make/ford"
models = requests.get(url).text
print(models)
{"Count":2,"Message":"Results returned successfully","Results":[{"ModelYear":"1965","Make":"FORD","Model":"MU
STANG"},{"ModelYear":"1965","Make":"FORD","Model":"THUNDERBIRD"}]}
  • Request a list of complaints for a given model year, maker, and model:

http://www.nhtsa.gov/webapi/api/api/Complaints/vehicle/modelyear/{YEAR}/make/{MAKE}/model/{MODEL}

Example:

[10]:
url = "http://www.nhtsa.gov/webapi/api/Complaints/vehicle/modelyear/1965/make/ford/model/mustang"
complaints = requests.get(url).text
print(complaints)
{"Count":4,"Message":"Results returned successfully","Results":[{"ODINumber":538398,"Manufacturer":"Ford Moto
r Company","Crash":"No","Fire":"No","NumberOfInjured":0,"NumberOfDeaths":0,"DateComplaintFiled":"\/Date(90056
1600000-0400)\/","VIN":"5RO7C219764","Component":"FUEL SYSTEM, GASOLINE:STORAGE:TANK ASSEMBLY","Summary":"OWN
ER CONCERNED THAT FUEL TANK WILL RUPTURE IN A REAR END COLLISION AND RESULT IN A FIRE.","ProductType":"VEHICL
E","ModelYear":"1965","Make":"FORD","Model":"MUSTANG"},{"ODINumber":733514,"Manufacturer":"Ford Motor Company
","Crash":"No","Fire":"No","NumberOfInjured":0,"NumberOfDeaths":0,"DateofIncident":"\/Date(901944000000-0400)
\/","DateComplaintFiled":"\/Date(970718400000-0400)\/","VIN":"5R08A203647","Component":"TIRES:TREAD/BELT","Su
mmary":"TIRE ONLY HAD 5-6000 MILES USE, ENTIRE TRED AREA DETACHED AS DONUT WRAPPED AROUND AXLE AND DAMAGED FE
NDER .*AK (TIRESIZE: P185/75SR1)( DOT NUMBER:   TIRE SIZE: P185/75SR1 )","ProductType":"VEHICLE","ModelYear":
"1965","Make":"FORD","Model":"MUSTANG"},{"ODINumber":10022583,"Manufacturer":"Ford Motor Company","Crash":"No
","Fire":"No","NumberOfInjured":0,"NumberOfDeaths":0,"DateofIncident":"\/Date(1054353600000-0400)\/","DateCom
plaintFiled":"\/Date(1057809600000-0400)\/","VIN":"SF07A362335","Component":"TIRES","Summary":"VEHICLE WAS PA
RKED, THE OWNER HEARD A BIG \"BANG\" NOISE COMING  FROM THE CAR.  A MICHELIN  REGAL SPORT TIRE BLEWOUT WITH
OUT ANY REASON.   *AK  THE CONSUMER DISCOVERED THE DRIVER'S SIDE FRONT TIRE EXPERIENCED A BLOW OUT.  (TIRE MO
DEL/REGAL SPORT CHALLENGER)   *SCC   *JB","ProductType":"VEHICLE","ModelYear":"1965","Make":"FORD","Model":"M
USTANG"},{"ODINumber":10937513,"Manufacturer":"Ford Motor Company","Crash":"Yes","Fire":"Yes","NumberOfInjure
d":0,"NumberOfDeaths":1,"DateofIncident":"\/Date(187678800000-0500)\/","DateComplaintFiled":"\/Date(148272840
0000-0500)\/","Component":"ELECTRICAL SYSTEM | FUEL/PROPULSION SYSTEM | STRUCTURE:BODY","Summary":"1965 FORD
MUSTANG STALLED DURING RAINY EVENING AND CAME TO A STOP. VEHICLE WAS THEN HIT FROM BEHIND BY ANOTHER VEHICLE.
 THE MUSTANG EXPLODED AND INCINERATED THE DRIVER.\r\n","ProductType":"VEHICLE","ModelYear":"1965","Make":"FOR
D","Model":"MUSTANG"}]}

In each case data is returned as a JSON encoded string. Using thejson module (or the jons() method of requests) we can convert it into a Python dictionary:

[7]:
import json
complaints = json.loads(complaints)
complaints
[7]:
{'Count': 4,
 'Message': 'Results returned successfully',
 'Results': [{'ODINumber': 538398,
   'Manufacturer': 'Ford Motor Company',
   'Crash': 'No',
   'Fire': 'No',
   'NumberOfInjured': 0,
   'NumberOfDeaths': 0,
   'DateComplaintFiled': '/Date(900561600000-0400)/',
   'VIN': '5RO7C219764',
   'Component': 'FUEL SYSTEM, GASOLINE:STORAGE:TANK ASSEMBLY',
   'Summary': 'OWNER CONCERNED THAT FUEL TANK WILL RUPTURE IN A REAR END COLLISION AND RESULT IN A FIRE.',
   'ProductType': 'VEHICLE',
   'ModelYear': '1965',
   'Make': 'FORD',
   'Model': 'MUSTANG'},
  {'ODINumber': 733514,
   'Manufacturer': 'Ford Motor Company',
   'Crash': 'No',
   'Fire': 'No',
   'NumberOfInjured': 0,
   'NumberOfDeaths': 0,
   'DateofIncident': '/Date(901944000000-0400)/',
   'DateComplaintFiled': '/Date(970718400000-0400)/',
   'VIN': '5R08A203647',
   'Component': 'TIRES:TREAD/BELT',
   'Summary': 'TIRE ONLY HAD 5-6000 MILES USE, ENTIRE TRED AREA DETACHED AS DONUT WRAPPED AROUND AXLE AND DAMAGED FENDER .*AK (TIRESIZE: P185/75SR1)( DOT NUMBER:   TIRE SIZE: P185/75SR1 )',
   'ProductType': 'VEHICLE',
   'ModelYear': '1965',
   'Make': 'FORD',
   'Model': 'MUSTANG'},
  {'ODINumber': 10022583,
   'Manufacturer': 'Ford Motor Company',
   'Crash': 'No',
   'Fire': 'No',
   'NumberOfInjured': 0,
   'NumberOfDeaths': 0,
   'DateofIncident': '/Date(1054353600000-0400)/',
   'DateComplaintFiled': '/Date(1057809600000-0400)/',
   'VIN': 'SF07A362335',
   'Component': 'TIRES',
   'Summary': 'VEHICLE WAS PARKED, THE OWNER HEARD A BIG "BANG" NOISE COMING  FROM THE CAR.  A MICHELIN  REGAL SPORT TIRE BLEWOUT WITH  OUT ANY REASON.   *AK  THE CONSUMER DISCOVERED THE DRIVER\'S SIDE FRONT TIRE EXPERIENCED A BLOW OUT.  (TIRE MODEL/REGAL SPORT CHALLENGER)   *SCC   *JB',
   'ProductType': 'VEHICLE',
   'ModelYear': '1965',
   'Make': 'FORD',
   'Model': 'MUSTANG'},
  {'ODINumber': 10937513,
   'Manufacturer': 'Ford Motor Company',
   'Crash': 'Yes',
   'Fire': 'Yes',
   'NumberOfInjured': 0,
   'NumberOfDeaths': 1,
   'DateofIncident': '/Date(187678800000-0500)/',
   'DateComplaintFiled': '/Date(1482728400000-0500)/',
   'Component': 'ELECTRICAL SYSTEM | FUEL/PROPULSION SYSTEM | STRUCTURE:BODY',
   'Summary': '1965 FORD MUSTANG STALLED DURING RAINY EVENING AND CAME TO A STOP. VEHICLE WAS THEN HIT FROM BEHIND BY ANOTHER VEHICLE. THE MUSTANG EXPLODED AND INCINERATED THE DRIVER.\r\n',
   'ProductType': 'VEHICLE',
   'ModelYear': '1965',
   'Make': 'FORD',
   'Model': 'MUSTANG'}]}

Dates in the NHTSA database

Complaints records in the NHTSA database contains two fields specifying date and time:

  • DateofIncident - the date and time of the reported incident.

  • DateComplaintFiled - the date and time when the complaint was reported.

For example:

[8]:
record = complaints['Results'][1]
print(f"DateofIncident:  {record['DateofIncident']}")
print(f"DateComplaintFiled:  {record['DateComplaintFiled']}")
DateofIncident:  /Date(901944000000-0400)/
DateComplaintFiled:  /Date(970718400000-0400)/

The string “901944000000-0400” has the following meaning:

  • The part “901944000000” is a Unix timestamp. It gives date and time in terms of the number of miliseconds that have elapsed since the time 00:00:00 GMT on January 1, 1970.

  • The part “-0400” indicates the adjustment that needs to be made to convert the GMT time to the local time used by the database: the local time is 4 hours behind GMT.

We can use Python datetime module to convert this data into a human-readable format:

[9]:
from datetime import datetime, timedelta, timezone
import re

date = "901944000000-0400"

# split the date into a timestamp and a time zone indicator
timestamp, time_zone = map(int, re.findall(r"(\d*)(.*)", date)[0])

# the datetime.fromtimestampt function expects timestamp expressed in seconds,
# so we need to round up miliseconds:
seconds = timestamp // 1000

# divide the timezone indicator by 100 to get the number of hours
time_zone_hours = time_zone / 100

# define timezone of the local time of the databease,
local = timezone(timedelta(hours=time_zone_hours))

# get date and time from the timestamp
date = datetime.fromtimestamp(seconds, tz=local)
print(date)
1998-08-01 00:00:00-04:00

This shows that the the string “901944000000-0400” corresponds to the time 00:00:00 on August 1, 1998 in the local time zone of the database.


Objectives

Use the NHTSA complaints database to find and analyze something that you consider interesting or important.