# EPA ECHO Scraper: Facility Violations and Fines (`parselab/epa-echo-facility-compliance-scraper`) Actor

Scrape EPA ECHO for regulated facilities with compliance status, violations, inspections, penalties and a concern score, plus full facility reports and federal enforcement cases. Filter by state, industry, program or significant violators. Includes nearby demographics. Export to CSV or Excel.

- **URL**: https://apify.com/parselab/epa-echo-facility-compliance-scraper.md
- **Developed by:** [ParseLab](https://apify.com/parselab) (community)
- **Categories:** Other, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $17.25 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Scraper: Facility Violations, Inspections and Penalties

This EPA ECHO scraper gives you the environmental compliance record of regulated facilities in the United States: refineries, chemical plants, power stations, water systems, waste handlers and factories. One row per facility shows its compliance status, whether it is a significant violator today, how many of the last 12 quarters it spent in violation, how many inspections and enforcement actions it had, the penalties paid, and the community around it. A concern score from 0 to 100 puts the facilities that need attention first.

Two more modes go deeper. The facility report returns the full history of a plant: inspections, formal actions, notices, drinking water violations, toxic releases, hazardous waste and the people living within a mile. The enforcement cases mode returns federal civil and criminal cases with the penalties, the settlement dates and the law behind them.

Environmental consultants, ESG analysts, insurers, lenders, real estate buyers, journalists, lawyers and community groups use it for due diligence and monitoring.

### What can you do with this EPA ECHO scraper?

- List the facilities of a state, county, city, ZIP code or industry with their compliance status
- Find significant violators and facilities in violation for many quarters
- Rank facilities by penalties paid in the last five years
- Find major facilities that have not been inspected for years
- Screen by community: percent minority and low income near the plant
- Check a company by name across all its sites
- Get the full inspection and enforcement history of one facility
- See toxic releases and hazardous waste history by year
- Follow federal civil cases and penalties by state, law and date
- Export to CSV or Excel, or send changes to Slack and your own tools

### What data can you extract from EPA ECHO?

| Mode | One row is | Highlights |
|---|---|---|
| Facilities and compliance | One facility | Name, registry id, address, county, EPA region, coordinates, active and major flags, federal and tribal flags, industry codes and names, programs (air, water discharge, hazardous waste, drinking water, toxic releases, greenhouse gases), compliance status per program, significant violator flag, current violation flag, quarters in noncompliance in total and by program, effluent exceedances, quarter by quarter history, inspections in five years, last inspection and days since, informal and formal actions, total penalties and by program, last penalty, enforcement cases, toxic releases, greenhouse gas tons, population density, percent minority, percent below low income, concern score and flags in words, link to the official report |
| Detailed facility report | One facility | Permits and industries, summary per law (inspections, status, quarters in violation, actions, penalties), inspection list, formal actions, enforcement cases with settlements, informal notices, drinking water violations with actions, toxic release history, hazardous waste history, watersheds, community demographics within a mile |
| Enforcement cases | One federal case | Case number and name, category, status, law and section, lead agency, filing, lodging, settlement and closing dates, days from filing to settlement, federal and state penalties, total penalty, supplemental project cost, compliance action cost, cost recovery, outcome, court and justice department docket, link |

### How to scrape EPA ECHO

1. Choose **Facilities and compliance**, **Detailed facility report** or **Enforcement cases**.
2. Add at least one filter: a state, county, city, ZIP code, company name or industry code.
3. Optionally keep only major facilities, significant violators or facilities with penalties above a limit.
4. Set **Max Items** and click **Start**.
5. Export the dataset as CSV, Excel or from the Apify console.
6. Take the registry ids you care about and run the detailed facility report for them.

### Input example

```json
{
  "mode": "facilities",
  "states": ["TX"],
  "sicCodes": ["2911"],
  "majorOnly": true,
  "onlySignificantNoncompliance": true,
  "maxItems": 50
}
```

### Facility output example

```json
{
  "facilityName": "Buckeye Texas Processing",
  "registryId": "110064647379",
  "city": "Corpus Christi",
  "state": "TX",
  "industry": "2911: Petroleum Refining",
  "isMajor": true,
  "complianceStatus": "Significant Violation",
  "significantNoncompliance": true,
  "quartersInNoncompliance12": 9,
  "inspectionsLast5Years": 3,
  "lastInspectionDate": "2026-05-06",
  "formalActionsLast5Years": 4,
  "totalPenaltiesUsd": 260640,
  "percentMinority": 73.6,
  "concernScore": 72,
  "concernFlags": ["Significant noncompliance now", "9 of the last 12 quarters in noncompliance", "Penalties of $100,000 or more in 5 years", "4 formal enforcement actions in 5 years"]
}
```

### Enforcement case output example

```json
{
  "caseNumber": "HQ-2023-0001",
  "caseName": "Enterprise Products GP, LLC",
  "category": "Judicial",
  "primaryLaw": "CAA",
  "dateFiled": "2026-09-29",
  "settlementDate": "2026-09-29",
  "federalPenaltyUsd": 7000000,
  "leadAgency": "EPA"
}
```

### How much does it cost to scrape EPA ECHO?

You pay per result: $23 per 1,000 rows plus a tiny start fee. The free plan returns up to 10 rows per run. A detailed facility report is one row per facility, even with long histories inside.

### Tips for better results

- The source refuses searches that return millions of records. Always add a state, and add a county, city, ZIP code, company name or industry code to narrow it.
- Sorting and filters are applied to the facilities read in the first part of the search, up to the scan limit (20,000 by default). Narrow the search or raise the limit to cover everything.
- The concern score is a screen built from public fields: significant violation, current violation, high priority air violations, quarters in noncompliance, penalties, formal actions and major facilities without inspections. It is not a legal finding.
- Penalties and counts cover about five years. Quarter histories cover three years.
- Industry codes work as four digit SIC codes, for example 2911 for refining and 4911 for electric utilities.
- One company has many facilities. Search the name, then group the rows by company in your spreadsheet.
- Percent minority and income are measured around the facility. Use them as a first screen for environmental justice questions.
- A schedule every month with the significant violators filter gives you a list of new problem sites.

### Who uses EPA ECHO data?

- **Consultants and lenders** run environmental due diligence.
- **ESG analysts and insurers** score companies and sites.
- **Real estate and industrial buyers** check a site and its neighbors.
- **Journalists and community groups** investigate polluters.
- **Lawyers** research the record of a defendant.

### Automate and connect

Schedule the Actor every month and send new violators to Slack, Google Sheets, Zapier, Make or n8n, or trigger a webhook when a run ends.

### FAQ

**Do I need an account or a login?**
No. The Actor works without any login.

**What is a registry id?**
The 12 digit number the EPA uses to identify a facility across its programs. It appears in every facility row.

**What does significant violator mean?**
A facility with serious violations that the EPA tracks with priority. It is a status of the agency, not a verdict of a court.

**Why does a facility show no penalties?**
Many facilities have none. Penalties come from formal enforcement actions in the last five years.

**Can I search by company?**
Yes. Use the facility or company names field. Facilities are named after the site, so try the common spelling and a short part of the name.

**How current is the data?**
The EPA refreshes each program on its own schedule, from weekly to quarterly.

**Is this legal advice?**
No. It is public information. Check the official report and ask a professional before you act on it.

### Legal note

This Actor collects information that is publicly visible on the website. Check the source site's terms and your local rules before using the data.

### Support

Missing a field or found a bug? Open an issue from the Actor page.

# Actor input Schema

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

Free users: Limited to 10 items (preview). Paid users: Optional, max 1,000,000.

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

Facilities returns one row per regulated facility with compliance status, inspections, penalties and a concern score. Facility report returns the full history of chosen facilities. Enforcement cases returns federal civil or criminal cases with penalties.

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

Two letter state codes, for example TX, LA, CA. In the cases mode only one state can be used.

## `cities` (type: `array`):

City names, for example Houston. Use together with a state.

## `counties` (type: `array`):

County names, for example Harris. Use together with a state.

## `zipCodes` (type: `array`):

Five digit ZIP codes, for example 77002.

## `facilityNames` (type: `array`):

Part of a facility name, for example Exxon, Dow Chemical or Tyson.

## `sicCodes` (type: `array`):

Four digit SIC codes, for example 2911 for petroleum refining or 4911 for electric utilities.

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

NAICS codes, for example 324110 for petroleum refineries. Works best together with a state.

## `registryIds` (type: `array`):

Facility report mode. The 12 digit EPA registry number of each facility, shown in the facilities mode, for example 110007182360.

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

Keep facilities regulated under all the chosen programs.

## `activeOnly` (type: `boolean`):

Skip facilities that closed or are no longer regulated.

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

Keep only facilities that the EPA counts as major sources, which are the largest polluters.

## `onlySignificantNoncompliance` (type: `boolean`):

Keep facilities in significant noncompliance right now.

## `onlyCurrentViolation` (type: `boolean`):

Keep facilities with a violation open now, including significant violators.

## `minPenaltiesUsd` (type: `integer`):

Keep facilities with at least this much in penalties over the last five years, for example 100000.

## `minQuartersInNoncompliance` (type: `integer`):

Keep facilities that were in noncompliance in at least this many of the last 12 quarters.

## `minPercentMinority` (type: `integer`):

Keep facilities where the population nearby is at least this percent minority, for environmental justice screening.

## `notInspectedForDays` (type: `integer`):

Keep facilities never inspected or last inspected at least this many days ago, for example 730.

## `sortBy` (type: `string`):

Facilities mode. Sorting is done on the facilities read, see the scan limit.

## `scanLimit` (type: `integer`):

Facilities and cases modes. Most records read per search before sorting and filtering. Between 500 and 60,000.

## `caseCategory` (type: `string`):

Enforcement cases mode.

## `caseLaws` (type: `array`):

Enforcement cases mode. Keep cases under these laws, for example CAA, CWA, RCRA, SDWA, CERCLA, TSCA, FIFRA.

## `caseName` (type: `string`):

Enforcement cases mode. Part of the case name, usually the company, for example Exxon.

## `minCasePenaltyUsd` (type: `integer`):

Enforcement cases mode. Keep cases whose federal plus state penalty is at least this amount.

## `dateFrom` (type: `string`):

Enforcement cases mode. First filing date, in the form 2025-01-31.

## `dateTo` (type: `string`):

Enforcement cases mode. Last filing date.

## `detailLimit` (type: `integer`):

Facility report mode. Most inspections, actions, notices and violations kept in each list of a report.

## Actor input object example

```json
{
  "maxItems": 10,
  "mode": "facilities",
  "states": [
    "TX"
  ],
  "sicCodes": [
    "2911"
  ],
  "activeOnly": true,
  "majorOnly": false,
  "onlySignificantNoncompliance": false,
  "onlyCurrentViolation": false,
  "sortBy": "concernScore",
  "scanLimit": 20000,
  "caseCategory": "civil",
  "detailLimit": 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 = {
    "maxItems": 10,
    "states": [
        "TX"
    ],
    "sicCodes": [
        "2911"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("parselab/epa-echo-facility-compliance-scraper").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 = {
    "maxItems": 10,
    "states": ["TX"],
    "sicCodes": ["2911"],
}

# Run the Actor and wait for it to finish
run = client.actor("parselab/epa-echo-facility-compliance-scraper").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 '{
  "maxItems": 10,
  "states": [
    "TX"
  ],
  "sicCodes": [
    "2911"
  ]
}' |
apify call parselab/epa-echo-facility-compliance-scraper --silent --output-dataset

```

## MCP server setup

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

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/DrgQlJqvyPDhgYc6o/builds/phrDdGNxvComHKhXn/openapi.json
