# USMIN Mine Feature Proximity Screener (`malonestar/usmin-mine-feature-proximity-screener`) Actor

Screens any US coordinate against USGS USMIN topographic mine symbols - adits, shafts, prospects, tailings, quarries - for Phase I ESA, geotechnical and land due diligence.

- **URL**: https://apify.com/malonestar/usmin-mine-feature-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 mine feature rows

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

## USMIN Mine Feature Proximity Screener

Screens any US coordinate against the USGS **USMIN Topographic Mine Symbols** dataset - adits, shafts, prospects, tailings, quarries and other historical workings that USGS field geologists digitized off topographic maps dating back to the early 1900s. Built for **Phase I Environmental Site Assessment (ASTM E1527-21)**, geotechnical due diligence (subsidence and mine-opening hazard), and acid-rock-drainage / abandoned-mine-drainage screening ahead of land acquisition.

### Who this is for

- **Environmental consultants** running a Phase I ESA who need to disclose historical mine workings within the ASTM search distance, not just active MSHA-permitted operations.
- **Geotechnical engineers** screening a parcel for subsidence risk from undocumented shafts, adits or open pits before siting a foundation.
- **Land and mineral-rights buyers** who want physical evidence of past mining (not just claims records) near a tract before closing.
- **Insurers and lenders** underwriting property in historic mining districts (Colorado, Nevada, Arizona, Montana, Utah, Appalachia) who need a defensible mine-hazard screen.

### What this is NOT

- **Not `blm-mining-claims`.** That actor covers BLM MLRS mineral **claims** - legal/administrative records of who holds rights to extract. This actor covers physical **workings** that were mapped on the ground - a shaft can exist with no active claim, and a claim can exist with no surface disturbance yet. They answer different questions.
- **Not an MSHA operations database.** Every MSHA-shaped Store competitor answers "which mines are permitted/active here." USMIN is historical and physical: features digitized from topographic maps, many predating MSHA (1977) or any modern permitting record entirely.

### How it works

For each asset (lat/lon), the actor queries all **four populated USMIN layers** - `24k_Points`, `625k_Points`, `24k_Polygons`, `625k_Polygons` - within the requested radius, dedupes, and returns:

1. **One `asset_summary` row per site** - counts, hazard-class breakdown, nearest point-feature distance, polygon-containment flag, and a screening verdict.
2. **One `mine_feature` row per matched feature** (optional, on by default) - full USMIN attributes plus a computed distance and hazard classification.

#### The false-clear trap this actor is built to avoid

The USMIN service exposes **nine** layers, not four. Three (`24k_Polygons_outlines`, `48k_Polygons_outlines`, `625k_Polygons_outlines`) are the same polygons re-served as lines - pure duplicates. Two more (`48k_Points`, `48k_Polygons`) are a near-abandoned scale series: **3,165 and 212 features nationally**, versus 466,747 / 101,205 / 142,658 / 11,703 on the four layers this actor actually uses (measured live 2026-08-11). An actor that queries "the polygons layer" by index, or resolves layers by numeric id instead of name, can silently land on one of these near-empty layers and report a confident "no mine features nearby" for the entire country. This actor resolves all four target layers **by name** against live service metadata on every run, and a **live drift gate** asserts each layer's national feature count stays well above the near-empty-layer magnitude before any row is ever billed. If USGS ever restructures the service, the run fails loudly instead of quietly downgrading to a false clear.

#### Distance is disclosed, never guessed

- **Point-layer hits** (adits, shafts) get an **exact** haversine distance from the asset to the feature's own coordinate.
- **Polygon-layer hits** (open pits, tailings ponds) get `distance_miles: 0` **only** when a real point-in-polygon test on the live geometry confirms the asset sits inside the footprint. A polygon that does **not** contain the asset (but is still within the search radius via the buffered intersects query) reports `distance_miles: null` with `distance_basis: "not_computed_polygon_layer"` - this actor will never publish a centroid-to-point or nearest-vertex-guess distance dressed up as a real number. (A sibling actor in this portfolio shipped exactly that bug - a "largest-acreage proxy" nearest distance that was 3x wrong.)

