Phase I ESA Environmental Database Search — EPA by Address avatar

Phase I ESA Environmental Database Search — EPA by Address

Pricing

from $5.50 / 1,000 results

Go to Apify Store
Phase I ESA Environmental Database Search — EPA by Address

Phase I ESA Environmental Database Search — EPA by Address

Environmental database report for any US address: EPA Superfund/NPL, RCRA CORRACTS/TSD/generators, TRI, UST, LUST, Brownfields, NPDES, AIR, TSCA, RMP — scored against ASTM E1527-21 search distances, plus on-site Superfund and institutional-control (AUL) boundary checks. No API key.

Pricing

from $5.50 / 1,000 results

Rating

0.0

(0)

Developer

Kyle Maloney

Kyle Maloney

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

a day ago

Last modified

Share

Phase I ESA Environmental Database Search — EPA Records by Address

Run an environmental database report on any US address or coordinate: ten EPA regulatory databases screened by distance, scored against the ASTM E1527-21 standard search distances, returned as structured rows. This is the multi-database regulatory records review at the core of a Phase I Environmental Site Assessment. Built for Phase I ESA consultants, CRE buyers and lenders, environmental attorneys and underwriters who need to triage a property or a whole portfolio before ordering the full report. No API key.

Environmental database report by address

Give it an address (or lat/lon) and a radius; get one row per nearby regulated site, each tagged with its program, its distance, its EPA status, and a direct link to the EPA source record.

programEPA databaseSource
SUPERFUNDNPL / Superfund (SEMS) + FRS SEMS pointsEPA Envirofacts ENVIROFACTS_SITE + EPA FRS FRS_INTERESTS_SEMS / _SEMS_NPL
RCRAHazardous-waste handlers, classified into CORRACTS / TSD / generatorEPA ECHO echo_rest_services + rcra_rest_services
TRIToxics Release Inventory reportersEPA ECHO
USTUnderground storage tank facilitiesEPA UST Finder (2018-2021 vintage)
LUSTLeaking underground storage tank releasesEPA UST Finder
BROWNFIELDBrownfields / ACRESEPA FRS ACRES
NPDES (opt-in)Clean Water Act discharge permits (ICIS-NPDES)EPA ECHO
AIR (opt-in)Clean Air Act permitted stationary sourcesEPA ECHO
TSCA (opt-in)TSCA-regulated facilities incl. PCB handlersEPA ECHO
RMP (opt-in)Risk Management Plan chemical-accident facilitiesEPA ECHO

Addresses are geocoded with the free US Census geocoder. Leave programs empty to screen the original six; name the opt-in four to include them (they come from the same EPA ECHO response, so they cost no extra upstream call).

ASTM E1527-21 standard environmental record sources and search distances

Set astmMode: true and each asset gets one extra astm_summary row scoring the databases against the ASTM E1527-21 Sec. 8.2.1 search-distance table — delivered as flat, CSV-safe columns (astm_npl_flag, astm_rcra_corracts_nearest_mi, ...) plus a nested object.

ASTM line itemRequired radiusColumn prefix
NPL (Superfund, Final)1.0 miastm_npl_*
Delisted NPL / SEMS-CERCLIS (non-NPL)0.5 miastm_cerclis_*
RCRA CORRACTS (corrective action)1.0 miastm_rcra_corracts_*
RCRA TSD (treatment/storage/disposal)0.5 miastm_rcra_tsd_*
RCRA generators (LQG/SQG/VSQG)0.25 miastm_rcra_generators_*
LUST0.5 miastm_lust_*
UST (registered)0.25 miastm_ust_*
Brownfields0.5 miastm_brownfield_*

TRI is not an ASTM standard record source and never gets an entry. radiusMiles accepts fractional miles (0.1–50) so you can screen at 0.25 or 0.5 mi directly.

Earlier versions applied the widest 1.0-mile CORRACTS radius to every RCRA facility, because echo_rest_services does not expose the distinction. rcra_rest_services does — via RCRAUniverse, Tsdf and CleanupActionFlag — so each RCRA hit now carries rcra_astm_class (CORRACTS / TSD / GENERATOR / OTHER), rcra_corracts, rcra_universe and rcra_tsd_types, and is scored at its correct ASTM radius.

rcra_astm_class is a single, mutually exclusive class resolved in precedence order CORRACTS → TSD → GENERATOR → OTHER, so a facility that is both a corrective-action site and a TSD is reported once, as CORRACTS. Its raw rcra_tsd_types still shows the TSD designation — BRODERICK WOOD PRODUCTS CO carries Land Disposal (L) while classing as CORRACTS. This is why astm_rcra_tsd_count can be lower than the raw count of TSD-designated facilities in range: each facility is scored at one ASTM line item, not several.

