EPA ECHO — US Facility Environmental Compliance and Enforcement
Pricing
from $30.00 / 1,000 search runs
EPA ECHO — US Facility Environmental Compliance and Enforcement
Search every US facility the EPA regulates and return its compliance record: current violation status under the Clean Air Act, Clean Water Act, RCRA and the Safe Drinking Water Act, inspections, formal enforcement actions and penalties in dollars. Free EPA open data, no key, no scraping.
Pricing
from $30.00 / 1,000 search runs
Rating
0.0
(0)
Developer
Benjamin Jerez
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Search every industrial and commercial facility the US Environmental Protection Agency regulates, and get back its compliance record: who is currently in violation, under which law, for how many quarters, how often they have been inspected, what enforcement followed and how much they were fined.
ECHO — Enforcement and Compliance History Online — is the EPA's combined view of its four big permitting programmes. No API key, no scraping, no licence fee.
What a search returns
states: ["NJ"], majorFacilitiesOnly: true — the 419 major sources in New Jersey:
| Summary field | Value |
|---|---|
facilitiesMatched | 419 |
facilitiesWithSignificantViolations | 30 |
facilitiesWithCurrentViolations | 210 |
facilitiesWithViolationsInLast3Years | 283 |
facilitiesInspected | 365 |
facilitiesWithFormalEnforcement | 201 |
totalPenalties, totalPenaltiesUsd | "$11,747,197" · 11747197 |
facilitiesUnderAir / UnderWater / UnderHazardousWaste | 319 · 279 · 289 |
Then one row per facility. ALERIS ROLLED PRODUCTS, INC in Clayton, NJ:
| Field | Value |
|---|---|
complianceStatus | Violation Identified |
airComplianceStatus | No Violation Identified |
waterComplianceStatus | Violation Identified |
hazardousWasteComplianceStatus | No Violation Identified |
drinkingWaterComplianceStatus | absent — not a public water system |
quartersInNonCompliance | 12 |
waterQuarterlyHistory | VVVVVVVVVVVVV |
hazardousWasteQuarterlyHistory | _____VV_____ |
inspectionCount, lastInspectionDate | 4 · 2026-02-19 |
formalActionCount, lastFormalActionDate | 5 · 2026-06-15 |
totalPenalties, totalPenaltiesUsd | "$68,790" · 68790 |
airPenaltiesUsd, hazardousWastePenaltiesUsd | 61 665 · 7 125 |
airIds, npdesIds, rcraIds | NJ0000003401500019 · NJG143723 · NJD051415909 |
echoFacilityUrl | https://echo.epa.gov/detailed-facility-report?fid=110000321535 |
Every dollar figure arrives from ECHO pre-formatted as a string like "$68,790". Both forms are kept: the string under totalPenalties, the number under totalPenaltiesUsd, so you can sort and sum without parsing.
Nulls are not zeros
This is the point of the dataset and the easiest thing to get wrong.
complianceStatus takes the values No Violation Identified, Violation Identified, Significant Violation, Violation, Unknown, or nothing at all. The per-programme fields have longer vocabularies of their own — the Clean Air Act status alone runs to Violation Addressed; Local Has Lead Enforcement, Violation Unaddressed; State Has Lead Enforcement, Violation w/in 1 Year, and more.
A missing drinkingWaterComplianceStatus does not mean the facility complies with the Safe Drinking Water Act. It means the facility is not a public water system and the Act does not apply to it. Of 2 419 major facilities sampled in New Jersey, Texas and California, 567 had no Clean Air Act status at all and 1 203 had no Clean Water Act status. Counting those as compliant would overstate compliance by half.
The companion regulatedUnderAir, regulatedUnderWater, regulatedUnderHazardousWaste and regulatedUnderDrinkingWater booleans say which programmes actually apply, so you can tell "not regulated" from "regulated and clean".
The quarterly history strings hold one character per quarter, oldest first: _ no violation on record, V violation, S significant violation, U unknown.
Filters that actually filter
Every filter in this Actor was checked against the live API by comparing the filtered row count with the unfiltered one, because ECHO silently ignores query parameters it does not recognise. A misspelled filter does not raise an error; it returns the whole unfiltered set, which looks like a perfectly good result. Some plausible spellings are among the ignored ones.
State, city, county, ZIP, NAICS, SIC, facility name, registry and permit IDs, programme, major sources, active sites, federal sites, current violations, significant violations, quarters in violation, facilities with penalties, and a latitude/longitude radius in statute miles.
Some worked examples from real runs:
states: ["CA"],mediaProgram: hazardousWaste,majorFacilitiesOnly,inViolationOnly,minQuartersInViolation: GT4— 170 facilities, $62 688 299 in penalties.states: ["TX"],significantViolationsOnly,withPenaltiesOnly,activeOnly— 311 facilities, $237 274 119.latitude: 41.8240,longitude: -71.4128,radiusMiles: 3,majorFacilitiesOnly— 9 major sources within three miles of downtown Providence.states: ["NJ"],facilityName: "MERCK"— 44 facilities, including CALGON and DUPONT MERCK PHARMACEUTICAL CO, because ECHO matches the aliases it holds for a site as well as its current name.
Enforcement detail
Turn on includeEnforcementDetail and each facility also gets its Detailed Facility Report unpacked into two extra row types.
programSummary, one row per statute — inspections, last inspection, quarters in non-compliance, quarters in significant non-compliance, formal actions, penalties. For ALERIS: CAA clean with $61 665 in penalties across four actions, CWA in violation for all twelve quarters with none, RCRA clean with $7 125.
enforcementAction, one row per formal action — the date, the action type, whether the state or the EPA led it, and the penalty. The four Clean Air Act administrative orders against ALERIS run 2022-07-27 · $2 400, 2023-08-07 · $30 800, 2024-05-02 · $24 640, 2026-06-15 · $3 825.
This costs one extra request per facility, so it is off by default and capped by maxDetailReports, highest penalties first.
Who uses this
Environmental and ESG due-diligence teams screening a target's sites before an acquisition. Lenders and insurers pricing environmental liability on an industrial property. Journalists and advocacy groups tracking which plants in a county have been in violation for years without enforcement. Site-selection and real-estate analysts checking what sits within a few miles of a parcel. Supply-chain and procurement teams auditing suppliers against their own environmental standards. Law firms building a facility's enforcement history.
Scope and limits
ECHO refuses any query matching more than 100 000 facilities. Verified: 98 167 rows succeed, 103 402 are rejected. This bites sooner than you expect — New Jersey alone holds 334 914 regulated records. The Actor reports the refusal in the summary row with the row count ECHO computed, so you know how much to narrow by. Adding majorFacilitiesOnly takes New Jersey from 334 914 to 419.
Most records are inactive. Rhode Island has 22 329 facilities on file and 3 838 currently active. activeOnly is off by default because EPA's own active flag is missing on some live sites, but it is usually what you want.
Compliance data lags. Status is computed from what state and EPA systems have reported, quarter by quarter. A violation that occurred last month may not appear for two quarters, and a resolved one may still show until the next refresh. The summary row carries the dataVersion string ECHO returns.
State-lead enforcement dominates. Most actions in the enforcement rows are taken by a state agency, not the EPA. The leadAgency field says which.
Source and licence
US Environmental Protection Agency, Enforcement and Compliance History Online, through echodata.epa.gov/echo — the all-programme facility search and the Detailed Facility Report service. US federal government works, public domain. Queried live on every run; nothing is cached.
Frequently asked
Why does the summary say 365 inspections for 419 facilities when the facilities list adds up to 1 801?
It does not say inspections. facilitiesInspected is the number of facilities with at least one inspection. All of ECHO's aggregate counts are facility counts, not event counts — this is the most common misreading of the data, so the fields here are named to prevent it.
Can I get every facility in a state? Only for smaller states. The 100 000-row ceiling is ECHO's, not this Actor's, and it is not raisable by a parameter. Split a large state by county, by ZIP or by NAICS code.
Why is totalPenalties $0 when lastPenalty is $13,000?
totalPenalties covers the recent enforcement window ECHO reports on; lastPenalty is the most recent penalty on record whenever it happened. A facility fined in 2008 and quiet since will show exactly that pattern.
Is echoFacilityUrl the same as ECHO's own link?
It points at the same report. ECHO's own DfrUrl column currently ships a malformed address with spaces around the =, so the link here is rebuilt from the registry ID.
What happens on a search that matches nothing?
You get one summary row with facilitiesMatched: 0 and a note saying so. Zero is a real answer from ECHO, not a failure, and it is charged as one search.
How large a run is practical? Results are paged a thousand at a time. A run collecting 8 000 Rhode Island facilities took 44 seconds and returned 8 000 distinct registry IDs with no duplicates.
Does it handle ECHO's expiring query IDs? Yes, and it has to. ECHO stores each query server-side under a numeric ID drawn from a small pool shared by every caller of every ECHO service. Measured on 2026-09-18, that counter advanced about six IDs per second and wrapped around a thousand, and an ID created for a 683-row query was handed to a different, 25-row query 189 seconds later — with no error, just different rows. This Actor re-runs its query before the ID can age out, checks every page against the row count the query reported, and re-runs and resumes if the ID has been taken.