OSHA Injury & Illness Data (ITA Form 300A) Rate Monitor avatar

OSHA Injury & Illness Data (ITA Form 300A) Rate Monitor

Pricing

from $4.40 / 1,000 establishment injury & illness records

Go to Apify Store
OSHA Injury & Illness Data (ITA Form 300A) Rate Monitor

OSHA Injury & Illness Data (ITA Form 300A) Rate Monitor

Establishment-level OSHA Form 300A injury and illness data from the OSHA Injury Tracking Application (ITA), CY2016 onward. Total Case Rate and DART injury rates from OSHA's own formula, a peer-industry median benchmark computed from the filers themselves, and a year-over-year delta. Keyless.

Pricing

from $4.40 / 1,000 establishment injury & illness records

Rating

0.0

(0)

Developer

Kyle Maloney

Kyle Maloney

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

19 hours ago

Last modified

Share

OSHA Injury & Illness Data (ITA Form 300A) — establishment rates, industry benchmark, and year-over-year delta

Establishment-level workplace injury and illness data straight from OSHA's Injury Tracking Application (ITA), calendar years 2016 through the current filing year, with the Total Case Rate (TCR) and DART rate computed using OSHA's own published formula, a peer-industry median computed from the filers themselves, and a year-over-year delta.

Keyless. No login, no API key, no scraping of a search UI — this reads the bulk Form 300A files OSHA publishes on its own data page.

Every March 2, employers above OSHA's size and industry thresholds must electronically submit their prior-year Form 300A summary. OSHA then publishes the whole national file. That deadline is the recurring event this actor exists to serve: run it after each March filing window to see who filed, what their rates look like against their industry, who got worse, who stopped filing.


Who this is for

  • EHS / safety consultants and brokers — benchmark a prospect or a client against every other ITA filer in the same NAICS industry, nationally, in the same year. "Your TCR is 11.4 against an industry median of 3.2" is a sales conversation.
  • Workers' comp underwriters and risk engineers — an employer-reported, government-published injury rate per establishment, with the denominators (hours worked, employees) visible so you can audit the arithmetic yourself.
  • Union organizers, plaintiff-side researchers, and journalists — establishment-level injury counts, deaths, and days away from work, by employer name and street address.
  • Corporate safety teams — pull your own establishments' filings back out, compare sites against each other and against the industry, and check what OSHA actually has on file for you.
  • Supply-chain and vendor-risk teams — screen contractors and suppliers by name across a state before you sign.
  • AI agents — clean, fully described fields with an explicit rate_basis on every row, so an agent can tell "rate is 0" from "there is no rate".

What makes this different

Every OSHA actor on the Apify Store reads the inspection and enforcement database (citations, penalties, violations). This one reads the injury file — a completely different OSHA dataset that nobody sells. An inspection record tells you OSHA showed up. This tells you how many people got hurt.

It also does the two things a raw dump does not:

  1. Computes the rates. OSHA publishes counts and hours, not rates. TCR and DART are computed here with OSHA's published formula and the arithmetic is spelled out on every row.
  2. Benchmarks against the peer group. For each establishment, the median TCR of every other ITA filer nationally in the same NAICS prefix and the same year, plus this establishment's percentile within that group. The peer group falls back 6-digit → 4-digit → 2-digit until it has at least 20 filers, and the level it actually used ships on the row.

Example input

{
"states": ["CO"],
"years": ["2024"],
"naicsPrefixes": ["23"],
"onlyWithRecordableCases": true,
"maxResults": 300
}

Year-over-year change for every Colorado hospital:

{
"states": ["CO"],
"years": ["2024"],
"mode": "delta",
"naicsPrefixes": ["622"]
}

One employer's whole footprint in a state:

{
"states": ["TX"],
"years": ["2024"],
"nameContains": "Kroger"
}

Input fields

FieldRequiredWhat it does
statesyesTwo-letter state codes. Matching is case-insensitive because OSHA's own file carries mixed-case spellings in some years. Also accepts AS, GU, MP, PR, VI, AA, AE, AP.
yearsyesCalendar years, e.g. ["2024"]. Max 3 per run. The published year list is read live from OSHA's data page every run; an unpublished year fails loudly with the list of years that do exist.
modenoestablishments (default) or delta.
naicsPrefixesno2- to 6-digit NAICS prefixes. Prefix matching, not exact-code matching — see the NAICS note below.
nameContainsnoCase-insensitive substring across both establishment_name and company_name.
minEmployeesnoMinimum annual average employees. An establishment that reported no employee count is excluded, because an unreported count is not a small count.
onlyWithRecordableCasesnoKeep only establishments that reported at least one case or death. Off by default — a zero-case filing is a real answer.
maxResultsnoHard cap on emitted rows, and therefore on what you are billed. Default 500.