Measured live at 39.8037, -104.9986 (Denver) within 1 mile: EPA lists 96–97 RCRA facilities, of which exactly 2 carry a corrective action (CORRACTS)BRODERICK WOOD PRODUCTS CO and KOPPERS INC (DENVER CO) — and 3 carry a TSD designation. Scoring all of them at the 1.0 mi CORRACTS radius, as earlier versions did, over-flags by roughly 48x. (EPA's RCRRows count at this point drifts by a facility or two between refreshes; it read 96 on 2026-07-26.)

Recognized Environmental Condition (REC) screening — is the property ON a site?

With includeBoundaries: true (default) each asset also gets a true point-in-polygon test, not a distance-to-centroid guess:

  • on_superfund_site, superfund_site_name, superfund_epa_id, superfund_epa_url, superfund_site_description — is the property inside a published EPA NPL Superfund site boundary? (2,114 polygons nationally.)
  • institutional_control_flag, institutional_control_site_name, institutional_control_description, institutional_control_area_acres — is it inside a published EPA Superfund institutional control boundary?

A boundary match also sets superfund_npl_status (a readable label such as Final NPL). Verified live 2026-07-26: 39.686641, -105.003564 returns DENVER RADIUM SITE; 39.793679, -104.982364 returns ASARCO, INC. (GLOBE PLANT) plus the institutional control OU4 - Environmental Covenant.

Institutional controls and activity and use limitations (AULs)

The IC layer answers the ASTM E1527-21 AUL record-source question where EPA has published a boundary. Coverage is thin and stated plainly: EPA publishes ~165 IC boundary polygons nationally. A false result means "not inside a published federal Superfund IC", not "no AUL exists on this property". A null means the layer was not consulted or failed — never read null as a clean result.

Business Environmental Risk — enforcement, penalties and compliance history

Every ECHO-derived hit now carries the facility's regulatory track record, which is what ASTM E1527-21 Business Environmental Risk is about: compliance_status, significant_noncompliance, inspection_count, last_inspection_date, formal_action_count, total_penalties_usd, last_penalty_date, plus sic_codes / naics_codes (an industry pre-screen: 7216 dry cleaner, 5541 gasoline station, 2491 wood preserving) and cross-program IDs (npdes_ids, air_ids, rcra_ids, sems_ids, tri_ids, tsca_ids, rmp_ids).

Every hit also carries dfr_url — a direct link to the facility's EPA Detailed Facility Report, the citable source for a report appendix.

A commercial radius report is a PDF you wait for. This is the same federal database layer as JSON/CSV/Excel, on demand, per address, at Pay-Per-Result pricing, callable from an API or an AI agent. It does not include the state/tribal databases, historical fire-insurance maps, city-directory research or the Environmental Professional's opinion that a commercial report and a real Phase I include — see the caveats below.

Environmental due diligence API for commercial real estate

Screen a whole portfolio in one call: pass as many items as you like in assets; each nearby site is one row. Every row carries the per-asset rollup, so you can sort a hundred properties by phase1_esa_flag and astm_refined_verdict before anyone opens a file.

Two modes

assets mode (default) — screen your properties. Each asset item is either { "address": "...", "label": "..." } or { "lat": <n>, "lon": <n>, "label": "..." }. state is now optional with lat/lon — Superfund is screened spatially against the EPA FRS SEMS point layers, which need no state; supplying state additionally pulls that state's full Envirofacts SEMS roster for wider non-NPL coverage.

{
"mode": "assets",
"assets": [
{ "lat": 39.8037, "lon": -104.9986, "state": "CO", "label": "Denver warehouse" },
{ "address": "5980 Lipan St, Denver, CO 80221", "label": "Denver warehouse (by address)" }
],
"radiusMiles": 1,
"programs": ["SUPERFUND", "RCRA", "TRI", "UST", "LUST", "BROWNFIELD", "NPDES", "AIR", "TSCA", "RMP"],
"maxHitsPerProgram": 50,
"astmMode": true,
"includeBoundaries": true
}

inventory mode — list the raw EPA SEMS/Superfund roster for the states you name.

{ "mode": "inventory", "states": ["CO", "NJ"], "onlyNpl": true }

Key output fields (assets mode)

  • result_typelisting (a hit), clear (screened, nothing within radius), or error.
  • program, list — the EPA program and its readable database name.
  • site_name, site_address, site_city, site_state, site_zip, site_county; site_id, registry_id.
  • distance_miles — great-circle distance from the asset to the site.
  • coordinate_source / positional_accuracy_m / coordinate_methodhow the site was located (state-supplied survey point vs. address geocode). This qualifies every distance in the row.
  • status, status_detail, on_npl, phase1_flag.
  • UST/LUST: ust_open_tanks, ust_closed_tanks, ust_temporarily_out_of_service, lust_substance, lust_reported_date, lust_case_open.
  • UST tank counts, unrounded: ust_open_tanks_reported, ust_closed_tanks_reported, ust_tos_tanks_reported and ust_tank_counts_unreported. EPA publishes no tank count for a slice of UST Finder — measured 2026-08-01, Closed_USTs is null on 15,221 of 742,855 facilities and TOS_USTs on 15,235. The three original fields report 0 there and always have, so they are unchanged; these four say plainly whether that 0 is a measurement or an absence. On this actor's own five published example runs, 23 of 243 UST rows (9.5%) carried a count EPA never published.
  • Receptors: population_within_1500ft, private_wells_within_1500ft, in_source_water_protection_area, in_wellhead_protection_area, in_100yr_floodplain, land_use.
  • asset_*, radius_miles, checked_at, error, disclaimer, source_url.

Did the databases actually answer? (data_complete)

Every row carries a data-completeness ledger, because a screening result that quietly means "we could not reach EPA" is worse than no result at all:

  • programs_requested, programs_screened, programs_failed, programs_failed_detail
  • data_complete — true only when every requested database answered
  • truncated_programs — programs whose upstream result hit a hard record cap, or whose retrieved record count did not match the upstream's own exact count
  • sems_roster_complete, sems_roster_expected, sems_roster_retrieved — the Superfund/SEMS state roster is now reconciled against EPA Envirofacts' own .../COUNT/JSON endpoint, queried with exactly the filter used to fetch it. If paging stopped early the row says so instead of ranking NPL proximity over a partial roster.

A clear result is only ever emitted when at least one requested database actually answered. If all of them failed for an asset, the row is result_type: "error" and says so — it never claims the property is clean. If every database fails for every asset, the run fails and nothing is billed. As of v1.3.4 that sentence is literally true: rows are held back until at least one asset has been screened by at least one live database, so on a total outage the run fails having pushed nothing at all. Before v1.3.4 one row per asset had already been written when the failure fired.

Live upstream drift assertions

Every EPA read is checked at runtime against what that service returned when this actor was baselined, because the expensive failure is not an outage — it is a source that quietly changes shape, keeps answering 200, and lets the screen return a confident wrong answer. Thirty assertions run on a full screen:

  • Column contracts. Every column the actor reads is checked on the payload that arrived. A column it needs to identify or locate a site going missing (FacLat, Latitude, primary_latitude_decimal_val, RCRAFlag, …) is treated as fatal: the run stops before anything is pushed, because listings would otherwise be silently missed. A column it only reads for enrichment going missing is a warning and the matching field goes null.
  • Record-count canaries. Each layer's national record count must sit inside a band measured live on the baseline date — UST Finder 742,855 facilities, LUST 531,310, FRS ACRES 44,235, FRS SEMS 14,970 (+1,837 NPL), Superfund boundaries 2,114, institutional-control boundaries 165, Envirofacts SEMS 55,588 sites. Bands are roughly a third of the measured value, so ordinary growth or a data-cycle refresh cannot trip them; only a layer being replaced by a subset can.
  • Retrieval completeness. Every paged ArcGIS read is reconciled against returnCountOnly, and every SEMS state roster against efservice COUNT/JSON. Both counts are issued with exactly the filter used to fetch, never through a chained join.
  • Parser completeness. EPA ECHO states its row count before sending the CSV, so a row dropped in parsing is caught for free.
  • Coordinate coverage. A latitude column that is present but entirely empty is invisible to a column check and would make every asset read clear; a roster of 500+ records with zero geocoded records fails the assertion.

The outcome is on every row: drift_status (ok / warning), drift_checks_run, drift_checks_failed, drift_warnings, programs_degraded, drift_baseline_date. A degraded source reports null for its derived answers, never false — including the Superfund and institutional-control boundary flags, which are skipped entirely rather than answered from a layer that failed its canary.

NPL/Superfund proximity rollup (per asset)

nearest_npl_site_name, nearest_npl_distance_miles, nearest_npl_status, npl_sites_within_radius, phase1_esa_flag, phase1_summary. Computed against the union of the state SEMS roster and the fully-geocoded FRS SEMS points, and not bounded by radiusMiles — a Phase I report conventionally states the nearest NPL site even when it falls outside the search radius. The NPL life-cycle now includes EPA's pre-proposal status, used for sites already under remedial enforcement; it surfaces as a readable label in nearest_npl_status (and, on a Superfund boundary match, superfund_npl_status) rather than as a raw status code.

Was that "clear" actually verified? (v1.3.4)

Three companion fields state, per row, whether a negative was checked or merely not checked. null means NOT CHECKED; false means checked and negative.

  • phase1_screen_performed - true when the asset was actually screened (coordinates resolved AND at least one requested database answered). False on an unresolvable address and on an asset where every requested database failed.
  • phase1_esa_flag_verified - true whenever a database actually returned a listing (a positive is self-verifying). false only when every requested program answered and none matched. null when the negative was never verified.
  • npl_sites_within_radius_verified - the same count as npl_sites_within_radius, but only when the Superfund/SEMS roster actually answered for this asset; null when SUPERFUND was not requested, failed, or the asset was never screened.

The original phase1_esa_flag and npl_sites_within_radius are unchanged and always will be: they have been live since v1.2 and pipelines are keyed to them. If a false clear would carry liability for you, filter on the _verified columns instead, which are blank rather than false / 0 when the check was never run.

Fields that are often empty, and why

Some columns are legitimately null on most rows because EPA does not carry the data, not because the actor failed to read it. Rather than hide them, here is the measured fill rate for each (2026-07-26) and an input that does populate it.

FieldWhy it is usually nullMeasured fillAn input that populates it
ust_last_inspection_dateEPA barely populates Date_of_Last_Inspection in UST Finder1,445 of 742,855 (0.19%) nationally; 17 of 11,330 in CO{"lat":37.15785,"lon":-107.605833} (BIA Warehouse #40, CO)
lust_substanceState-reported; most states file no substance~19% nationally; MI 17,398, KS 6,058, CA 9, TX 0, OH 0, CO 0{"lat":42.44684,"lon":-83.10325} (Detroit, MI)
rcra_open_violation_sinceOnly exists for a facility with an open violation0 of 97 within 1 mi of Denver; 26 of 3,238 within 10 mi of Houston{"lat":29.66984,"lon":-95.23289}
rcra_land_release_chemicalsOnly exists where EPA has a land-release record0 of 97 at Denver; 7 of 3,238 at Houston{"lat":29.71247,"lon":-95.22496}
institutional_control_*EPA publishes very few IC boundary polygons~165 polygons nationally{"lat":39.793679,"lon":-104.982364} (ASARCO Globe Plant)
truncated_programsNull is the healthy value — nothing was truncatedfills only at large radii in dense metrosradiusMiles: 25 in a major metro
errorNull on every successful rowfills on error rows onlyan asset with neither address nor coordinates
drift_checks_failed, drift_warnings, programs_degradedNull is the healthy value — every live upstream assertion passed0 of 1,457 rows on the 2026-08-01 audit across the prefill and all five example runsfills only when an EPA service changes shape or a layer collapses
name, epa_id, address, city, state, zip, county, npl_status_code, npl_status_name, non_npl_status_name, is_superfund, federal_facility, archived, archived_date, lat, lonInventory-mode columns; structurally absent from an assets-mode row50 of 50 rows in inventory mode{"mode":"inventory","states":["CO"],"onlyNpl":false,"onlyWithCoords":true,"maxResults":50}

A null in these columns is a fact about EPA's records, not a gap in the screen. Where a field means something stronger — on_superfund_site, institutional_control_flag, data_complete — null and false are deliberately different: false means checked-and-negative, null means not checked.

Field availability also depends on which programs a row came from: dfr_url, sic_codes, compliance_status, total_penalties_usd and the rcra_* block exist only on EPA ECHO-derived rows (RCRA/TRI/NPDES/AIR/TSCA/RMP); coordinate_source, receptor counts and the ust_*/lust_* blocks only on UST/LUST rows; sems_coord_source only on Superfund rows.

Caveats worth knowing

  • This is a screening aid, not a Phase I ESA. It does not replace a licensed Environmental Professional's records search, and it does not by itself satisfy ASTM E1527-21 or the AAI rule. Use it to triage, then order the real report on anything flagged.
  • Federal databases only. State and tribal registries, historical aerials, fire-insurance maps and city directories are not included. Pair it with the companion State UST, LUST & Spill Registry Screener for state-level coverage.
  • SEMS/Superfund geocoding varies sharply by state. Measured 2026-07: 3% of Texas SEMS records carry coordinates, 16% California, 48% Colorado, 60% New Jersey, 77% New York. NPL-track records, however, are ~96–100% geocoded everywhere, and the FRS SEMS point layers (100% geocoded, ~14,967 non-NPL + 1,837 NPL points) are unioned in to close much of the remaining gap. A clear result still means "no listed, geocoded record within radius", not a guarantee of no history.
  • distance_miles is measured to a database point, not a property boundary — check coordinate_source before relying on a tight distance. The on_superfund_site polygon test is exact.
  • Institutional-control coverage is thin (~165 national polygons). See the AUL section above.
  • An EPA service that changes shape now stops the run rather than answering wrongly. If a source drops a column the screen depends on to identify or locate a site, the run fails with a message naming the column, before any row is emitted and before anything is billed. That is deliberate: on a Phase I screen, a red run you can retry is far cheaper than a clear row that missed a listing. Outages behave as they always did — the affected program is marked failed on the row, and the run only fails if every database fails for every asset.

Use as an MCP tool

This Actor is callable directly by any MCP-compatible AI agent through Apify's hosted MCP server. There is no server to run and no integration code to write - the tool schema an agent sees is generated from this Actor's own input and dataset schemas.

Endpoint

https://mcp.apify.com?tools=malonestar/epa-contaminated-site-screener

Claude Desktop, Claude Code or Cursor - add to claude_desktop_config.json, .mcp.json or .cursor/mcp.json respectively:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=malonestar/epa-contaminated-site-screener",
"headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }
}
}
}

