OSHA Inspections & Citations Scraper - Penalties by Company
Pricing
from $2.10 / 1,000 inspections
OSHA Inspections & Citations Scraper - Penalties by Company
OSHA inspections joined with citations from the official DOL API: company, site address, NAICS, inspection type, open and close dates, serious, willful and repeat counts, initial and current penalties and cited standards, newest first. Filter by state, industry and penalty.
Fetch recent federal and state-plan OSHA workplace safety inspections joined with their cited violations, penalty amounts (initialPenaltyUsd and currentPenaltyUsd), gravity counts (Serious, Willful, Repeat), and human-readable CFR safety standards via the official U.S. Department of Labor (DOL) Open Data API v4.
What it does
The Occupational Safety and Health Administration (OSHA) conducts tens of thousands of workplace inspections each year across construction, manufacturing, warehousing, and industrial facilities. In the raw DOL database, inspection metadata (OSHA/inspection) and individual violation citations (OSHA/violation) live in separate endpoints keyed by activity_nr, and safety standards are stored as unformatted 8-character strings (e.g. 19260501).
This Actor:
- Queries
https://apiprod.dol.gov/v4/get/OSHA/inspection/jsonfiltered by worksite state (states), NAICS industry prefix (naicsPrefix), and opening date (openDateFrom). - Batch-fetches matching violation records from
https://apiprod.dol.gov/v4/get/OSHA/violation/jsonbyactivity_nr. - Aggregates violation counts (
violationsCount,seriousCount,willfulCount,repeatCount), sumsinitialPenaltyUsdandcurrentPenaltyUsd, and maps the 30 most-cited OSHA standards to readable labels (e.g.19260501→"1926.501 Fall Protection",19100147→"1910.147 Control of Hazardous Energy (Lockout/Tagout)").
Found a problem or need a field? Open an issue on the Issues tab; we respond quickly.
Who it's for
- Environmental Health & Safety (EHS) consulting and training firms identifying establishments that recently underwent planned, complaint, or referral inspections.
- Industrial safety equipment and PPE distributors matching cited CFR standards (fall protection, respiratory protection, scaffolding, machine guarding, lockout/tagout) to safety hardware needs.
- Commercial insurance underwriters and workers' compensation brokers evaluating workplace safety history by NAICS and geography.
- Workplace safety and labor researchers analyzing penalty trends and enforcement activity.
Input
states(array of strings) — Two-letter US state codes for the inspected worksite. Default:["AZ", "TX"]. Leave empty ([]) for all states.naicsPrefix(string) — NAICS industry code prefix (e.g."23"for Construction,"31"–"33"for Manufacturing). Default:"23". Leave empty ("") for all industries.openDateFrom(string, YYYY-MM-DD) — Earliest inspectionopen_dateto include. Defaults to 365 days.minCurrentPenaltyUsd(integer) — Minimum summedcurrentPenaltyUsdper inspection (0includes recent inspections even before citations are issued). Default:0.violationTypes(array of strings) — Optional filter for violation gravity ("Serious","Willful","Repeat","Other-than-serious"). Default:[].onlyWithCitations(boolean) — Defaulttrue. Skips inspections with no citation items issued yet (citations usually follow the inspection by weeks or months).- Partial results: if the time budget runs out, the DOL API keeps answering 429, the 4,000-inspection safety cap is reached, the source feed looks stale or drifted, or the max charge limit stops the push, the run still returns what it fully checked and the status message starts with PARTIAL and gives the reason. When the reason is on the source side (rate limit, schema drift, stale feed, excluded invalid rows), the message also ends with: If this keeps happening, please open an issue on this actor's Issues tab and we'll fix it fast. A PARTIAL caused only by your own limits (max charge, time budget, safety caps) omits that line — raising the limit is the fix there, not a bug report.
maxScanSeconds(integer) — Time budget, default75. The DOL API is rate-limited; raise this and the run timeout for large pulls.useApifyProxy(boolean) — Defaultfalse(opt-in). The DOL API throttles some shared cloud IPs, including Apify's, and can answer HTTP 429 from the first request. If that happens, turn this on. It uses Apify's shared datacenter proxy on your account: every Apify plan includes it (the Free plan has 5 shared IPs), and its data transfer counts toward your platform usage.onlyOpenCases(boolean) — Keep only inspections wherecloseCaseDateisnull. Default:false.dolApiKey(string, secret, optional) — Your own free DOL Open Data API v4 key from dataportal.dol.gov. If left blank, the Actor reads theDOL_API_KEYenvironment secret configured on the Actor; if neither is set, the Actor fails with a clear message saying so.maxItems(integer) — Maximum inspection rows to return. Default:100.
Example input JSON
{"states": ["AZ", "TX"],"naicsPrefix": "23","openDateFrom": "2026-07-25","minCurrentPenaltyUsd": 0,"violationTypes": [],"onlyOpenCases": false,"maxItems": 200}
Canary input (quick health check)
{"states": ["AZ"],"naicsPrefix": "23","maxItems": 5}
A healthy canary returns 5 rows and ends Complete: 5 rows. It ends PARTIAL only with a stated source-side reason — for example, if DOL has not posted any inspection for the query in over 60 days, or the API rate-limited the scan. Citation lag alone never makes a run PARTIAL: freshness is measured on the newest inspection DOL has posted for your query, before citation filters are applied (see the FAQ below). A canary should never end in an unexplained failure.
Example run options (default max charge $50)
Set a default maximum charge of $50 ("maxTotalChargeUsd": 50) in your run options:
{"maxTotalChargeUsd": 50}
Output
Results are deduplicated by activityNumber and sorted newest first by openDate descending.
| Field | Type | Description |
|---|---|---|
activityNumber | string | Unique OSHA inspection activity number (activity_nr). |
establishmentName | string | null | Name of the inspected business establishment. |
siteStreet | string | null | Inspected worksite street address. |
siteCity | string | null | Worksite city. |
siteState | string | null | Worksite 2-letter state code. |
siteZip | string | null | Worksite postal ZIP code. |
naicsCode | string | null | 6-digit NAICS industry code. |
inspectionType | string | null | Decoded inspection trigger (Planned, Complaint, Referral, Accident, Follow-Up, etc.). |
scope | string | null | Decoded inspection scope (Complete, Partial, Records Only, No Inspection). |
openDate | string | null | Date the inspection opened (YYYY-MM-DD). |
closeCaseDate | string | null | Date the case closed (YYYY-MM-DD) or null if still open. |
unionStatus | string | null | Worksite union representation status (Union or Non-Union). |
ownerType | string | null | Sector classification (Private, Local Government, State Government, Federal Government). |
violationsCount | integer | Total cited violations joined to this inspection. |
seriousCount | integer | Count of Serious (S) violations. |
willfulCount | integer | Count of Willful (W) violations. |
repeatCount | integer | Count of Repeat (R) violations. |
initialPenaltyUsd | number | Summed initial proposed penalty in USD. |
currentPenaltyUsd | number | Summed current penalty in USD (reflects latest post-settlement/contest adjustments). |
citedStandards | array<string> | Human-readable CFR safety standards cited on the inspection. |
inspectionUrl | string | null | OSHA IMIS inspection detail URL for interactive browser lookup. |
Sample output row (synthetic example)
{"activityNumber": "1999999","establishmentName": "EXAMPLE STRUCTURAL BUILDERS LLC","siteStreet": "1200 W INDUSTRIAL PKWY","siteCity": "PHOENIX","siteState": "AZ","siteZip": "85009","naicsCode": "236220","inspectionType": "Planned","scope": "Partial","openDate": "2026-10-12","closeCaseDate": null,"unionStatus": "Non-Union","ownerType": "Private","violationsCount": 2,"seriousCount": 2,"willfulCount": 0,"repeatCount": 0,"initialPenaltyUsd": 24800.0,"currentPenaltyUsd": 17360.0,"citedStandards": ["1926.501 Fall Protection","1926.1053 Ladders"],"inspectionUrl": "https://www.osha.gov/ords/imis/establishment.inspection_detail?id=1999999"}
How pricing works
Pay per result. You only pay for rows returned. Set "maxTotalChargeUsd": 50 in your run options to cap spend automatically.
Data source and terms
- Official source: U.S. Department of Labor Open Data Portal (dataportal.dol.gov).
- Important context on penalties and citations:
- OSHA citations and proposed penalties are often reduced or modified after an informal settlement conference with the OSHA Area Director, or may still be under formal contest before the Occupational Safety and Health Review Commission (OSHRC).
currentPenaltyUsdreflects the latest value recorded in the DOL enforcement feed. - Because citations can take several weeks after
openDateto be issued and posted, very recent inspections may showviolationsCount: 0andcurrentPenaltyUsd: 0.
- OSHA citations and proposed penalties are often reduced or modified after an informal settlement conference with the OSHA Area Director, or may still be under formal contest before the Occupational Safety and Health Review Commission (OSHRC).
- Affiliation disclaimer: This Actor is an independent tool and is not affiliated with or endorsed by the Occupational Safety and Health Administration (OSHA) or the U.S. Department of Labor (DOL).
Compliance
This Actor outputs business establishment names and physical worksite addresses published by the U.S. Department of Labor (no personal contact emails or phone numbers are included). Buyers are responsible for complying with the Telephone Consumer Protection Act (TCPA), the National Do-Not-Call Registry, the CAN-SPAM Act, and all applicable federal and state privacy laws before any business outreach. Do not use this Actor for consumer or individual targeting.
Troubleshooting
- "A DOL API key is required" — Neither the
DOL_API_KEYenvironment secret nor thedolApiKeyinput was set. Add one of them (see FAQ below) and re-run. - "DOL API rejected the API key (HTTP 401/403)" — The configured key is invalid or revoked. Register or regenerate a key at dataportal.dol.gov and update the secret/input.
- Status starts with PARTIAL — The run returned everything it could fully verify and stopped for the stated reason (rate limit, time budget, safety cap, stale or drifted feed, or the max charge limit). Re-run with a narrower window or a higher budget/limit.
- "returned no matching inspections" — The filters matched nothing in the DOL feed. Widen
openDateFrom,states, ornaicsPrefix.
Limits and FAQ
- How do I get a free DOL API key?
Register for a free account at dataportal.dol.gov and paste your API key into the
dolApiKeyinput, or configure theDOL_API_KEYenvironment secret on the Actor. If neither is set, the run fails with instructions; there is no other built-in key. - Why do some recent inspections have 0 violations?
Under the OSH Act, OSHA has up to 6 months from an inspection opening date to issue citations. Keeping
minCurrentPenaltyUsd: 0returns newly opened inspections immediately; raisingminCurrentPenaltyUsd(e.g.5000) filters for inspections where penalty citations have already posted. - How is "stale source" judged?
Freshness is measured on the newest inspection DOL has posted for your query — before the
onlyWithCitations, penalty, and violation-type filters are applied. Because citations trail inspections by weeks to months, the newest cited inspection is routinely old even when the feed is perfectly current, so it is never used for the freshness check. Only if DOL has posted nothing for the query in over 60 days does the run end PARTIAL with a "source data may be stale" note.
Changelog
- v0.3 (2026-10-26): Freshness is now measured on the newest inspection DOL has posted for the query (before citation filters), so normal citation lag no longer makes every run PARTIAL-stale; the stale threshold is 60 days. The Issues call-to-action is only appended to source-caused PARTIALs, not to PARTIALs caused by your own limits (max charge, time budget, safety caps). Runs now fail when more than 20% of collected rows fail output validation. The schema-drift sentinel also catches value-level drift (a mapped field present but null/empty across a page, e.g. every
estab_namenull), with a stricter threshold on identity fields. More robust source parsing:delete_flagis read as deleted only for explicit affirmative values, violation gravity accepts full-word encodings ("Serious", "Willful", "Repeat") as well as the S/W/R codes, non-numeric penalty values are counted and reported instead of silently summed as $0, duplicate citation rows are deduplicated, the citation pagination cap notes itself, and the time budget is enforced during citation fetching too. Non-string inputs now fail with a clear message instead of crashing. - v0.2 (2026-10-26): The Actor now reads the
DOL_API_KEYenvironment secret (the per-rundolApiKeyinput remains as an optional fallback); v0.1.6 as shipped required the input key and ignored the secret. Added per-row output schema validation with counted exclusions, a schema-drift sentinel on both DOL endpoints, a freshness check, the verbatim Issues call-to-action on PARTIAL statuses (including the charge-limit exit, now a proper PARTIAL), and an honest fail (instead of "no matches") when collected inspections must be dropped. - v0.1 (2026-10-23): Initial release with DOL Open Data API v4 inspection/violation join and Top-30 CFR standard label mapping.