# EPA ECHO Facility Violations and Enforcement API (`transparent_meteorite/epa-echo-facility-violations`) Actor

Find facilities in violation of the Clean Air Act, Clean Water Act or RCRA from the free EPA ECHO web services: address, NAICS, quarters in noncompliance, inspections, enforcement, penalties and a compliance-risk score. No login.

- **URL**: https://apify.com/transparent_meteorite/epa-echo-facility-violations.md
- **Developed by:** [Detroit Web Agent - Open Data](https://apify.com/transparent_meteorite) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 40.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.30 / 1,000 facility rows

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## EPA ECHO Facility Violations and Enforcement

**EPA ECHO facility violations** for the states you choose: Clean Air Act, Clean Water Act and hazardous waste (RCRA) facilities with a current violation, with compliance status, quarters in noncompliance, inspections, formal enforcement actions, penalties and a 0-100 compliance-risk score.

Pull regulated facilities that are out of compliance with the Clean Air Act, the Clean Water Act or the hazardous waste law (RCRA) into one clean table. Each row has the facility name and address, state, industry (NAICS), program, current compliance status, quarters in noncompliance, last inspection date, formal enforcement actions, penalties in dollars, the EPA registry ID, a link to the EPA ECHO report and a simple compliance-risk score. Data comes from the free public EPA ECHO web services. No login, no proxy, no personal data: these are facility-level records only.

### What is EPA ECHO Facility Violations and Enforcement?

Find facilities in violation of the Clean Air Act, Clean Water Act or RCRA from the free EPA ECHO web services: address, NAICS, quarters in noncompliance, inspections, enforcement, penalties and a compliance-risk score. No login. Run it from the Apify Console, the API or a schedule, and export the results as JSON, CSV, Excel or HTML.

### Why use it

- **Official source.** Data is EPA ECHO, the public compliance database run by the agency.
- **Three programs, one table.** Air, water and hazardous waste in the same shape, with ISO dates.
- **Repeatable.** Fixed filters and a fixed score, so runs can be compared month to month.

### Output

One row per facility and program:

| Field | Meaning |
|---|---|
| `facilityName`, `address`, `city`, `state`, `zip`, `county` | The facility and where it is. |
| `program`, `programDetail` | CAA, CWA or RCRA, plus program details such as permit type or generator size. |
| `naicsCode`, `naicsDescription` | Industry code and name when EPA has one. |
| `complianceStatus`, `inViolation`, `significantViolation` | Current EPA status and two simple flags. Significant means high priority (air) or significant noncompliance (water, waste). |
| `quartersInNoncompliance` | Quarters in noncompliance out of the last 12. |
| `lastInspectionDate`, `inspectionCount` | Last inspection (air uses the last compliance evaluation) and how many. |
| `formalEnforcementActions`, `lastFormalEnforcementDate` | Formal actions on record. The water service gives only the last date, so the count is empty for CWA rows. |
| `penaltiesUsd`, `lastPenaltyDate` | Penalties recorded in dollars and the latest date. |
| `complianceRiskScore`, `riskLevel` | 0 to 100 score and high, medium, low or none. |
| `registryId`, `sourceId`, `echoUrl` | EPA registry ID, the program permit or site ID and the EPA ECHO facility report link. |
| `scrapedAt` | When the run read the data. |

### Sample output

```json
{
  "facilityName": "ARBOR HILLS LANDFILL, INC.",
  "program": "CAA",
  "city": "NORTHVILLE",
  "state": "MI",
  "naicsCode": "221118 562212",
  "complianceStatus": "High Priority Violation",
  "quartersInNoncompliance": 12,
  "lastInspectionDate": "2026-09-01",
  "formalEnforcementActions": 3,
  "penaltiesUsd": 730109,
  "complianceRiskScore": 100,
  "riskLevel": "high",
  "registryId": "110015815402",
  "echoUrl": "https://echo.epa.gov/detailed-facility-report?fid=110015815402"
}
```

### Input

| Field | What it does |
|---|---|
| `states` | Two-letter state codes, for example `MI`, `OH`. Default `MI`. |
| `programs` | `CAA` (air), `CWA` (water permits), `RCRA` (hazardous waste). Default: all three. |
| `onlyInViolation` | Keep facilities with a current violation or quarters in noncompliance. Default on. |
| `minRiskScore` | Optional 0 to 100 threshold. |
| `majorOnly` | Air and water only: keep major sources and major permits. |
| `nameContains` | Optional text that must appear in the facility name. |
| `maxItems` | Stop after this many rows, highest risk first. Default 100. |

Sample input:

```json
{
  "states": ["MI", "OH"],
  "programs": ["CAA", "CWA"],
  "onlyInViolation": true,
  "minRiskScore": 50,
  "maxItems": 200
}
```

### Pricing

Pay per event. You pay a small fixed amount per facility row delivered, listed on the Pricing tab, plus a tiny start fee per run. You can set a maximum cost per run in the run options.

### What does this Actor do?

It calls the EPA ECHO air, water and hazardous waste facility services for the states you choose, reads every active facility in each program, keeps the ones with a current violation (or all of them if you prefer), scores each one and sorts the highest risk first. The actor reports what EPA publishes. It does not decide whether a facility broke the law, and a violation flag is not a finding of guilt.

**Run in 30 seconds**

1. Open the Actor and press **Try for free** (a free Apify account is enough).
2. Keep the prefilled input (Michigan, all three programs, only facilities in violation) and press **Start**. A run takes a few minutes because EPA returns whole states at once.
3. Open the **Output** tab. Use the table view or download CSV, Excel or JSON.

### Use cases

- Screen suppliers, vendors or acquisition targets for environmental compliance problems before signing.
- Build a regional list of high-risk industrial sites for environmental consultants, insurers or lenders.
- Monitor your state or county each month and flag facilities whose quarters in noncompliance or penalties increased.
- Give journalists and community groups a ranked list of the facilities with the longest violation streaks.
- Feed rows into an n8n, Make or Zapier workflow that opens a due-diligence task when a matching facility scores high.

### Compliance-risk score

A fixed rule of thumb, not an EPA rating: 30 points for a current violation, or 55 if it is significant or high priority, plus up to 25 for quarters in noncompliance (12 of 12 gives 25), plus 5 per formal enforcement action (up to 10), plus up to 10 for penalties on a log scale. Capped at 100. The same record always gives the same score.

### Limits

- Active facilities only. Closed or inactive permits are skipped.
- Violation data is as reported by EPA and the states, and may be incomplete or later corrected. Do not treat it as legal advice.
- Large states return thousands of facilities per program, so runs take a few minutes.
- Other programs (drinking water, toxics release) are not included.

### Related Actors

- [Developer Signals](https://apify.com/transparent_meteorite/developer-signals) tracks public developer activity signals for companies.
- [Website Tech Stack](https://apify.com/transparent_meteorite/website-tech-stack) detects which technologies a website runs on.
- [Sitemap Link Inventory](https://apify.com/transparent_meteorite/sitemap-link-inventory) lists every URL a site publishes in its sitemaps.

Found a bug or need a field? Open an issue on the Issues tab with the run URL.

### FAQ

**How fresh is the data?**
EPA refreshes ECHO regularly, but state reports can lag by weeks or months. Always check the linked ECHO report for the latest.

**Why do I get fewer rows than maxItems?**
Only facilities that match your states, programs and filters exist. Try more states, all three programs, or turn off "only in violation".

**Is this an official EPA product?**
No. It is an independent tool that reads the public EPA ECHO web services. Check echo.epa.gov for authoritative records.

**This Actor vs fortuitous_pirate/epa-echo-facilities:** that one is the most-used EPA ECHO actor and also extracts permits, violations, inspections and enforcement actions. Choose this one to pull whole states across all three programs at once, keep only facilities in violation, and get every row scored and sorted highest risk first.

### More from DWA Open Data

Browse all 69 data Actors, with live prices and sample output, at [open-data-actors.pages.dev](https://open-data-actors.pages.dev).

***

**Feedback:** if this Actor was useful, or if it fell short, an honest review on the [Reviews tab](https://apify.com/transparent_meteorite/epa-echo-facility-violations/reviews) helps other users decide. Problems or feature requests: please open an [Issue](https://apify.com/transparent_meteorite/epa-echo-facility-violations/issues) and we usually reply within one business day.

### Changelog

- 2026-10-22: Initial release.
- 2026-10-25: Documentation updated: README refreshed.
- 2026-10-25: Pricing update announced, effective 2026-10-25: Price cut to stay the lowest on the Store.
- 2026-10-25: Listing refresh: new Store icon, README reorganised (overview, data fields, pricing, FAQ) and changelog tab added. No code change.

# Changelog

This Actor's version history is a separate document: https://apify.com/transparent_meteorite/epa-echo-facility-violations/changelog.md

# Actor input Schema

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

Two-letter US state or territory codes, for example MI, OH, TX. Facilities are filtered by their state.

## `programs` (type: `array`):

CAA = Clean Air Act, CWA = Clean Water Act (NPDES permits), RCRA = hazardous waste. Leave empty for all three.

## `onlyInViolation` (type: `boolean`):

Keep facilities with a current violation or quarters in noncompliance. Turn off to include compliant facilities.

## `minRiskScore` (type: `integer`):

Optional 0 to 100. Keep only rows at or above this score.

## `majorOnly` (type: `boolean`):

Air and water only: keep facilities EPA classes as major sources or major permits. Hazardous waste has no such flag and is not filtered.

## `nameContains` (type: `string`):

Optional text that must appear in the facility name, for example "steel" or "refinery".

## `maxItems` (type: `integer`):

Stop after this many rows, highest compliance-risk score first.

## Actor input object example

```json
{
  "states": [
    "MI"
  ],
  "programs": [
    "CAA",
    "CWA",
    "RCRA"
  ],
  "onlyInViolation": true,
  "minRiskScore": 0,
  "majorOnly": false,
  "maxItems": 100
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# 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": [
        "MI"
    ],
    "programs": [
        "CAA",
        "CWA",
        "RCRA"
    ],
    "onlyInViolation": true,
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("transparent_meteorite/epa-echo-facility-violations").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": ["MI"],
    "programs": [
        "CAA",
        "CWA",
        "RCRA",
    ],
    "onlyInViolation": True,
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("transparent_meteorite/epa-echo-facility-violations").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).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": [
    "MI"
  ],
  "programs": [
    "CAA",
    "CWA",
    "RCRA"
  ],
  "onlyInViolation": true,
  "maxItems": 100
}' |
apify call transparent_meteorite/epa-echo-facility-violations --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,transparent_meteorite/epa-echo-facility-violations"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/v3bEvBoPzSJo7Etk2/builds/KDwzc0OhYtmtpMcCw/openapi.json