#### `Topo_Date` is a map vintage, not a mine date

USMIN's `Topo_Date` records the **year the source topographic quadrangle was published**, not when the mine feature was active, opened, or closed. A Leadville CO adit carrying `Topo_Date: "1969"` was mapped in 1969 - it could have been dug decades earlier. This actor emits it as `source_map_year` and documents it as provenance, never as a mine-activity date.

#### Cross-sell: trace a hit back to its source map

Every feature row carries `scan_id`, `source_map_name`, `source_map_year` and `source_map_scale` - the exact identifiers needed to pull up the scanned topographic sheet a feature was digitized from in **`usgs-historical-topo-records-review`**. This is the only place in the portfolio where a spatial hit traces back to its literal source document.

### Input

```json
{
  "assets": [
    { "lat": 39.2508, "lon": -106.2925, "label": "Leadville CO - historic silver-lead district" },
    { "lat": 40.5225, "lon": -112.1489, "label": "Bingham Canyon UT - Kennecott open-pit copper mine" },
    { "lat": 37.6872, "lon": -97.3301, "label": "Wichita KS - clear control" }
  ],
  "radiusMiles": 2,
  "includeFeatureDetail": true,
  "maxFeaturesPerAsset": 0
}
```

| Field | Required | Description |
|---|---|---|
| `assets` | **Yes** | Array of `{lat, lon, label}`. Missing or empty fails the run loudly (never a silent empty success). |
| `radiusMiles` | No | Search radius in statute miles, 0.05-25. If omitted, the actor applies a documented 2-mile default **in code** (never a schema default - see the gotcha below) and logs that it did so. |
| `includeFeatureDetail` | No, default `true` | Emit one `mine_feature` row per matched feature in addition to the summary row. |
| `maxFeaturesPerAsset` | No, default `0` (unlimited) | Caps detail rows per asset, ordered nearest-first. The summary row's counts are always the true, untruncated totals; `feature_detail_rows_truncated` discloses whether a cap actually cut anything. |

**Why `radiusMiles` has a `prefill`, not a schema `default`:** an Apify input-schema `default` on a field that becomes a query predicate is injected server-side into *every* run, including programmatic/MCP calls that never saw the Console form - this has silently changed the meaning of several actors' filters elsewhere in this portfolio. `radiusMiles` instead ships only a Console `prefill`; a caller who truly omits it gets a documented, logged, code-level fallback.

### Output

One dataset with two record types, distinguished by `record_type`.

#### `asset_summary` rows (one per screened site)

*This table was generated from `.actor/actor.json`, which is itself generated from the actor's real pure functions run against real captured fixtures - every field below is a field the code can genuinely emit.*