Output fields

One row per establishment per calendar year (mode: "establishments"), or one row per establishment (mode: "delta"). 84 fields; every one of them is documented in the dataset schema and visible on the Store page.

Identity and location

record_type · run_mode · filing_year · establishment_id · record_id · establishment_name · company_name · street_address · city · state · zip_code · ein

establishment_id is OSHA's own stable identifier and is the documented key for linking to OSHA's case-detail files.

Industry and size

naics_code · naics_vintage_year · naics_vintage_raw · industry_description · establishment_type_code · size_code · size_code_peer_count · size_code_peer_median_employees · annual_average_employees · total_hours_worked

size_code ships as OSHA's raw code with no invented label, because the code set is not stable (see gotchas). size_code_peer_median_employees gives you what the code actually means in this file: the median employee count of every establishment carrying the same code.

Reported counts (OSHA Form 300A columns G–M)

had_recordable_cases · no_injuries_illnesses_code · total_deaths (G) · total_dafw_cases (H) · total_djtr_cases (I) · total_other_cases (J) · total_recordable_cases (H+I+J) · dart_cases (H+I) · total_dafw_days (K) · total_djtr_days (L) · total_injuries (M1) · total_skin_disorders (M2) · total_respiratory_conditions (M3) · total_poisonings (M4) · total_hearing_loss (M5) · total_other_illnesses (M6)

Computed rates

total_case_rate · dart_rate · dafw_case_rate · rate_basis · rate_is_implausible · rate_formula · data_quality_flags

Total Case Rate (TCR) = (H + I + J) x 200,000 / hours worked
DART rate = (H + I) x 200,000 / hours worked

That is OSHA's published Rate Calculation, verbatim. 200,000 is 100 full-time-equivalent workers for a year.

rate_basis is the honest part. It is one of computed, hours_not_reported, hours_reported_zero, case_counts_incomplete — or, in delta mode, establishment_absent_in_current_year / establishment_absent_in_prior_year. When a rate cannot be computed it is null, never 0.

Industry benchmark

industry_benchmark_naics_level · industry_benchmark_naics_prefix · industry_benchmark_peer_count · industry_median_total_case_rate · total_case_rate_vs_industry_median · total_case_rate_percentile_in_industry · industry_benchmark_note

Delta mode only

prior_filing_year · filing_status · prior_annual_average_employees · prior_total_hours_worked · prior_total_recordable_cases · prior_total_deaths · prior_total_case_rate · total_case_rate_change · total_case_rate_change_pct · rate_direction · prior_rate_basis · prior_dart_rate · stopped_filing_note · delta_current_year · delta_prior_year · prior_data_source_file · prior_data_vintage_last_modified · prior_national_filers_scanned

filing_status is continuing, new_filer or stopped_filing.

Provenance and completeness

submitted_date · change_reason · data_source_url · data_source_file · data_vintage_last_modified · source_file_changed_since_last_run · national_filers_scanned · optional_columns_present · matched_rows_total · max_results · results_truncated · retrieved_at · in_ita_scope_note · data_quality_note

source_file_changed_since_last_run is null on the first run for a given scope — never false. Having never looked is not the same as nothing having changed.


Honesty and limitations — read this before you use a number

These are not editorial hedges. They come from measuring the live files, and several of them ship as text on every row.

Absence from this dataset is not evidence that an establishment had no injuries. OSHA collects Form 300A data only from establishments with 250+ employees not in the exempt-industry list (29 CFR 1904 Subpart B App A), and from establishments with 20–249 employees in the 300A Table (29 CFR 1904 Subpart E App A). Most US workplaces are out of scope entirely. OSHA also states it has not removed data submitted by establishments that were not required to submit, so the file contains some voluntary filers too. This sentence ships on every row as in_ita_scope_note.

OSHA does not validate what employers report. OSHA's own guidance says concluding an establishment is the "most dangerous" or "least dangerous" solely from these rates would be inappropriate. This ships on every row as data_quality_note. Concretely, in the CY2024 file: one establishment reports 41,092,597 employees, another reports 862,847,000,000 hours worked, 763 rows compute a TCR above 200 per 100 workers, and 1,574 rows report zero hours. None of that is corrected here — it is flagged in data_quality_flags, and flagged rows sort below sound ones so a truncated result set is not a page of data-entry errors.