Get a token at https://console.apify.com/settings/integrations. Claude Desktop can also authenticate interactively via OAuth against https://mcp.apify.com with no headers block. Full reference: https://docs.apify.com/platform/integrations/mcp

Try asking your agent

Screen 1200 Broadway, Denver CO for environmental risk under ASTM E1527-21 and tell me which findings are within the standard's search distance.

Chains well with - expose these alongside it by comma-separating the tools parameter, and the agent can carry results from one into the next:

  • malonestar/parcel-owner-lookup
  • malonestar/site-due-diligence-bundle
  • malonestar/fws-wetlands-proximity-screener
https://mcp.apify.com?tools=malonestar/epa-contaminated-site-screener,malonestar/parcel-owner-lookup,malonestar/site-due-diligence-bundle,malonestar/fws-wetlands-proximity-screener

Billing is unchanged when called as an MCP tool: this Actor is Pay-Per-Event and an agent pays the same per-result price a human does. A run that cannot answer fails without billing rather than returning an unverified negative.

Use in n8n

This Actor is published as an n8n community node, so it can be dropped into a workflow without writing an HTTP request by hand.

Install from Settings > Community Nodes > Install in any self-hosted n8n instance, enter n8n-nodes-epa-contaminated-site-screener, then add your Apify API key as an Apify API credential. The node calls this Actor through the Apify API, so there is no extra infrastructure to run and billing is identical to a normal run.