| Field | Type | Description |
|---|---|---|
| `record_type` | string/null | asset\_summary for the one row per screened site, or mine\_feature for a per-feature detail row (emitted when includeFeatureDetail is on). |
| `asset_label` | string/null | The label supplied for this asset, or a synthesized default from its coordinates. |
| `asset_lat` | number/null | Latitude of the screened asset. |
| `asset_lon` | number/null | Longitude of the screened asset. |
| `search_radius_miles` | number/null | The search radius applied for this asset, in statute miles. |
| `checked_at` | string/null | ISO 8601 timestamp when this asset was screened. |
| `dataset_source` | string/null | Name of the upstream dataset (USGS USMIN Topographic Mine Symbols). |
| `layer_points_24k_status` | string/null | ok or unavailable outcome for the 24k\_Points USMIN layer on this asset. |
| `layer_points_625k_status` | string/null | ok or unavailable outcome for the 625k\_Points USMIN layer on this asset. |
| `layer_polygons_24k_status` | string/null | ok or unavailable outcome for the 24k\_Polygons USMIN layer on this asset. |
| `layer_polygons_625k_status` | string/null | ok or unavailable outcome for the 625k\_Polygons USMIN layer on this asset. |
| `mine_features_status` | string/null | ok (all 4 layers answered), partial (some failed) or unavailable (all failed) for this asset. |
| `mine_features_matched_total` | number/null | Total USMIN features matched within radius across all 4 layers, per the service's own returnCountOnly answer. Null when the source was totally unavailable, never a substitute 0. |
| `mine_features_retrieved_total` | number/null | Total USMIN features actually retrieved. Equals matched\_total for every layer that answered - a mismatch is refused before it ever reaches this row. |
| `mine_features_query_complete` | boolean/null | True when retrieved equals matched for every layer that answered. |
| `mine_features_present` | boolean/null | True if any layer found a feature (safe under partial coverage, since more coverage can only add matches). False only when ALL 4 layers answered and found nothing. Null when coverage was partial and nothing was found - an unverified negative. |
| `hazard_class_opening_count` | number/null | Count of matched features classed as a subsurface opening such as an adit, shaft or prospect pit - subsidence/fall hazard. |
| `hazard_class_waste_or_tailings_count` | number/null | Count of matched features classed as waste or tailings - AMD/geotechnical hazard. |
| `hazard_class_surface_disturbance_count` | number/null | Count of matched features classed as a surface-disturbance extraction pit or quarry. |
| `hazard_class_support_infrastructure_count` | number/null | Count of matched features classed as non-hazard support infrastructure (mill site, tipple). |
| `hazard_class_unclassified_count` | number/null | Count of matched features whose Ftr\_Type is not yet in this actor's hazard-class map. Should be 0 on a healthy run - a live drift gate fails the run if the upstream vocabulary grows. |
| `nearest_feature_distance_miles` | number/null | Distance in statute miles to the nearest POINT-layer feature (adit, shaft, etc). Null if no point-layer feature matched - a polygon distance is never substituted here. |
| `nearest_feature_type` | string/null | Raw USMIN Ftr\_Type of the nearest point-layer feature. |
| `nearest_feature_hazard_class` | string/null | Hazard class of the nearest point-layer feature. |
| `nearest_feature_layer` | string/null | Which USMIN layer the nearest point-layer feature came from. |
| `asset_inside_mapped_mine_feature` | boolean/null | True if the asset coordinate falls inside a mapped mine polygon footprint, verified by a real point-in-polygon test on the live geometry, never a proxy. |
| `feature_detail_rows_included` | boolean/null | Whether per-feature detail rows were requested for this run (includeFeatureDetail input). |
| `feature_detail_rows_returned` | number/null | How many mine\_feature detail rows were actually emitted for this asset. |
| `feature_detail_rows_truncated` | boolean/null | True if maxFeaturesPerAsset cut the detail rows below the true matched total. The summary counts above always report the untruncated truth. |
| `verdict` | string/null | Screening verdict: source\_unavailable, partial\_source\_unavailable, inside\_mapped\_feature, clear, opening\_hazard\_nearby, waste\_hazard\_nearby, or surface\_feature\_nearby. |
| `verdict_reasons` | string/null | Human-readable reasons supporting the verdict. |
| `error` | string/null | Error message when mine\_features\_status is unavailable. Null on every healthy or partial row. |

#### `mine_feature` rows (one per matched feature, when `includeFeatureDetail` is on)