The benchmark is not a BLS SOII estimate. It is the median TCR of the other ITA filers in the same NAICS prefix and year, computed from the same file. ITA filers are a size- and industry-selected subset of US workplaces, so the benchmark is not generalizable to the whole worker population. For generalizable national estimates, use the BLS Survey of Occupational Injuries and Illnesses. This ships on every row as industry_benchmark_note.

stopped_filing is not evidence of closure. It means an establishment_id present in the earlier year is absent from the later one. That can mean closure — or falling below the reporting threshold, or an acquisition, or a changed identifier, or simply not filing. This ships on every delta row as stopped_filing_note.

A run that matches nothing succeeds with zero rows. That is the answer, and it costs you nothing beyond the tiny actor start. A run that cannot answer — OSHA unreachable, a file that failed the live drift gate, a year OSHA does not publish, an input that cannot be interpreted — fails loudly and bills nothing.

Not in v1: case-detail (Form 300/301) data. OSHA also publishes per-case detail for CY2023 onward, including AI-assigned OIICS injury codes for 2023–2024 and free-text incident narratives. It is a much larger and structurally different product (the CY2025 case file alone is a 422 MB uncompressed CSV with 39 columns, and OIICS codes are present on 2023–2024 but not yet on 2025). It is deliberately not merged in here rather than half-supported. establishment_id on every row is the join key when it ships.


What was measured in the source, and why the code looks the way it does

Every item below was measured live on 2026-09-03 against the published files and is pinned by an offline fixture.

  • no_injuries_illnesses is coded the opposite way to its name. Code 1 means the establishment did record cases; code 2 means it recorded none. Measured across CY2024: code 1 → 227,666 rows with cases and 13 without; code 2 → 170,941 rows with zero cases and zero with cases. A naive Boolean() or === 1 reading inverts the meaning on 398,607 of 398,620 rows. A live gate asserts this mapping on every run, so an OSHA recoding fails the run rather than silently inverting every answer.
  • The file URLs change naming convention almost every yearITA_300A_Summary_Data_2024_through_12-31-2025.zip, ITA-data-cy2022.zip, ITA-Data-CY-2020.zip, ITA%20Data%20CY%202019.zip — across two directories, and the current year is published as a bare CSV, not a zip. URLs are scraped from OSHA's data page on every run and never guessed.
  • The CSV entry name inside each zip also differs every year (ITA Data CY 2016.csv, CY 2022.csv, ITA_300A_Summary_Data_2024_through_12-31-2025_v2.csv), so the entry is selected by extension.
  • Column order differs between years and CY2024 added a 32nd column (naics_year). Columns are addressed by name; a positional parser reads the wrong column for at least two years.
  • CY2022 carries a UTF-8 BOM; the other years do not.
  • CY2022 carries 24 mixed-case state spellings (Fl on 50 rows, Co, ca, Tx, ny, …) across 85 distinct values. A case-sensitive state filter silently drops those establishments.
  • Three NAICS vintages coexist in one file — CY2024 holds 2022 (222,316 rows), 2012 (164,137), 2017 (11,964) codes plus a "0" sentinel. Industry filtering is by prefix, and the "0" sentinel is never published as a year.
  • size is not the documented three-value code. CY2024 carries five values and 168,310 of 398,620 rows read 21; the same code covers 227 rows in CY2022, and the employee bands behind codes 2 and 3 differ between the two years. No label is invented — the raw code ships with a measured peer-median employee count.
  • CY2016 publishes no EIN at all (blank on all 214,978 rows); ~11% of CY2024 rows are blank and 84 CY2022 values are non-numeric. Blank is null, never 0.
  • OSHA revises published years in place — CY2016 through CY2020 all carry a 2025-11-25 Last-Modified. Every row publishes the file's own Last-Modified as its vintage.
  • www.osha.gov answers HTTP 403 with an HTML body to a non-browser User-Agent on every file path, including paths that do not exist, so a bot-gate 403 is indistinguishable from a deleted file. It also 403s HEAD on files it serves at 200 to GET.

Cost — read this first

$8.00 per 1,000 result rows ($0.008 per row), on Apify's pay-per-result model, with graduated discounts on the paid plans (Bronze −20%, Silver −30%, Gold −45%, Platinum −60%, Diamond −70%). One emitted row = one billed result. There is no per-run fee beyond Apify's tiny actor-start event.

