PULSCAR ANALYSIS OF NHTSA PUBLIC DATA — WHICH SYMPTOMS REACH THE OBD2 PORT PulsCar analysis of NHTSA public data, September 2026. License: CC BY 4.0. Files in this folder may be reused with attribution to PulsCar (pulscar.io). -------------------------------------------------------------------------- 1. THE QUESTION -------------------------------------------------------------------------- Every "best diagnostic app" list ranks OBD2 apps without measuring the one thing that decides whether any of them can help: whether the symptom you have ever reaches the car's computer as a code. This folder is our attempt to put a number on that, from the largest public record of what owners actually report. -------------------------------------------------------------------------- 2. SOURCE FILE -------------------------------------------------------------------------- NHTSA complaints flat file FLAT_CMPL.txt, downloaded from static.nhtsa.gov and loaded into a local SQLite database on 16 September 2026: 777,040 owner complaints (ODINO), received 1 January 2015 - 8 September 2026. Field definitions: https://static.nhtsa.gov/odi/ffdd/cmpl/CMPL.txt Complaints are owner reports, not verified repairs and not failure rates. We count the WORDS OWNERS CHOSE. A complaint that does not mention a code does not prove no code was set - only that the owner did not write one down. That limitation runs through everything below and is the reason the table is built as a comparison BETWEEN symptom families rather than as an absolute claim about any one of them: the writing habit is roughly constant across families, so the differences between them carry the signal. -------------------------------------------------------------------------- 3. CASE SENSITIVITY: THE TRAP IN THIS FILE -------------------------------------------------------------------------- NHTSA narratives are recorded in ALL CAPS through 2020 and in mixed case from 2021 onward. Any regex written in uppercase without re.IGNORECASE, and any uppercase SQLite GLOB, silently drops most of the modern file. Measured here: a case-sensitive prefilter for an uppercase diagnostic trouble code ("P0", "P1", "C0", "B1", "U0") finds 7,358 complaints quoting a code. The same search run case-insensitively finds 10,476 - the uppercase version loses 29.8 percent of them, and the loss is concentrated entirely in 2021-2026. Every query behind these files is case-insensitive: SQLite LIKE folds ASCII case, FTS5 folds case, and every Python regex carries re.IGNORECASE. -------------------------------------------------------------------------- 4. THE THREE MEASURES (obd2-visibility-by-symptom.csv) -------------------------------------------------------------------------- For each complaint narrative, three case-insensitive tests: names a code or warning light: check engine light | engine light | warning light | warning lamp | indicator light | malfunction indicator | MIL | service engine | [PBCU]\d{4} | trouble code | fault code | diagnostic code | error code | DTC | OBD | scanned/scanner/scanning | code reader quotes a real DTC: \b[PBCU]\d{4}\b (e.g. P0300, C1391, U0121) says there was no code or light: no (trouble|fault|diagnostic|error)? codes? | no codes (were|was) (found|shown|stored|present) | did not (show|store|set|throw) (any)? codes | no (check engine|warning) light | check engine light (did not|never|has not|had not|was not) | without (setting|throwing) (any)? codes -------------------------------------------------------------------------- 5. THE SYMPTOM FAMILIES, AND HOW THEY WERE TIGHTENED -------------------------------------------------------------------------- Each family is a case-insensitive keyword pattern. Two exclusions were added after reading samples of a first, looser run: (a) The symptom phrase must appear in the FIRST 250 CHARACTERS of the narrative. NHTSA narratives lead with the subject; without this rule a complaint about headlights that mentions a wheel bearing in passing counted as a wheel-bearing complaint. (b) Motorcycles, trailers, RVs, buses and heavy trucks are dropped by make and model string. Base after exclusion: 766,825 complaints. The CSV publishes both runs: the tightened counts and, in the last two columns, the looser run's counts and code share, so the effect of the tightening is visible rather than hidden. The tightening moves every family in the same direction (fewer complaints, lower code share), which is what you would expect if the loose run was pulling in complaints about other systems that happen to mention codes. SAMPLE READING. 30 members of the tightened "wheel bearing hum or growl" family were drawn at random (random.seed(31)) and read in full. 24 of 30 described a hum, growl, roar or grind from a wheel bearing, hub, differential or driveline. 6 of 30 did not: a hum traced to the fuel pump, a hum "around the gas tank area", a clutch throw-out bearing, a windshield-wiper failure, one RV trailer and one motorcycle that survived the make filter because its make was recorded as UNKNOWN. Observed false-positive rate about 20 percent (6/30). Read that row as "a hum or growl from a rotating part", not strictly as a wheel bearing. An earlier, looser version of the same family read 30 and produced 8 clear false positives (about 27 percent), which is what prompted the first-250-characters rule. Small families are small: "Brake grind or squeal" is only 265 complaints after tightening, because owners usually write "brakes grinding" in ways this pattern does not catch. Treat its percentages as indicative and read the count beside them. -------------------------------------------------------------------------- 6. dtc-codes-owners-quote.csv -------------------------------------------------------------------------- The 40 most-quoted diagnostic trouble codes across the 10,476 complaints (1.35 percent of the file) that quote at least one. A complaint is counted once per distinct code it names. These are codes owners typed into a complaint, so the list is weighted toward codes tied to expensive or disputed repairs, not toward codes that occur most often in workshops. -------------------------------------------------------------------------- 7. app-prices-read.csv -------------------------------------------------------------------------- Every price and term quoted on the page, with the page it came from and the date it was read. The re_read_this_pass column says plainly which figures were fetched again on 18 September 2026 and which are carried forward from 13 September 2026 because the listing did not serve a price to our request. The generic ELM327 band is our own estimate and is labeled as one. -------------------------------------------------------------------------- 8. LIMITATIONS -------------------------------------------------------------------------- * Owner vocabulary, not diagnosis. Nothing here says a code did or did not exist; it says whether the owner wrote about one. * Self-selection. People file federal complaints about safety and about expensive, unresolved repairs. Routine repairs are missing from the file entirely. * No denominator. None of these counts is a rate per vehicle on the road. * Keyword families overlap. A complaint can belong to more than one, and the shares are of each family, not parts of a whole. * Small families (under ~500) carry wide uncertainty; their counts are printed next to their percentages for exactly that reason. Questions, corrections, or a figure that does not reproduce: support@pulscar.io