| Field | Type | Description |
|---|---|---|
| `layer_key` | string/null | Internal key of the USMIN layer this feature came from: points\_24k, points\_625k, polygons\_24k, or polygons\_625k. |
| `layer_name` | string/null | USMIN service layer name this feature came from. |
| `layer_id` | number/null | USMIN service layer id this feature came from, resolved by name at runtime and never hard-coded. |
| `geometry_type` | string/null | point or polygon - the native geometry of the source layer. |
| `object_id` | number/null | USMIN OBJECTID of this feature within its layer. Unique per layer, not globally. |
| `state` | string/null | US state abbreviation, as published by USMIN. |
| `county` | string/null | County name, as published by USMIN. |
| `feature_type` | string/null | Raw USMIN Ftr\_Type value, for example Adit, Mine Shaft, Tailings - Pond, Quarry. |
| `hazard_class` | string/null | This actor's editorial hazard grouping of feature\_type: opening, waste\_or\_tailings, surface\_disturbance, support\_infrastructure, or unclassified. |
| `feature_name` | string/null | USMIN Ftr\_Name, when the source map named the feature. Null on most features - this does not mean the feature is not real. |
| `feature_azimuth_deg` | number/null | Compass azimuth in degrees for a linear point feature such as an adit. Point layers only. |
| `source_map_name` | string/null | Name of the source USGS topographic quadrangle this feature was digitized from. |
| `source_map_year` | number/null | Publication year of the source topographic map (Topo\_Date). This is the map's vintage, NOT the year the mine feature was active or closed. |
| `source_map_scale` | string/null | Scale of the source topographic map, for example 24000 or 625000. |
| `compiled_by` | string/null | Agency that compiled this USMIN record, typically USGS. |
| `remarks` | string/null | Free-text remarks published by USMIN for this feature, when present. |
| `gda_id` | string/null | USMIN Geologic Data Archive identifier for the source map. |
| `scan_id` | string/null | USMIN ScanID. Cross-references the scanned source topo sheet in usgs-historical-topo-records-review. |
| `lat` | number/null | Latitude of the feature. Point layers only; null for polygon-layer features. |
| `lon` | number/null | Longitude of the feature. Point layers only; null for polygon-layer features. |
| `distance_miles` | number/null | Distance in statute miles from the asset to this feature. Exact for point layers; 0 for a polygon that geometrically contains the asset; null otherwise. Never a centroid or nearest-vertex guess - see distance\_basis. |
| `distance_basis` | string/null | How distance\_miles was computed: point\_feature\_exact, asset\_inside\_polygon, or not\_computed\_polygon\_layer. Disclosed rather than guessed. |
| `asset_inside_feature` | boolean/null | True or false for polygon-layer features, a real computed point-in-polygon result. Null for point-layer features, where the concept does not apply. |
| `feature_area_sq_m` | number/null | Polygon area in square meters. Polygon layers only. |
| `feature_perimeter_m` | number/null | Polygon perimeter in meters. Polygon layers only. |

`asset_label`, `asset_lat`, `asset_lon` and `search_radius_miles` also appear on every `mine_feature` row so detail rows are self-contained.

### Screening verdicts

| Verdict | Meaning |
|---|---|
| `source_unavailable` | All four USMIN layers failed for this asset. No answer was verified. |
| `partial_source_unavailable` | One or more layers failed. Never presented as a clean clear, even if the layers that did answer found nothing. |
| `inside_mapped_feature` | The asset coordinate falls inside a mapped mine polygon footprint. |
| `clear` | All four layers answered; no feature matched within the radius. |
| `opening_hazard_nearby` | A subsurface opening (adit, shaft, pit) was matched - the highest-severity finding. |
| `waste_hazard_nearby` | A waste/tailings feature was matched, no opening. |
| `surface_feature_nearby` | Only surface-disturbance or support-infrastructure features were matched. |

This is a **screening** tool, not a determination. `verdict` and `hazard_class` are an editorial grouping of USMIN's raw `Ftr_Type` values to make results scannable; every row carries the raw `feature_type` so a reviewer can re-derive their own classification.

### Pricing

**$8 per 1,000 Result events** (one dataset row = one Result event), with the portfolio's standard graduated volume discounts (Bronze/Silver/Gold/Platinum/Diamond). A failed run bills nothing.

### Use as an MCP tool

This actor is discoverable to AI agents (Claude, Cursor, etc.) via `mcp.apify.com` under Pay-Per-Event pricing. A typical agent prompt:

> "Check whether 123 Mountain View Dr, Leadville, CO has any historical mine workings within a half mile, and tell me if any of them are subsurface openings."

Client config (Claude Desktop / Claude Code / Cursor):

```json
{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": ["-y", "@apify/actors-mcp-server", "--actors", "malonestar/usmin-mine-feature-proximity-screener"]
    }
  }
}
```

### FAQ

**Does this replace an MSHA mine-operations lookup?** No. USMIN and MSHA are different record classes - MSHA covers permitted operations, USMIN covers physical workings mapped from topographic surveys, many with no corresponding modern permit.

