# Orphaned Oil & Gas Well Proximity Screener - Phase I ESA (`malonestar/orphaned-well-proximity-screener`) Actor

Screen any US coordinate against 117,672 documented orphaned oil and gas wells. Returns count in radius, nearest-well distance and bearing, status, well type, positional accuracy and a Phase I ESA risk signal. Covers 27 states; a site outside coverage is reported as such, never as clear.

- **URL**: https://apify.com/malonestar/orphaned-well-proximity-screener.md
- **Developed by:** [Kyle Maloney](https://apify.com/malonestar) (community)
- **Categories:** Real estate, Developer tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.40 / 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Orphaned Oil & Gas Well Proximity Screener (Phase I ESA / Land Development)

Give it a coordinate and a radius. It tells you how many **documented orphaned oil
and gas wells** the USGS national dataset places inside that radius, exactly how
far away the nearest one is and in what direction, what the state's own record
says about each well, **how accurate each well's published location actually is**,
and a transparent 0-100 screening score.

Built on the **USGS US Documented Unplugged Orphaned Oil and Gas Well Dataset**
(DOI [10.5066/P91PJETI](https://doi.org/10.5066/P91PJETI)) - **117,672 wells
across 27 states**, compiled from the state oil and gas regulators themselves.
No API key, no scraping, no login.

### Who this is for

- **Phase I ESA consultants.** An undocumented orphaned well on or beside a site
  is a real recognised environmental condition: a possible vapour and groundwater
  pathway, and a plugging liability that can land on the current owner. This is
  a fast screen for that, with the well identifiers you need to pull the state
  file, and it is honest about the roughly one-third of the dataset where the
  state does not say whether the well was ever plugged.
- **Land developers and homebuilders.** A well under a planned foundation is a
  design problem, not a paperwork problem. Screen a whole land pipeline in one
  run and rank it.
- **Solar, wind, battery and carbon-project developers.** Orphaned wells inside
  a project boundary drive setbacks, and for carbon storage they are a leakage
  pathway that regulators ask about directly.
- **Lenders, insurers and title teams** doing pre-close environmental screening.
- **AI agents.** See "Use as an MCP tool" below.

### What makes this different from a map click

1. **It is honest about coverage.** The dataset holds 27 states. A site in
   Florida returns zero wells - but that is *no data*, not *no wells*. This actor
   resolves each site's own state (FCC census-block API, Census TIGERweb as
   fallback) and reports `out_of_dataset_coverage` instead of publishing a clear.
   `phase1_esa_further_inquiry_flag` is only ever `false` on a completed query
   inside a covered state.
2. **It is honest about positional accuracy.** 795 wells in this dataset are
   located only to a PLSS **section centroid** - a one-square-mile box, so a
   reported distance can be wrong by 0.7 mile. 158 are *permitted* locations that
   may never have been drilled. 285 the source itself flags as questionable. 7,685
   have an unconfirmed horizontal datum, which alone is worth up to about 200 m.
   Every well ships a `positional_class` and an uncertainty estimate.
3. **It does not guess at codes.** USGS republishes each state's own status text
   verbatim and publishes no codebook for the opaque two-letter codes. Codes are
   normalized only where the literal English is unambiguous or the dataset
   documents them; everything else normalizes to `null` with
   `basis: unmapped_state_code`, and the raw value is always emitted.
   `plugged_per_state_record` is `true` for exactly three status values and
   `null` - never `false` - wherever the record does not actually say.
4. **A short read is an error, not an answer.** The service caps a page at 2,000
   features. Before paging, the actor asks the service for its own exact count,
   then pages with keyset pagination until it has all of them. If it cannot, the
   site fails loudly rather than reporting "the nearest well" computed off an
   arbitrary subset.
5. **It verifies the upstream on every run** before emitting a single billable
   row: field set, national count floor, live state coverage, status vocabulary,
   two positive canaries, two negative controls, an explicit projection check and
   a true-circle fidelity test. Every measured value is printed to the log.

### Example input

```json
{
  "assets": [
    { "lat": 34.07, "lon": -118.29, "label": "Los Angeles City oil field - infill parcel, CA", "radiusMiles": 0.5 },
    { "lat": 41.4651, "lon": -79.6504, "label": "Oil City brownfield, Venango County PA", "radiusMiles": 1 },
    { "lat": 39.7392, "lon": -104.9903, "label": "Denver CO downtown control site", "radiusMiles": 1 },
    { "lat": 25.7617, "lon": -80.1918, "label": "Miami FL control site (outside dataset coverage)", "radiusMiles": 1 }
  ],
  "includeWellDetail": true,
  "maxWellsPerAsset": 10
}
```

Those four sites are the shipped prefill and they demonstrate all four outcomes:
the Los Angeles parcel sits on the **Los Angeles City oil field** (289 documented
orphaned wells within half a mile), Oil City PA returns 63 within a mile, Denver
returns a **verified clear inside a covered state**, and Miami returns
**out of dataset coverage** - the same zero, with a completely different meaning.

### Input reference

| Input | What it does |
|---|---|
| `assets` (**required**) | Array of `{lat, lon, label, radiusMiles}`. `radiusMiles` is optional per site and overrides the run-level radius. `latitude`/`longitude`/`lng` are accepted as aliases. Omitting `assets` entirely returns HTTP 400 before the run starts, so nothing is billed. |
| `radiusMiles` | Run-level search radius in statute miles, 1-25. Per-site values may be fractional (0.25, 0.5). Defaults to 1 mile. |
| `includeWellDetail` | Emit one row per well in addition to the site summary. Off by default. |
| `maxWellsPerAsset` | Cap on per-well rows, nearest kept first. Defaults to 100. |
| `maxAssets` | Cap on sites per run. Defaults to 50. |
| `resolveAssetState` | Resolve each site's state to test dataset coverage. On by default. |
| `skipDriftChecks` | Diagnostic. Skips the live upstream integrity checks. |
| `simulateOutage` | Diagnostic seam (`none`/`wells`/`state`/`both`) to prove the failure path on demand. |

**Note:** no input carries a schema `default`, deliberately. An Apify input-schema
`default` is injected server-side into every run, so a default on a predicate
field silently narrows queries the caller never asked for. Defaults live in code.

### Output

Two record types share one flat schema, distinguished by `record_type`:

- **`asset_summary`** - exactly one row per screened site, always.
- **`well`** - one row per documented orphaned well inside the radius, nearest
  first. Only emitted when `includeWellDetail` is on.

Fields that belong to the other record type are `null`, and **every field is
nullable**.

#### The `null` vs `false` contract

This is the most important thing to understand about the output:

- **`null` means "not checked"** - the source did not answer, the state does not
  publish it, or the band lies outside the radius you searched.
- **`false` means "checked, and the answer is negative."**

They are never collapsed. A run where the well layer fails emits
`orphaned_wells_present: null`, not `false`. A distance band wider than your
radius is `null`, not `0`. A state record that does not state a plugging status
gives `plugged_per_state_record: null`, not `false`. If **every** site fails, the
run fails and **nothing is billed**.

#### Output fields

##### Site identity and run context

| Field | Type | Description |
|---|---|---|
| `record_type` | string | asset\_summary for the one row per screened site, or well for a per-well detail row (only emitted when includeWellDetail is on). |
| `asset_label` | string | The label you supplied for this site, echoed on every row so results can be joined back to your portfolio. |
| `asset_lat` | number | Site latitude in WGS84 decimal degrees, as supplied. |
| `asset_lon` | number | Site longitude in WGS84 decimal degrees, as supplied. |
| `search_radius_miles` | number | The radius actually searched for this site, in statute miles. This is a true circle, not a bounding box. |
| `checked_at` | string | UTC timestamp of the run that produced this row. |
| `dataset_source` | string | The upstream dataset and layer this answer came from. |
| `dataset_doi` | string | Permanent DOI for the USGS data release, for citation in a Phase I report. |
| `dataset_national_well_count` | number | Total wells in the live national dataset, measured on this run. 117,672 on 2026-08-04. Null if the drift checks were skipped. |
| `dataset_states_covered_count` | number | How many states the live dataset actually contains, measured on this run rather than hard-coded. |
| `dataset_states_covered` | string | The states the dataset covers, measured live. A site outside this list cannot be screened by this dataset and is reported as out\_of\_dataset\_coverage, never as clear. |
| `dataset_vintage_earliest` | string | Earliest per-state data file date in the whole dataset. The compilation is a snapshot of state records, not a live feed. |
| `dataset_vintage_latest` | string | Latest per-state data file date in the whole dataset. |
| `risk_model_version` | string | Version of the screening score formula, so a future change to the model is detectable in your own records. |
| `error` | string | Null on a healthy row. Populated when this site could not be screened; the row then asserts nothing about wells. |

##### Source health, completeness and coverage

| Field | Type | Description |
|---|---|---|
| `wells_source_status` | string | ok when the orphaned-well layer answered completely for this site; unavailable when it did not. Every well-derived field on an unavailable row is null, never false. |
| `wells_source_error` | string | Why the orphaned-well layer could not answer for this site. Null on a healthy row. |
| `wells_reported_by_source` | number | Exact well count the service itself reports inside the radius, read from its own returnCountOnly answer. This is the truncation guard. |
| `wells_retrieved` | number | How many well records were actually retrieved and mapped. If this is ever below wells\_reported\_by\_source the site fails rather than answering from a partial set. |
| `query_complete` | boolean | True only when wells\_retrieved equals wells\_reported\_by\_source. A silently truncated ArcGIS read is the single most common cause of a wrong proximity answer. |
| `wells_dropped_outside_radius` | number | Wells the service returned that a haversine re-check placed outside the requested radius. Expected to be 0; a non-zero value means the service stopped honouring a true-circle query. |
| `asset_state` | string | The US state the site itself falls in, resolved independently of the well data. Used only to decide whether the dataset covers this site. |
| `asset_state_source` | string | Which resolver answered: fcc\_census\_block or census\_tigerweb. |
| `asset_state_status` | string | ok when a resolver answered, unavailable when both failed. When unavailable, in\_dataset\_coverage stays null and a zero-well result is reported as coverage\_unknown rather than as clear. |
| `asset_state_error` | string | Why the state could not be resolved, or a note that the coordinate is not inside any US state. |
| `asset_county` | string | County containing the site, when the FCC resolver supplied one. |
| `in_dataset_coverage` | boolean | True when the site is in one of the states the dataset actually contains, false when it is not, and null when the state could not be resolved. Never guessed. |
| `coverage_basis` | string | How in\_dataset\_coverage was decided: measured\_from\_live\_dataset, asset\_state\_unresolved, asset\_state\_lookup\_disabled, or covered\_state\_list\_unavailable. |

##### The screening answer

| Field | Type | Description |
|---|---|---|
| `screening_result` | string | wells\_found | no\_documented\_wells\_in\_covered\_state | out\_of\_dataset\_coverage | coverage\_unknown | source\_unavailable. Only the second value is a verified clear. |
| `orphaned_wells_present` | boolean | True when documented orphaned wells were found in the radius, false only on a completed query inside a covered state, and null whenever the question was not actually answered. |
| `phase1_esa_further_inquiry_flag` | boolean | True when at least one documented orphaned well sits inside the radius, meaning the site warrants further inquiry in a Phase I ESA. False only on a verified clear inside a covered state. Null when coverage or the source is in doubt. Screening only, not a determination. |
| `well_count_within_radius` | number | Documented orphaned wells inside the search radius. Null when the query did not complete. |
| `wells_within_500_ft` | number | Wells within 500 feet. Null when the search radius is smaller than this band, because a band you did not search is not zero. |
| `wells_within_0_25_mile` | number | Wells within 0.25 mile. Null when the search radius is smaller than 0.25 mile. |
| `wells_within_0_5_mile` | number | Wells within 0.5 mile. Null when the search radius is smaller than 0.5 mile. |
| `wells_within_1_mile` | number | Wells within 1 mile. Null when the search radius is smaller than 1 mile. |
| `risk_score` | number | Screening score 0-100. 0 means a verified clear. Null whenever the screen did not complete. The full formula is documented in the README and versioned by risk\_model\_version. |
| `risk_level` | string | none (0), low (1-19), moderate (20-44), elevated (45-69) or high (70-100). Null when the screen did not complete. |
| `risk_reasons` | string | Plain-language list of exactly which factors contributed to the score. |

##### The nearest well

| Field | Type | Description |
|---|---|---|
| `nearest_distance_miles` | number | Great-circle distance from the site to the nearest documented orphaned well, in statute miles. |
| `nearest_distance_feet` | number | The same distance in feet, for site plans and Phase I text. |
| `nearest_bearing_degrees` | number | Initial great-circle bearing from the site to the nearest well, 0-360 degrees clockwise from true north. |
| `nearest_bearing_compass` | string | The same bearing as a 16-point compass direction. |
| `nearest_well_id` | string | Full identifier of the nearest well as published, including its system prefix. |
| `nearest_well_id_system` | string | Identifier system: API (110,976 rows), USGSID (6,121) or IGSID (575). |
| `nearest_well_name` | string | Lease or well name of the nearest well as the state records it. |
| `nearest_well_number` | string | Well number within the lease. Null on the 64,214 rows where the state publishes none. |
| `nearest_well_state` | string | State whose records the nearest well came from. |
| `nearest_well_county` | string | County of the nearest well. |
| `nearest_well_status_raw` | string | The state's own status text for the nearest well, verbatim and unmodified. This is the authoritative value. |
| `nearest_well_status_normalized` | string | Normalized bucket: orphan, potential\_orphan, abandoned, idle, shut\_in, suspended, active, forfeited, canceled, remediation\_pending, unknown or plugged. Null when the state uses an opaque code USGS publishes no codebook for. |
| `nearest_well_status_basis` | string | How the bucket was derived: literal\_text, documented\_in\_dataset, unmapped\_state\_code, or blank\_sentinel. Nothing is guessed. |
| `nearest_well_plugged_per_state_record` | boolean | True only when the state record literally says Plugged, PA or P\&A. False when the status unambiguously says otherwise. Null when the record does not say - which is the case for about a third of the dataset. |
| `nearest_well_type_raw` | string | The state's own well type text, verbatim. Null on the 59,909 rows where the state publishes none. |
| `nearest_well_type_normalized` | string | Coarse bucket: oil, gas, oil\_and\_gas, injection\_disposal, coalbed\_methane, storage, exploratory\_stratigraphic, dry\_hole, observation\_monitoring, water or permitted\_location\_only. Null for opaque state codes. |
| `nearest_well_injection_or_disposal` | boolean | True when the type text identifies an injection, disposal, brine, waterflood or EOR well - the types most relevant to a subsurface contamination pathway. Null when the type is not stated. |
| `nearest_well_latitude` | number | Latitude of the nearest well as USGS publishes it (NAD83 decimal degrees). |
| `nearest_well_longitude` | number | Longitude of the nearest well as USGS publishes it. |
| `nearest_well_positional_class` | string | How the coordinate was derived: surveyed\_or\_reported, datum\_converted, datum\_unconfirmed, third\_party\_derived, plss\_quarter\_quarter, plss\_quarter, plss\_section, planned\_not\_actual, questionable, or unspecified. |
| `nearest_well_positional_uncertainty_miles` | number | Approximate positional uncertainty implied by that class - about 0.71 mi for a PLSS section centroid, 0.01 mi for a surveyed coordinate. Null when the source states no method, or when the location is flagged questionable and the error is unbounded. |
| `nearest_well_positional_low_confidence` | boolean | True when the nearest well is located only to a PLSS section or quarter, is a permitted-not-actual location, or is flagged questionable - so the reported distance carries real uncertainty. Null when the source states no method. |
| `nearest_well_location_note` | string | The source's verbatim location note, so the positional class can be audited. |
| `nearest_well_status_date` | string | Date the state last set that status, parsed out of the free-text notes where the source buries it. Impossible dates (06/31/2005) and future dates (09/09/2099) present in the source are rejected rather than published. |
| `nearest_well_orphan_declared_date` | string | Date the state formally declared the well orphaned, where the note carries one. |
| `nearest_well_priority_class` | string | The state's own plugging priority ranking, where it publishes one (Kansas uses Priority 1A/1B/1C/2). |
| `nearest_well_operator_note` | string | Source note about the responsible operator. The dataset has NO operator column; where operator information exists at all it is free text such as "Orphan-No Responsible Operator". |
| `nearest_well_plss_location` | string | Township / range / section / quarter description of the nearest well, assembled from the nine PLSS columns. |
| `nearest_well_source_agency` | string | The state agency whose records USGS compiled this well from. |
| `nearest_well_data_file_date` | string | Date of the state data file this well came from. This is the well record's real vintage and it ranges from 2019-07-01 to 2022-12-10 across states. |

##### Composition of everything in the radius

| Field | Type | Description |
|---|---|---|
| `wells_plugged_per_state_record` | number | How many wells in the radius carry a state status that literally says plugged. The dataset is a compilation of UNPLUGGED orphaned wells, but 323 rows nationally do carry a plugged status, so the count ships rather than being assumed away. |
| `wells_not_plugged_per_state_record` | number | How many wells carry a status that unambiguously indicates they are not plugged. |
| `wells_plug_status_not_stated` | number | How many wells whose state record does not state a plugging status. These are the ones a Phase I most needs a state file review for. |
| `wells_injection_or_disposal` | number | Injection, disposal, brine, waterflood or EOR wells inside the radius. |
| `wells_type_not_stated` | number | Wells whose type the state does not publish (about half the national dataset). |
| `wells_low_positional_confidence` | number | Wells located only to a PLSS section or quarter, permitted-not-actual, or flagged questionable. |
| `wells_positional_class_not_stated` | number | Wells for which the source records no location method at all. |
| `wells_planned_location_only` | number | Wells whose published coordinate is a permitted (planned) location, not an as-drilled one. |
| `wells_questionable_location` | number | Wells the source itself flags as "Questionable location - Numerous duplicate coordinates". |
| `wells_datum_unconfirmed` | number | Wells whose horizontal datum the source could not confirm (NAD27 vs NAD83 can differ by up to about 200 m). |
| `wells_unmapped_status_codes` | string | Distinct state status codes found in the radius that USGS publishes no codebook for, listed so you can look them up with the issuing agency. Null when every status was decodable. |
| `count_by_status_raw_json` | string | JSON object of verbatim state status text to well count inside the radius. |
| `count_by_status_normalized_json` | string | JSON object of normalized status bucket to well count. "(not stated)" covers blanks and unmapped state codes. |
| `count_by_well_type_json` | string | JSON object of normalized well type to count. |
| `count_by_source_agency_json` | string | JSON object of state agency to count - the provenance of every well in the radius. |
| `count_by_state_json` | string | JSON object of state to count, which matters on a radius that crosses a state line. |
| `count_by_county_json` | string | JSON object of county to count. |
| `count_by_positional_class_json` | string | JSON object of positional-accuracy class to count, so the reliability of the whole set is visible at a glance. |
| `wells_data_vintage_earliest` | string | Earliest state data file date among the wells found for this site. |
| `wells_data_vintage_latest` | string | Latest state data file date among the wells found for this site. |

##### Per-well detail rows (record\_type = "well")

| Field | Type | Description |
|---|---|---|
| `well_rank_by_distance` | number | Rank of this well among all wells found for the site, 1 = nearest. |
| `well_object_id` | number | The layer OBJECTID, stable within a dataset vintage and useful for de-duplication. |
| `well_id` | string | Full published identifier including its system prefix. |
| `well_id_system` | string | Identifier system: API, USGSID or IGSID. |
| `well_id_value` | string | The identifier with the system prefix stripped - the value to paste into a state well-record search. |
| `well_name` | string | Lease or well name as the state records it. |
| `well_number` | string | Well number within the lease, where the state publishes one. |
| `well_state` | string | State whose records this well came from. |
| `well_county` | string | County of the well. |
| `well_latitude` | number | Published well latitude (NAD83 decimal degrees). |
| `well_longitude` | number | Published well longitude. |
| `well_distance_miles` | number | Great-circle distance from the site to this well, in statute miles. |
| `well_distance_feet` | number | The same distance in feet. |
| `well_bearing_degrees` | number | Initial bearing from the site to this well, 0-360 clockwise from true north. |
| `well_bearing_compass` | string | The same bearing as a 16-point compass direction. |
| `well_status_raw` | string | The state's own status text, verbatim. |
| `well_status_normalized` | string | Normalized status bucket, or null when the state code has no published codebook. |
| `well_status_basis` | string | literal\_text, documented\_in\_dataset, unmapped\_state\_code or blank\_sentinel. |
| `well_plugged_per_state_record` | boolean | True only when the state record literally says the well is plugged; false when it unambiguously says otherwise; null when it does not say. |
| `well_type_raw` | string | The state's own well type text, verbatim. |
| `well_type_normalized` | string | Coarse well-type bucket, or null for an opaque state code. |
| `well_type_basis` | string | literal\_text, unmapped\_state\_code or blank\_sentinel. |
| `well_injection_or_disposal` | boolean | True for injection, disposal, brine, waterflood, steamflood or EOR wells. Null when the type is not stated. |
| `well_positional_class` | string | How this coordinate was derived (see nearest\_well\_positional\_class for the full vocabulary). |
| `well_positional_uncertainty_miles` | number | Approximate positional uncertainty implied by that class, in miles. |
| `well_positional_low_confidence` | boolean | True when this coordinate is PLSS-derived, permitted-only or questionable. Null when the source states no method. |
| `well_datum_unconfirmed` | boolean | True when the source records that the horizontal datum is unconfirmed and NAD27 is likely. |
| `well_planned_location_only` | boolean | True when the published coordinate is a permitted (planned) location rather than an as-drilled one. |
| `well_questionable_location` | boolean | True when the source itself flags the coordinate as questionable. |
| `well_location_note` | string | The source's verbatim location note. |
| `well_status_date` | string | Date the state last set this status, parsed from the free-text notes. Invalid and future dates in the source are rejected. |
| `well_type_date` | string | Date associated with the well type in the source notes, where present. |
| `well_orphan_declared_date` | string | Date the state formally declared the well orphaned, where the note carries one. |
| `well_priority_class` | string | The state's plugging priority ranking, where published. |
| `well_operator_note` | string | Free-text operator note. There is no operator column in this dataset. |
| `well_coordinate_note` | string | Free-text note about how the coordinate was obtained, where the source records one separately. |
| `well_plss_location` | string | Township / range / section / quarter description assembled from the nine PLSS columns. |
| `well_source_agency` | string | State agency whose records this well came from. |
| `well_data_file_date` | string | Date of the state data file this well came from - the record's real vintage. |
| `well_info_raw` | string | The complete verbatim Well\_info note, kept so nothing fetched is silently discarded. |
| `well_other_note_raw` | string | The complete verbatim Other\_note field, kept for the same reason. |

### The screening score

`risk_score` is a transparent 0-100 screen, versioned by `risk_model_version`
(currently `1.0`). It is **not** a determination, and every contributing factor
is spelled out in `risk_reasons` on the row.

| Contribution | Points |
|---|---|
| Nearest well within 100 ft | +45 |
| Nearest well within 500 ft | +35 |
| Nearest well within 0.25 mi | +25 |
| Nearest well within 0.5 mi | +15 |
| Nearest well within 1 mi | +8 |
| A well in radius but further than 1 mi | +3 |
| Wells within 0.25 mi | +5 each, capped at +25 |
| More than 10 wells in the radius | +1 per 10, capped at +10 |
| Any injection/disposal well within 0.25 mi | +10 |
| Any well within 0.25 mi whose plugging status the state does not state | +7 |
| Any questionable or permitted-only well location in the radius | +8 |

Capped at 100. Levels: `none` = 0, `low` = 1-19, `moderate` = 20-44,
`elevated` = 45-69, `high` = 70-100.

**The score is gated on the verdict.** It is only ever computed for
`wells_found` and `no_documented_wells_in_covered_state`. A site that is out of
coverage, whose state could not be resolved, or whose source failed gets
`risk_score: null` and `risk_level: null` - **never `0` / `none`** - with
`risk_reasons` explaining why. Otherwise a buyer filtering on
`risk_level === "none"` would read a site the dataset has no data for as clean.

### Data vintage - read this before you cite it

This is a **compilation of state records, not a live feed**. Each state's slice
carries its own `File_date`, and they range from **2019-07-01 (Colorado) to
2022-12-10 (Louisiana)**. Every row publishes both the dataset-wide range
(`dataset_vintage_earliest` / `dataset_vintage_latest`) and the vintage of the
specific wells found (`wells_data_vintage_earliest` / `wells_data_vintage_latest`).

Practical consequences:

- Wells plugged since a state's file date may still appear here.
- Wells documented as orphaned since then will **not** appear.
- The dataset is titled *unplugged*, but 323 rows nationally carry a state status
  that literally says plugged. Those are counted separately in
  `wells_plugged_per_state_record` rather than quietly dropped or quietly
  included.

Always confirm a hit against the issuing state agency - `nearest_well_source_agency`
and `well_source_agency` name it, and `well_id_value` is the identifier to search.

### Coverage

27 states, measured live on every run and published on every row in
`dataset_states_covered`: Alabama, Alaska, Arkansas, California, Colorado,
Illinois, Indiana, Kansas, Kentucky, Louisiana, Michigan, Mississippi, Missouri,
Montana, Nebraska, Nevada, New Mexico, New York, North Dakota, Ohio, Oklahoma,
Pennsylvania, Tennessee, Texas, Utah, West Virginia, Wyoming.

Largest state counts: Ohio 20,557 - Pennsylvania 19,160 - Oklahoma 15,971 -
Kentucky 12,695 - Illinois 8,480 - New York 7,029 - Texas 5,854.

If a state ever *disappears* from the live dataset the run fails, because a lost
state silently turns every site there into a false clear.

### Status normalization, and what is deliberately left `null`

`*_status_raw` is always the state's own text, verbatim - that is the
authoritative value. `*_status_normalized` is populated only when the mapping is
defensible, and `*_status_basis` tells you which rule applied:

- `literal_text` - the English is unambiguous (`Orphan`, `Abandoned Well`,
  `Idle`, `Active`, `Plugged`, `Unknown Not Found`, ...).
- `documented_in_dataset` - the dataset's own notes decode the code. Only `AB`
  and `SI` qualify, from the Nebraska note *"Shut In to be converted to "AB" or
  "OR" by source"*.
- `blank_sentinel` - the source publishes a single space. All 5,854 Texas rows
  are in this state.
- `unmapped_state_code` - an opaque code with no published codebook. **These are
  left `null` rather than guessed.** The affected codes and their issuing states
  are: `OR` (Oklahoma 15,971 / Ohio 877), `HP` (Ohio 15,493), `UN` (Ohio 3,289),
  `OP` (Ohio 802), `LU` (Ohio 96), `TA` (Colorado 47 / Utah 12), `S` (Utah 58),
  `DA` (Colorado 56), `PR` (Colorado 39), `AL` (Colorado 5), `DM` (Colorado 4),
  `I` (Utah 2), `WO` (Colorado 2), `IJ` (Colorado 1), `XX` (Colorado 1).
  Any of them appearing in your radius is listed in `wells_unmapped_status_codes`.

Only `Plugged`, `PA` and `P&A` set `plugged_per_state_record: true`.

### Positional accuracy classes

| `positional_class` | Meaning | Uncertainty |
|---|---|---|
| `surveyed_or_reported` | An actual surveyed or operator-reported coordinate | ~0.01 mi |
| `datum_converted` | USGS converted the original NAD27 value to NAD83 | ~0.05 mi |
| `datum_unconfirmed` | Datum unconfirmed, NAD27 likely for older wells | ~0.15 mi |
| `third_party_derived` | Generated from third-party data (all 5,854 Texas rows) | ~0.15 mi |
| `plss_quarter_quarter` | Located to a 40-acre PLSS quarter-quarter | ~0.18 mi |
| `plss_quarter` | Located to a 160-acre PLSS quarter | ~0.35 mi |
| `plss_section` | Located to a 1-square-mile PLSS section centroid | ~0.71 mi |
| `planned_not_actual` | The *permitted* location, not an as-drilled one | ~0.25 mi |
| `questionable` | The source itself flags the coordinate as unreliable | unbounded (`null`) |
| `unspecified` | The source records no location method | `null` |

`*_positional_low_confidence` is `true` for `plss_section`, `plss_quarter`,
`planned_not_actual` and `questionable`; it is `null` - not `false` - when the
source states no method at all.

### Failure behaviour

Zero rows is a valid success **only** when the query was well formed, reached the
upstream, and the upstream honestly returned nothing.

| Situation | What happens |
|---|---|
| `assets` omitted | HTTP 400 at run creation. Nothing runs, nothing is billed. |
| The upstream layer has drifted or is unreachable | Run **FAILS** before any row is pushed. |
| Every site failed to screen | Run **FAILS**. The billing gate runs before `pushData`. |
| Some sites screened, some failed | Rows are emitted; the failed ones carry `wells_source_status: "unavailable"` and assert nothing about wells. |
| Query completed, no wells in radius | **SUCCESS** with a row saying so - a real answer. |

Every failure message ends with "Nothing was emitted and nothing was billed."

**A deliberate choice worth stating:** on a *partial* outage the failed sites do
emit one billable row each. That row is a genuine per-site answer - it says
explicitly that the source was unavailable and leaves every well field `null` -
and a total outage fails the run instead, so no one is ever billed for a dataset
of nothing but errors.

### Use as an MCP tool

This actor is callable by AI agents through [mcp.apify.com](https://mcp.apify.com).
Every input and every output field carries a description, so an agent can pick it
and chain it without guessing. It composes well: hand it coordinates produced by a
geocoder, then feed `phase1_esa_further_inquiry_flag` and `risk_level` into a
site-selection or due-diligence workflow. Because the null-vs-false contract is
explicit, an agent can tell "no wells here" apart from "we could not check", which
is exactly the distinction that makes an automated screen safe to act on.

### Pricing

**$8 per 1,000 results**, billed on the standard Apify result event - one charge
per dataset row. A summary-only run costs one result per site: screening 50 sites
is 50 results, **$0.40**. Turning on `includeWellDetail` bills one extra result
per well, so cap it with `maxWellsPerAsset` on dense sites. Graduated discounts
apply on paid Apify plans. A failed run emits nothing and bills nothing.

### FAQ

**Is there a free API for orphaned oil and gas wells near an address?**
The underlying USGS layer is free and keyless. What this actor adds is the part
that is easy to get wrong: complete paging with a truncation guard, a true-circle
radius, coverage gating so a no-data state is not reported as clear, positional
accuracy per well, and status normalization that refuses to guess.

**How many orphaned wells are there in the US?**
This dataset documents **117,672** across 27 states. Federal estimates of
*undocumented* orphaned wells run into the hundreds of thousands to millions, and
by definition none of those are in any dataset - which is why this is a screen and
not a clearance.

**Does a zero result mean my site is clean?**
Only when `screening_result` is `no_documented_wells_in_covered_state`. If it is
`out_of_dataset_coverage`, `coverage_unknown` or `source_unavailable`, the actor
has not answered the question and says so.

**Why is the nearest well's status blank or unmapped?**
Because the state publishes it that way. All 5,854 Texas rows carry a blank
status, and about a third of the dataset uses two-letter state codes USGS
publishes no codebook for. The raw value is always in `*_status_raw`; look it up
with the agency named in `*_source_agency`.

**Can I search a whole county or state instead of a point?**
Not directly - this is a point-and-radius screener. Use a large `radiusMiles`
(up to 25) around a centroid, or pass many points. The service's own exact count
is published in `wells_reported_by_source` so you always know the true size.

**Does it work for Phase I ESA reports?**
It is a screening tool, and every row cites the DOI, the issuing state agency and
the data vintage so it can be referenced properly. It is not a determination and
does not replace a state file review or a site reconnaissance.

**Why do some distances have a large uncertainty?**
Because the state never surveyed the well. A PLSS section-centroid location is
accurate to about 0.7 mile at best. `*_positional_uncertainty_miles` tells you
which wells those are instead of hiding it behind a four-decimal distance.

**How often does the data update?**
The USGS release is a periodic compilation, currently spanning 2019-2022 state
files. This actor reads it live on every run and fails loudly if the national
count collapses or a state disappears.

### Related actors

Screening a site properly takes more than one dataset. These pair directly with
this one:

- **[EPA Contaminated Site Screener](https://apify.com/malonestar/epa-contaminated-site-screener)**
  - Superfund/SEMS, RCRA, USTs, ECHO enforcement and institutional controls at
    the same coordinate. The standard Phase I companion to this one.
- **[Site Due Diligence Bundle](https://apify.com/malonestar/site-due-diligence-bundle)**
  - 20 federal and state layers for a single coordinate in one call, with a
    composite go / caution / no-go verdict.
- **[Oil & Gas Well Permits](https://apify.com/malonestar/oil-gas-well-permits)**
  - the other side of the same story: newly permitted and active wells from state
    regulators, where this actor covers the abandoned ones.

### Source

USGS, *US Documented Unplugged Orphaned Oil and Gas Well Dataset*,
<https://doi.org/10.5066/P91PJETI>, served from
`services.arcgis.com/v01gqwM5QqNysAAi` FeatureServer **layer 5**. Compiled from
27 state oil and gas regulators. Public domain.

# Actor input Schema

## `assets` (type: `array`):

One object per site: {"lat": 34.07, "lon": -118.29, "label": "Los Angeles infill site", "radiusMiles": 0.5}. lat/lon are WGS84 decimal degrees. label is free text used on every output row. radiusMiles is optional and overrides the run-level radius for that site only.

## `radiusMiles` (type: `integer`):

Run-level search radius in statute miles, used for any site that does not carry its own radiusMiles. Accepts 0.05 to 25; ASTM E1527 Phase I practice commonly uses 0.25, 0.5 or 1 mile. If omitted the actor uses 1 mile.

## `includeWellDetail` (type: `boolean`):

When true, each site's summary row is followed by one row per documented orphaned well inside the radius, nearest first, with full identifiers, status, type, positional accuracy and source notes. When false (the actor's behaviour if omitted) only the one summary row per site is emitted. Each row is a billable result, so leave this off for large-radius portfolio screens.

## `maxWellsPerAsset` (type: `integer`):

Caps how many per-well detail rows are emitted for each site when includeWellDetail is on. Wells are always emitted nearest-first, so the cap keeps the closest ones. If omitted the actor uses 100.

## `maxAssets` (type: `integer`):

Safety cap on how many sites a single run will screen. Extra sites are skipped with a warning in the log. If omitted the actor uses 50.

## `resolveAssetState` (type: `boolean`):

The USGS dataset covers 27 states. When this is on (the actor's behaviour if omitted) each site's state is resolved via the FCC census-block API with Census TIGERweb as a fallback, so a zero-well answer inside a covered state is reported as a genuine clear while a site in an uncovered state is reported as out\_of\_dataset\_coverage rather than as clear. Turn it off only to skip those two lookups.

## `skipDriftChecks` (type: `boolean`):

Diagnostic only. The actor normally verifies the live layer before emitting anything: field set, national well count floor, state coverage, status vocabulary, two positive canaries, two negative controls and a true-circle fidelity test. Skipping them removes the guarantee that the answers came from an undegraded source.

## `simulateOutage` (type: `string`):

Permanent diagnostic seam used to prove the failure path without waiting for a real outage. 'wells' fails the orphaned-well layer, 'state' fails the state resolver, 'both' fails both, 'none' is the normal behaviour. With 'wells' or 'both' the run fails loudly and emits nothing.

## Actor input object example

```json
{
  "assets": [
    {
      "lat": 34.07,
      "lon": -118.29,
      "label": "Los Angeles City oil field - infill parcel, CA",
      "radiusMiles": 0.5
    },
    {
      "lat": 41.4651,
      "lon": -79.6504,
      "label": "Oil City brownfield, Venango County PA",
      "radiusMiles": 1
    },
    {
      "lat": 39.7392,
      "lon": -104.9903,
      "label": "Denver CO downtown control site",
      "radiusMiles": 1
    },
    {
      "lat": 25.7617,
      "lon": -80.1918,
      "label": "Miami FL control site (outside dataset coverage)",
      "radiusMiles": 1
    }
  ],
  "radiusMiles": 1,
  "includeWellDetail": true,
  "maxWellsPerAsset": 10,
  "maxAssets": 50,
  "resolveAssetState": true,
  "simulateOutage": "none"
}
```

# Actor output Schema

## `results` (type: `string`):

The default dataset.

# 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 = {
    "assets": [
        {
            "lat": 34.07,
            "lon": -118.29,
            "label": "Los Angeles City oil field - infill parcel, CA",
            "radiusMiles": 0.5
        },
        {
            "lat": 41.4651,
            "lon": -79.6504,
            "label": "Oil City brownfield, Venango County PA",
            "radiusMiles": 1
        },
        {
            "lat": 39.7392,
            "lon": -104.9903,
            "label": "Denver CO downtown control site",
            "radiusMiles": 1
        },
        {
            "lat": 25.7617,
            "lon": -80.1918,
            "label": "Miami FL control site (outside dataset coverage)",
            "radiusMiles": 1
        }
    ],
    "radiusMiles": 1,
    "includeWellDetail": true,
    "maxWellsPerAsset": 10,
    "maxAssets": 50,
    "resolveAssetState": true,
    "skipDriftChecks": false,
    "simulateOutage": "none"
};

// Run the Actor and wait for it to finish
const run = await client.actor("malonestar/orphaned-well-proximity-screener").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 = {
    "assets": [
        {
            "lat": 34.07,
            "lon": -118.29,
            "label": "Los Angeles City oil field - infill parcel, CA",
            "radiusMiles": 0.5,
        },
        {
            "lat": 41.4651,
            "lon": -79.6504,
            "label": "Oil City brownfield, Venango County PA",
            "radiusMiles": 1,
        },
        {
            "lat": 39.7392,
            "lon": -104.9903,
            "label": "Denver CO downtown control site",
            "radiusMiles": 1,
        },
        {
            "lat": 25.7617,
            "lon": -80.1918,
            "label": "Miami FL control site (outside dataset coverage)",
            "radiusMiles": 1,
        },
    ],
    "radiusMiles": 1,
    "includeWellDetail": True,
    "maxWellsPerAsset": 10,
    "maxAssets": 50,
    "resolveAssetState": True,
    "skipDriftChecks": False,
    "simulateOutage": "none",
}

# Run the Actor and wait for it to finish
run = client.actor("malonestar/orphaned-well-proximity-screener").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "assets": [
    {
      "lat": 34.07,
      "lon": -118.29,
      "label": "Los Angeles City oil field - infill parcel, CA",
      "radiusMiles": 0.5
    },
    {
      "lat": 41.4651,
      "lon": -79.6504,
      "label": "Oil City brownfield, Venango County PA",
      "radiusMiles": 1
    },
    {
      "lat": 39.7392,
      "lon": -104.9903,
      "label": "Denver CO downtown control site",
      "radiusMiles": 1
    },
    {
      "lat": 25.7617,
      "lon": -80.1918,
      "label": "Miami FL control site (outside dataset coverage)",
      "radiusMiles": 1
    }
  ],
  "radiusMiles": 1,
  "includeWellDetail": true,
  "maxWellsPerAsset": 10,
  "maxAssets": 50,
  "resolveAssetState": true,
  "skipDriftChecks": false,
  "simulateOutage": "none"
}' |
apify call malonestar/orphaned-well-proximity-screener --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=malonestar/orphaned-well-proximity-screener",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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