If you build software for trucking, sooner or later you join your data to FMCSA's. The agency publishes carrier registration data openly on data.transportation.gov, keyed by USDOT number, and many brokers, insurers and TMS products rely on it.

I wanted to know two things. First, does the same FMCSA dataset return the same records through its paginated API as through its CSV export? Second, when two different FMCSA publications describe the same carriers, do they agree?

I used LogiParity, the open-source parity checker I maintain, on carriers based in Iowa and Vermont, using the data as published on November 8, 2026. All numbers below come from those runs. The configuration, scripts, checksums and reports are kept so the check can be repeated.

The data

Two datasets from data.transportation.gov, joined by USDOT number:

  • Company Census File, refreshed daily. The version I used was updated on November 7, 2026.
  • SMS Input: Motor Carrier Census, produced by FMCSA's monthly CSA data run. The version I used was published on October 13, 2026, and its newest records date from late September.

No account or API key is needed for either. I did not request phone numbers, emails or company officers.

Check 1: the API and the export agree

The first comparison read the Company Census twice with the same filter: once through the JSON API, 5,000 records per page, and once as a CSV export.

api: type: rest baseUrl: https://data.transportation.gov path: "/resource/az4n-8mr2.json?$select=...&$where=phy_state='${STATE}'&$order=dot_number" pagination: { type: offset, offsetParam: "$offset", sizeParam: "$limit", size: 5000, allowShortFirstPage: true } csv: type: csv file: ./data/census_${STATE}.csv 

For Iowa, 58,074 records came back through 12 API pages and 58,074 through the export. Across 25 fields (status, operation, names, address, power units, drivers, mileage, hazmat indicator, docket and safety rating), LogiParity found zero differences. The totals matched too: 26,832 active carriers, 699,129 power units and 224,963 drivers in both. Vermont gave the same result: 8,378 records and no differences.

A clean result is still a result. It means nothing is lost or duplicated at page boundaries, so you can build on either form for this dataset. It does not say the registration data itself is accurate, because both forms come from the same query engine.

Check 2: two publications, different answers

The second comparison joined the SMS census to the active records of the Company Census for Iowa, on 11 shared fields.

  • 25,877 carriers in the SMS file and 26,832 active carriers in the Census; 25,648 matched.
  • 229 carriers appear only in the SMS file, and 1,184 only in the Census.
  • 3,757 field differences on matched carriers: the hazmat flag (1,708), power units (1,137), mileage year (297), mileage (270), drivers (202), and a few dozen ZIP codes, cities, names and operation codes.

That looks alarming until you look at why. A separate script checked each group against other public fields.

Most of it is timing. The SMS file reflects registrations up to about September 24, while the Census reflects November 7. Of the 229 SMS-only carriers, 200 are now inactive or pending in the Census. 140 of the Census-only carriers were added or re-filed after the SMS cutoff. Most mileage, driver and operation differences belong to carriers that filed a newer MCS-150 form between the two snapshots, which is exactly what a six-week gap would produce.

The totals reconcile exactly. The driver total differs by 5,988 between the two files. It breaks down into −6,884 from SMS-only carriers, +879 from Census-only carriers and +17 from value changes on matched carriers. The power-unit total differs by 5,470 and also breaks down exactly. When a total is fully explained, you can stop worrying about it and look at the parts that are not.

Some of it is not explained by timing. About 1,025 active Census carriers in Iowa are missing from the SMS file without a recent filing. Many have no MCS-150 date at all. My guess is that the monthly run selects carriers by criteria that neither dataset shows, but I could not confirm that from the data. For power units, 938 of the 1,137 differences have the same filing date in both files, and I found no explanation that fits.

A hazmat flag is not always the same hazmat flag

The most useful lesson came from the largest group. 1,691 Iowa carriers are marked as hazmat in the Census and not in the SMS file, and only 17 the other way round. 1,661 of these differences have the same MCS-150 filing date in both datasets, so a newer filing does not explain them.

The data dictionaries do. The SMS field means "carrier is subject to the placardable hazardous materials threshold". The Census field is simply "hazmat indicator". Two different questions ended up in columns with similar names.

If your product shows a carrier as hazmat-capable, which of the two did you join? Neither dataset is wrong. They answer different questions, and the join is where the mistake would be made.

What the tool got right and wrong

I would rather show this than hide it.

LogiParity matched the records, reported every missing, extra and changed value, and explained the carrier count completely. Its automatic cause labels were weaker on this data:

  • It called the hazmat difference "likely a stale or lagging value", and suggested checking refresh timing in the newer source. The evidence points to different definitions instead.
  • It labelled repeated numeric changes, such as 1 power unit becoming 2, as "a different vocabulary for the same field". A carrier reporting another truck is a value change, not a vocabulary problem.
  • It stopped on JSON rows where the API simply leaves out empty fields, and it could not compare date-only values. I worked around both, and they are now on the fix list together with the misleading labels.

A tool that diagnoses causes should be tested against real data where the right answer is known. This run gave me five concrete improvements.

Practical tips if you compare Socrata data

  • The JSON API leaves out properties whose value is empty, so make sure your tool treats a missing field as empty rather than as an error.
  • There is no total count in the response. Check completeness with a separate $select=count(*) query using the same filter.
  • Order by the key when paging with $offset, or pages can overlap.
  • Read the data dictionary of both datasets before joining on similar column names.

Limitations

This covers two states on one day, with one version of each dataset, so it makes no national claim. FMCSA was not contacted, and the field definitions come from the dictionaries attached to the datasets. The SMS readme describes its population as active interstate and intrastate hazmat carriers, yet most Iowa rows in it are intrastate non-hazmat carriers, so its documentation may be out of date. I mention this neutrally rather than as an error.

Try it

LogiParity is free and MIT-licensed: github.com/Nutts5796/logiparity

If you work with FMCSA data and know why the power units or the missing carriers differ, I would really like to hear it in the comments. That is exactly the kind of domain knowledge a parity check cannot infer.

The data runs, the supporting analysis and this text were prepared with AI assistance under my direction. I checked the numbers against the reports, and the conclusions are mine.