Measured row counts so you can price a run before you make it (CY2024 file, 398,620 establishments nationally):

ScopeRows matchedCost at list price
Colorado, all industries7,243$57.94 uncapped — use maxResults
Colorado, maxResults: 500 (the default)500$4.00
Colorado, construction only (naicsPrefixes: ["23"])~1,000~$8.00
Colorado, one 4-digit industry200–400$1.60–$3.20
One employer by nameContains in one state1–60under $0.50

maxResults defaults to 500, so a default run costs at most $4.00. Every emitted row carries matched_rows_total and results_truncated, so you always know whether the cap bit.

A run that fails — bad input, OSHA unreachable, drift gate tripped — emits nothing and bills nothing.


Use as an MCP tool

This actor is callable by AI agents (Claude, Cursor, Windsurf, any MCP client) through Apify's hosted MCP server. Billing is unchanged when it is called as a tool, and a run that cannot answer fails without billing.

Endpoint: https://mcp.apify.com/?actors=malonestar/osha-ita-injury-illness-establishment-monitor

Claude Desktop / Claude Code / Cursor config:

{
"mcpServers": {
"osha-injury-data": {
"url": "https://mcp.apify.com/?actors=malonestar/osha-ita-injury-illness-establishment-monitor",
"headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }
}
}
}

A worked agent prompt:

"Using the OSHA ITA tool, pull every Colorado construction establishment (NAICS 23) that filed a CY2024 Form 300A and recorded at least one case. Rank them by how far their Total Case Rate sits above their own industry's median, and tell me which ones have a rate_basis other than computed so I know which rankings to distrust."

Chaining with the rest of the fleet — an agent can load several of these at once:

https://mcp.apify.com/?actors=malonestar/osha-ita-injury-illness-establishment-monitor,malonestar/dol-enforcement-rollup,malonestar/warn-layoff-aggregator

That combination answers a whole employer-risk question in one agent turn: OSHA-reported injury rates, DOL wage-and-hour enforcement history, and WARN-Act layoff notices for the same employer.

  • dol-enforcement-rollup — US Department of Labor Wage & Hour enforcement cases, penalties and back wages by employer. The enforcement half of the same employer-risk picture.
  • warn-layoff-aggregator — state WARN-Act mass-layoff and closure notices. Useful next to filing_status: stopped_filing, which on its own is not evidence of closure.
  • epa-tri-facility-release-rollup — EPA Toxics Release Inventory chemical releases per facility, for the environmental side of the same industrial sites.
  • epa-rcra-hazwaste-generator-rollup — RCRA hazardous-waste generation by handler.
  • license-verifier — professional and occupational licence verification across 19 boards in 9 states.

FAQ

Where does this data come from? OSHA's Injury Tracking Application, published at https://www.osha.gov/Establishment-Specific-Injury-and-Illness-Data. It is public, keyless bulk data. This actor reads OSHA's own files directly; it does not scrape a search interface.

How is the injury rate calculated? (number of cases x 200,000) / employee hours worked, which is OSHA's published formula. TCR uses Form 300A columns H + I + J; DART uses H + I. rate_formula ships on every row.

Why is total_case_rate null on some rows? Because it could not be computed. Check rate_basis: the establishment reported zero hours worked, reported no hours at all, or its case counts were incomplete. A null rate is never presented as a zero rate.

Does a high rate mean an employer is dangerous? No, and OSHA says so explicitly. Rates depend on self-reported hours and counts that OSHA does not validate, and small establishments produce volatile rates. Use industry_benchmark_peer_count, rate_is_implausible and data_quality_flags before drawing a conclusion.

Why is my company not in the results? Most likely it is not required to file. OSHA only collects Form 300A data above specific employee-count and industry thresholds. Absence here is not evidence of no injuries.

How current is the data? Employers file by March 2 for the prior calendar year, and OSHA publishes shortly after. The actor reads the published-year list live on every run and reports each file's Last-Modified as data_vintage_last_modified. OSHA also revises historical years in place, which is why the vintage ships on every row.

Can I get individual injury case details, not just the annual summary? Not in v1 — see the limitations section. establishment_id is the documented join key for when it ships.

How do I keep the cost down? Filter. naicsPrefixes, nameContains and minEmployees all narrow the result set before anything is billed, and maxResults is a hard cap enforced by a single audited code path with a pre-push tripwire.