Use in n8n

This Actor is published as an n8n community node, so it can be dropped into a workflow without writing an HTTP request by hand.

Install from Settings > Community Nodes > Install in any self-hosted n8n instance, enter n8n-nodes-epa-contaminated-site-screener, then add your Apify API key as an Apify API credential. The node calls this Actor through the Apify API, so there is no extra infrastructure to run and billing is identical to a normal run.

FAQ

Which databases does it search? Superfund/NPL, RCRA (split into CORRACTS/TSD/generators), TRI, UST, LUST and Brownfields by default; NPDES, AIR, TSCA and RMP on request.

Does this replace a Phase I ESA? No. It is a pre-screen; order a licensed Phase I ESA for anything flagged.

Does this satisfy an ASTM E1527-21 records review or AAI? No. astmMode approximates the standard's search-distance table against this actor's EPA databases. It is not a Phase I ESA and does not satisfy ASTM E1527-21 or 40 CFR Part 312.

What are the ASTM E1527-21 search distances? See the table above — 1.0 mi for NPL and RCRA CORRACTS, 0.5 mi for SEMS-CERCLIS / RCRA TSD / LUST / Brownfields, 0.25 mi for registered UST and RCRA generators.

Can I screen a whole portfolio at once? Yes — pass as many items as you want in assets; each site hit is one row.

How is billing calculated? One dataset row per site hit (assets mode, including the optional astm_summary row) or per SEMS site (inventory mode). Boundary and AUL checks add fields, not rows, and are not billed. Runs that cannot screen anything fail without billing.