**Why does `nearest_feature_distance_miles` come back null when `mine_features_matched_total` is greater than zero?** All the matches within radius were polygon-layer features that do not contain the asset coordinate. Their existence is confirmed by the search (they intersect the buffered search circle), but this actor will not publish a guessed distance to a polygon boundary - see `mine_feature.distance_basis`.

**Why is `feature_name` null on almost every row?** USMIN only records a name when the source topographic map labeled the feature. An unnamed feature is not a less-real feature.

**Can I trust a `clear` verdict?** Only when `mine_features_status` is `ok`. A `partial_source_unavailable` verdict means part of the search never completed - treat it as "recheck," not "confirmed clear."

# Actor input Schema

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

Sites to screen. Each item needs lat, lon, and an optional label. Required - the actor cannot answer without at least one coordinate.

## `radiusMiles` (type: `number`):

How far around each asset to search for mapped mine features, in statute miles. If omitted the actor applies a 2-mile default in code (never a schema default, so a caller who omits it gets a documented, logged fallback rather than a silently injected value). Must be greater than 0 and at most 25.

## `includeFeatureDetail` (type: `boolean`):

When true (default), emit one row per matched mine feature in addition to the one asset-summary row. When false, only the summary row is emitted (cheaper for a pure go/no-go screen).

## `maxFeaturesPerAsset` (type: `integer`):

Caps the number of per-feature detail rows billed per asset, ordered nearest-first among point-layer hits (polygon-layer hits, which have no computed distance, are appended after). 0 means unlimited - every matched feature is returned and billed. The asset-summary row always reports the TRUE total matched and retrieved counts and sets feature\_detail\_rows\_truncated honestly, regardless of this cap.

## Actor input object example

```json
{
  "assets": [
    {
      "lat": 39.2508,
      "lon": -106.2925,
      "label": "Leadville CO - historic Lake County silver-lead district"
    },
    {
      "lat": 40.5225,
      "lon": -112.1489,
      "label": "Bingham Canyon UT - Kennecott open-pit copper mine"
    },
    {
      "lat": 37.6872,
      "lon": -97.3301,
      "label": "Wichita KS - clear control, no mining history"
    }
  ],
  "radiusMiles": 2,
  "includeFeatureDetail": true,
  "maxFeaturesPerAsset": 0
}
```

# 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": 39.2508,
            "lon": -106.2925,
            "label": "Leadville CO - historic Lake County silver-lead district"
        },
        {
            "lat": 40.5225,
            "lon": -112.1489,
            "label": "Bingham Canyon UT - Kennecott open-pit copper mine"
        },
        {
            "lat": 37.6872,
            "lon": -97.3301,
            "label": "Wichita KS - clear control, no mining history"
        }
    ],
    "radiusMiles": 2
};

// Run the Actor and wait for it to finish
const run = await client.actor("malonestar/usmin-mine-feature-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": 39.2508,
            "lon": -106.2925,
            "label": "Leadville CO - historic Lake County silver-lead district",
        },
        {
            "lat": 40.5225,
            "lon": -112.1489,
            "label": "Bingham Canyon UT - Kennecott open-pit copper mine",
        },
        {
            "lat": 37.6872,
            "lon": -97.3301,
            "label": "Wichita KS - clear control, no mining history",
        },
    ],
    "radiusMiles": 2,
}

# Run the Actor and wait for it to finish
run = client.actor("malonestar/usmin-mine-feature-proximity-screener").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 '{
  "assets": [
    {
      "lat": 39.2508,
      "lon": -106.2925,
      "label": "Leadville CO - historic Lake County silver-lead district"
    },
    {
      "lat": 40.5225,
      "lon": -112.1489,
      "label": "Bingham Canyon UT - Kennecott open-pit copper mine"
    },
    {
      "lat": 37.6872,
      "lon": -97.3301,
      "label": "Wichita KS - clear control, no mining history"
    }
  ],
  "radiusMiles": 2
}' |
apify call malonestar/usmin-mine-feature-proximity-screener --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,malonestar/usmin-mine-feature-proximity-screener"
        }
    }
}

```

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/jM06f9oZWzwJCPeZp/builds/5i7vvd6HsHV9ZK3c6/openapi.json
