# OSHA Inspections & Violations Feed (`thoob/osha-enforcement-feed`) Actor

Clean, flat OSHA workplace-safety enforcement records from the official US DOL data: establishment, address, inspection date and type, cited standards, violation severity, and penalties, with a what-changed-since-last-run mode. Billed only per delivered inspection record. No API key needed.

- **URL**: https://apify.com/thoob/osha-enforcement-feed.md
- **Developed by:** [Pono Data](https://apify.com/thoob) (community)
- **Categories:** Developer tools, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.00 / 1,000 inspection records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## OSHA Inspections & Violations Feed

Clean, flat OSHA workplace-safety enforcement records from the official US Department of Labor data. Filter by state, industry (NAICS), inspection type, date, and penalty, get one useful row per inspection with its violations rolled up, and run a changes-only mode that returns just what is new or updated since your last run.

You pay only for a delivered inspection record. Filtered-out rows, unchanged rows in changes mode, and malformed rows cost nothing. There is no per-run start fee.

### You need a free DOL API key

The official DOL data API requires your own key. It is free and takes about two minutes:

1. Register at https://dataportal.dol.gov/registration
2. Copy your key from https://dataportal.dol.gov/api-keys
3. Paste it into the `apiKey` field (or set the `DOL_API_KEY` secret)

The actor never stores or logs your key. Without a key, the run exits cleanly and bills nothing.

### What a record is

One flat row per inspection, decoded from the raw DOL codes:

- establishment and location: `establishment`, `siteAddress`, `siteCity`, `siteState`, `siteZip`
- industry: `naicsCode`, `sicCode`
- the inspection: `inspectionTypeLabel` (Accident, Complaint, Planned, Fatality/Catastrophe, and the rest), `inspectionScopeLabel`, `safetyHealthLabel`, `openDate`, `caseClosedDate`
- violations rolled up: `violationCount`, `seriousViolationCount`, `willfulViolationCount`, `repeatViolationCount`, `currentPenaltyTotal`, `initialPenaltyTotal`, `citedStandards`, `worstViolationType`
- provenance: `sourceUrl`, `retrievedAt`, `confidence`, `dataSource`, and in changes mode `changeType`

Every value is copied or deterministically decoded from the source record. The one-letter DOL codes (for example `F` for FollowUp, `S` for Serious) are carried both raw and as a label. Nothing is guessed.

### Sample output

A real slice (abbreviated), one row per inspection:

| Inspection # | Establishment | City | State | Type | Opened | Violations | Penalty $ |
|---|---|---|---|---|---|---|---|
| 306953084 | CHRISTMAS TREE SHOPS | SALEM | NH | FollowUp | 2005-12-20 | 0 | |
| 125110833 | FIBER RESIN CORP | WARREN | MI | Planned | | | |

Each row also carries `sourceUrl` to the inspection's own detail page on osha.gov.

### Two modes

- **full**: every inspection matching your filter.
- **changes**: only inspections that are new, or whose modification or close date or violation count has changed since this account's last run. The state is tracked per account, so it is your timeline. The first changes run has no baseline, so it returns everything matching once, then tracks deltas from there.

### Filters

- **states**: keep only inspections at a site in these states (two-letter codes).
- **naicsCodes**: keep only establishments whose NAICS code starts with one of these (prefix match, for example 23 for construction).
- **inspectionTypes**: keep only these inspection-type codes.
- **openedSince**: keep only inspections opened on or after this date.
- **minPenalty**: keep only inspections whose total current penalty is at least this many dollars (needs Include violations).
- **includeViolations**: attach the violation rollup to each inspection (on by default).
- **maxRecords**: a cap on how many records a run delivers and bills. The platform spend cap is honored regardless.

State and date are also applied as a server-side narrowing before paging; everything is re-checked on the returned record, so the billed result set is exactly what was delivered.

### What to expect

- The OSHA enforcement data holds millions of inspection and violation records, updated daily. A filter narrows that to the slice you care about.
- The raw API is public and free directly from the DOL with your key. What this actor sells is the flat decoded record, the violation rollup, the filtering, and the per-account change feed, so you do not have to walk the raw code tables or diff them yourself.
- Who uses this: insurers underwriting workplace risk, safety and compliance teams, and M\&A due-diligence on a target's enforcement history.

### Source and scope

- Source: the official DOL Open Data Portal v4 API (`apiprod.dol.gov/v4`), OSHA Inspection (dataset 10334) and Violation (dataset 10338) datasets. This is the successor to enforcedata.dol.gov.
- The records are public federal workplace-safety enforcement records about employers and establishments. They are business-level, with no consumer personal data. Scope is the United States.
- This is a data tool, not legal, insurance, or compliance advice. An enforcement record is a filing, not a verdict; contested citations and penalties can change.

### See also

More clean, pay-only-for-results data tools from Pono Data:

- [Federal Spending Feed](https://apify.com/thoob/federal-spending-feed) - US federal awards from USAspending
- [Regulatory Change Monitor](https://apify.com/thoob/regulatory-change-monitor) - federal rulemaking from the Federal Register

Full catalog: https://apify.com/thoob

# Actor input Schema

## `apiKey` (type: `string`):

Your own free DOL Open Data Portal API key. Register in about two minutes at https://dataportal.dol.gov/registration . The official DOL data API requires a key; this actor never stores or logs it. You can also set it as the DOL\_API\_KEY secret env var instead.

## `states` (type: `array`):

Keep only inspections at a site in these US states (two-letter postal codes, for example CA, TX, NY). Applied as a server-side narrowing and re-checked on the returned record. Leave empty for all states.

## `naicsCodes` (type: `array`):

Keep only inspections whose establishment NAICS code starts with one of these (for example 23 for construction, 31 to 33 for manufacturing, 6221 for general hospitals). Prefix match on the returned record. Leave empty for all industries.

## `inspectionTypes` (type: `array`):

Keep only these inspection-type codes: A=Accident, B=Complaint, C=Referral, D=Monitoring, F=FollowUp, H=Planned, M=Fatality/Catastrophe, and the rest. Filtered on the returned record. Leave empty for all types.

## `openedSince` (type: `string`):

Keep only inspections opened on or after this date (YYYY-MM-DD). Applied as a server-side narrowing and re-checked on the record. Leave empty for no date floor.

## `minPenalty` (type: `integer`):

Keep only inspections whose total current penalty (summed across its live violations) is at least this many dollars. Requires Include violations. Leave empty for no penalty floor.

## `includeViolations` (type: `boolean`):

When on (default), each inspection carries its violation rollup: counts by severity, cited standards, and total penalties. This makes one extra API call per page. Turn off for a faster inspection-only feed.

## `mode` (type: `string`):

full returns every inspection matching your filter. changes returns only inspections that are new, or whose modification/close date or violation count has changed since this account's last run, tracked per account. The first changes run has no baseline, so it returns everything matching once, then tracks deltas.

## `maxRecords` (type: `integer`):

Safety cap on how many inspections this run delivers and bills. 0 means no cap. In changes mode, inspections beyond the cap are not dropped: they are delivered on a later run, never billed twice. The platform spend cap (ACTOR\_MAX\_TOTAL\_CHARGE\_USD) is honored regardless.

## `pageSize` (type: `integer`):

How many inspections to request per API page (1 to 500). Larger pages are fewer requests; the default is a polite middle.

## Actor input object example

```json
{
  "states": [],
  "naicsCodes": [],
  "inspectionTypes": [],
  "includeViolations": true,
  "mode": "full",
  "maxRecords": 1000,
  "pageSize": 100
}
```

# Actor output Schema

## `inspections` (type: `string`):

One row per inspection matching your filter.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "states": [],
    "naicsCodes": [],
    "inspectionTypes": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("thoob/osha-enforcement-feed").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "states": [],
    "naicsCodes": [],
    "inspectionTypes": [],
}

# Run the Actor and wait for it to finish
run = client.actor("thoob/osha-enforcement-feed").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "states": [],
  "naicsCodes": [],
  "inspectionTypes": []
}' |
apify call thoob/osha-enforcement-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=thoob/osha-enforcement-feed",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/VjzFGuIfmr0KTvPu1/builds/QJFfgUHVaXhj6DiSl/openapi.json
