OSHA Safety Search — establishment inspection records avatar

OSHA Safety Search — establishment inspection records

Pricing

from $13.40 / 1,000 resolved safety records

Go to Apify Store
OSHA Safety Search — establishment inspection records

OSHA Safety Search — establishment inspection records

Look up an establishment's OSHA inspection record by name or inspection number in the DOL's official OSHA enforcement data: site, dates, NAICS, inspection codes, violation counts and penalty totals. Official source. No API key. Pay per record.

Pricing

from $13.40 / 1,000 resolved safety records

Rating

0.0

(0)

Developer

NexGen Watch

NexGen Watch

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

Share

📚 OSHA Safety Search — establishment inspection records

OSHA inspection records by establishment name or inspection number, from the U.S. Department of Labor's own OSHA enforcement data. Give it company names or OSHA activity numbers; for each one you get the inspection: establishment name and site address, open and close dates, NAICS and SIC codes, the inspection type, scope, union and owner codes as OSHA records them, employees at the site, and the citation summary — violation count by type code and the initial and current penalty totals in US dollars.

Official source. No API key. Pay per record. The data is the DOL's public bulk download of the OSHA inspection and violation tables (data.dol.gov), refreshed by DOL daily. Every row carries data_as_of, the date of the DOL file it came from.

Why it changed (2026-10-03). This actor used to read OSHA's IMIS establishment search pages. Since late September 2026 those pages answer 403/405 to every automated request, so the actor failed (loud and unbilled) on every run. It now searches an index built from the same enforcement data that IMIS shows, published by DOL as bulk files.

Output is one safety_record row per result; billing is pay-per-event, the value event being one resolved safety record (a $0.02 start fee per run, then $0.02 per resolved safety record). Source: data.dol.gov, www.osha.gov.

Who buys this

Buyers usually search for OSHA inspections or OSHA violations.

  • Sales and lead-generation teams building lists from OSHA inspections.
  • KYB, onboarding and compliance teams checking OSHA violations.
  • Market researchers and data teams that need the official record as rows.

📊 Sample Output

OSHA Safety Search — establishment inspection records sample output — a table of real resolved safety record rows (input, resolved, establishment_name, establishment_site) from run RJYxcUcdv5pgFHEGq on build 0.1.28

Real rows from run RJYxcUcdv5pgFHEGq on build 0.1.28 (2026-10-03), the same input as the Quick start below — every value is as the source published it (emails masked, long text shortened):

inputresolvedestablishment_nameestablishment_sitesite_addressdata_as_of
348668104TrueJMG CUSTOMS METALS SHOP INC7318 NW 79TH TERRACE, MEDLEY, FL 331667318 NW 79TH TERRACE2026-10-02T11:04:28Z
AmazonFalse2026-10-02T11:04:28Z

The run finished with the status message: PARTIAL: 1 resolved (1 ambiguous refusals, 0 unavailable) of 2; data as of 2026-10-02T11:04:28Z | safety-record billable=1 | safety-record charged=1

✅ What you get

Each row is flat JSON with these fields (from the dataset schema and the sample run; a field the source does not publish for a given row is null):

  • record_type (string) — e.g. safety_record
  • input (string/null) — e.g. 348668104
  • resolved (boolean/null) — e.g. True
  • found (boolean/null) — e.g. True
  • activity_id (string/null) — e.g. 348668104
  • establishment_name (string/null) — e.g. JMG CUSTOMS METALS SHOP INC
  • establishment_site (string/null) — e.g. 7318 NW 79TH TERRACE, MEDLEY, FL 33166
  • site_address (string/null) — e.g. 7318 NW 79TH TERRACE
  • site_city (string/null) — e.g. MEDLEY
  • state (string/null) — e.g. FL
  • site_zip (string/null) — e.g. 33166
  • date_opened (string/null) — e.g. 2025-12-30
  • close_conference_date (string/null) — e.g. 2025-12-30
  • close_case_date (string/null) — null in every sample row
  • case_modified_date (string/null) — e.g. 2026-10-01
  • naics (string/null) — e.g. 332999
  • sic (string/null) — null in every sample row
  • inspection_type (string/null) — e.g. C
  • scope (string/null) — e.g. B
  • union_status (string/null) — e.g. B
  • safety_or_health (string/null) — e.g. S
  • owner_type (string/null) — e.g. A
  • employees_at_site (integer/null) — e.g. 3
  • reporting_office_id (string/null) — e.g. 0418800
  • violations_total (integer/null) — e.g. 8
  • violations_by_type (object/null) — e.g. {"S": 8, "W": 0, "R": 0, "O": 0}
  • penalty_initial_usd (number/null) — e.g. 16143
  • penalty_current_usd (number/null) — e.g. 16143
  • last_citation_date (string/null) — e.g. 2026-04-17
  • detail_url (string/null) — e.g. https://www.osha.gov/ords/imis/establishment.inspection_detail?id=348668104
  • data_as_of (string/null) — e.g. 2026-10-02T11:04:28Z
  • source (string/null) — e.g. U.S. Department of Labor enforcement data (data.dol.gov), OSHA inspection + viol
  • unavailable_reason (string/null) — e.g. ambiguous_refusal_with_candidates
  • establishment_query (string/null) — e.g. Amazon
  • match_count (integer/null) — e.g. 819
  • candidates (array/null) — e.g. [{"activity_id": "349167437", "establishment_name": "AMAZON.COM SERVICES LLC - P
  • refusal (string/null) — e.g. 'Amazon' is ambiguous: 819 OSHA inspections match (newest first below). This is
  • note (string/null) — null in every sample row

⚙️ Sample inputs

1. Quick start — the Store example (this is what the sample above came from)

{
"establishments": [
"348668104",
"Amazon"
]
}

The sample run charged exactly: 1 × $0.02 apify-actor-start + 1 × $0.02 safety-record = $0.04 on the Free tier — every delivered row was billed.

This actor takes no size cap or filter beyond the input above, so the Store example is the one input to run; put it on a schedule to keep the data current.

🧾 JSON sample record

One real record from run RJYxcUcdv5pgFHEGq, exactly as it lands in the dataset (emails masked, long text shortened):

{
"record_type": "safety_record",
"input": "348668104",
"resolved": true,
"found": true,
"activity_id": "348668104",
"establishment_name": "JMG CUSTOMS METALS SHOP INC",
"establishment_site": "7318 NW 79TH TERRACE, MEDLEY, FL 33166",
"site_address": "7318 NW 79TH TERRACE",
"site_city": "MEDLEY",
"state": "FL",
"site_zip": "33166",
"date_opened": "2025-12-30",
"close_conference_date": "2025-12-30",
"close_case_date": null,
"case_modified_date": "2026-10-01",
"naics": "332999",
"sic": null,
"inspection_type": "C",
"scope": "B",
"union_status": "B",
"safety_or_health": "S",
"owner_type": "A",
"employees_at_site": 3,
"reporting_office_id": "0418800",
"violations_total": 8,
"violations_by_type": {
"S": 8,
"W": 0,
"R": 0,
"O": 0
},
"penalty_initial_usd": 16143,
"penalty_current_usd": 16143,
"last_citation_date": "2026-04-17",
"detail_url": "https://www.osha.gov/ords/imis/establishment.inspection_detail?id=348668104",
"data_as_of": "2026-10-02T11:04:28Z",
"source": "U.S. Department of Labor enforcement data (data.dol.gov), OSHA inspection + violation tables",
"unavailable_reason": null
}

🔧 How it works

Transport. Plain HTTPS from the Apify platform, no proxy.

Charging. Each resolved safety record is charged at the moment it is pushed (safety-record). Refusals and notices are pushed to the dataset too, uncharged, so the dataset can hold more rows than were charged; the run's status message gives both counts.

Source. DOL's public OSHA bulk files: https://data.dol.gov/data-catalog/OSHA/inspection/OSHA_inspection.zip (about 5.2 million inspections) and https://data.dol.gov/data-catalog/OSHA/violation/OSHA_violation.zip (about 13.3 million citation lines). No login, no key. A weekly publisher job reads both files (only when DOL has published a newer file), adds up each inspection's citations (deleted citations excluded), and stores a compact index split into small pieces. A run reads one index piece per query, so a typical run takes a few seconds.

Matching. A number is looked up as an OSHA activity number (the inspection number, nine digits for recent inspections). A name matches establishments whose name starts with it, after removing punctuation and a leading "The" ("Amazon" matches "AMAZON.COM SERVICES LLC"); add a two-letter state to narrow (Acme, TX). One match is a record. No match is a sourced "not found" record. Several matches give a refusal listing up to 30 candidates, newest first, with their activity numbers, and that refusal is not charged.

Codes. Inspection type, scope, union status, owner type and safety/health are given as the one-letter codes OSHA publishes; violation counts are keyed by OSHA's violation type code (S, W, R, O). This actor does not translate the codes into words, because DOL's code list sits behind its API key. OSHA's own field definitions are at osha.gov/data/inspection-detail-definitions.

What is not charged. Ambiguous names (refusal with candidates), an IMIS-style id with a decimal (e.g. 1908104.015) that is not an activity number, empty queries, and index outages are delivered as notices and never charged. If nothing in a run resolves, the run FAILS and charges nothing.

Freshness. data_as_of on every row is the DOL file date. Recent inspections can still be open: penalties and citations change until the case closes (close_case_date). detail_url is OSHA's inspection page for that activity number; this actor builds the link but does not read it.

What is not done. No login, no cookie or CAPTCHA bypass, no private or personal-account data, no browser automation.

💰 Pricing example

EventFreeBronzeSilverGold
Actor Start (apify-actor-start)$0.02$0.02$0.02$0.02
Resolved safety record (safety-record)$0.02$0.018$0.016$0.0134

Worked at the live Free-tier price:

  • 2 resolved safety records: $0.02 start + 2 × $0.02 = $0.06
  • 25 resolved safety records: $0.02 start + 25 × $0.02 = $0.52
  • 100 resolved safety records: $0.02 start + 100 × $0.02 = $2.02

A run that delivers zero rows charges the $0.02 start fee only. A BLOCKED run (source refused) fails loud and charges no value event. The start fee is charged once per GB of run memory; the default run memory is 1024 MB.

Yield on the sample run: PARTIAL: 1 resolved (1 ambiguous refusals, 0 unavailable) of 2; data as of 2026-10-02T11:04:28Z | safety-record billable=1 | safety-record charged=1.

This actor reads public, logged-out pages and feeds published by data.dol.gov, www.osha.gov. It collects only what the source publishes to any visitor, identifies itself, and does not access accounts, private data or anything behind authentication. Use the output in line with the source's terms and your local law; the intended use is B2B research and monitoring.

❓ FAQ

Q: Do I need an API key or a login?
A: No. The source (data.dol.gov, www.osha.gov) is read logged-out; the input schema has no key field and the actor carries no secrets.

Q: Why did my run return 0 rows?
A: Read the run's status message. GENUINE_EMPTY means the source was read and had nothing in scope for your input; BLOCKED means the source refused and the run failed without billing a value event — retry later or narrow the input. A zero-row run bills the start fee only.

Q: How fresh is the data?
A: Every run reads the source live at run time; nothing is cached between runs. Put it on a schedule for a continuous feed.

Q: What formats can I export?
A: The dataset downloads as JSON, CSV, Excel, XML or RSS from the run's Dataset tab or the Apify API, and any run can push to a webhook or integration.

Q: How is this different from the other public records lookups actors?
A: Same output shape and billing model; this one covers data.dol.gov, www.osha.gov. The siblings under Related Actors cover the other sources or slices — run several on one schedule for a combined feed.

Q: Are there rate limits?
A: The actor paces itself against the source; there is no per-buyer limit beyond your Apify plan's concurrency.

🆘 Troubleshooting

  • Run FAILED with BLOCKED → the source refused the request or changed its page shape → nothing was billed beyond the start fee; retry after a while, and if it persists open an Issue with the run id.
  • Fewer rows than expected → the source had fewer items in scope → widen the input.
  • Input validation error on start → a field is outside the schema's allowed values → start from the Quick start block and change one field at a time.
  • Run TIMED-OUT → a very wide request on a slow day → raise the run timeout in Run options or narrow the input; what was delivered before the timeout is still in the dataset.

⭐ Found this useful?

If this actor saved you a manual check, a quick review on the Apify Store helps other teams find it. Feature request or a source that changed? Open it from the Issues tab — every one is read.