# CA CalGEM Oil & Gas & Geothermal Well Register (`j0401/ca-wells`) Actor

California oil & gas / geothermal well register (public CalGEM data, ~242k wells): status (active/idle/plugged), well type, operator, county, field, HPZ, location. Due-diligence for environmental & mineral-rights research. Filter by county, operator, status, API number.

- **URL**: https://apify.com/j0401/ca-wells.md
- **Developed by:** [Wenhao Yang](https://apify.com/j0401) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 california oil/gas well registration records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

## CA CalGEM Oil & Gas & Geothermal Wells - California Well Register

California's Dept of Conservation / CalGEM publishes its **well register** (WellSTAR) as a free public map service - every oil, gas and geothermal well ever filed with the state. This actor turns it into a queryable, charged-per-record API - **for environmental due-diligence, mineral-rights and land research, and oil & gas supply-chain vetting.**

### What it covers

**~242.5k wells** across California (layer 0 of CalGEM's WellSTAR service). Each record carries:

| Field | What it is |
|---|---|
| `apiNumber` | the 10-digit API number - the stable per-well key |
| `status` | **Active** (53.9k) / Idle (30.3k) / **Plugged** (146.6k, sealed) / Canceled / New / PluggedOnly / Unknown |
| `wellType` | Oil & Gas / Waterflood / Cyclic Steam / Steamflood / Observation / Gas Storage / Water Disposal / Dry Gas ... |
| `operatorName` | who operates the well (Chevron, Aera Energy, California Resources...) |
| `county` / `district` | location (Kern is the giant; offshore areas are suffixed 'Offshore') |
| `fieldName` / `areaName` | producing field |
| `leaseName` / `wellNumber` | lease and well-on-lease identity |
| `section` / `township` / `range` / `baseMeridian` | PLSS survey location |
| `spudDate` / `spudYear` | when the well was first drilled |
| `inHPZ` | verified high-pressure-zone wells |
| `isConfidential` / `isDirectionallyDrilled` | flags |
| `latitude` / `longitude` | coordinates |

### Typical questions

- "How many **active** wells does this operator run in Kern County?"
- "Which wells are in a **verified HPZ** near this township/range?"
- "Every **plugged** well on this lease - did the site get sealed?"
- "Where are California's **gas-storage** wells (for storage-safety diligence)?"
- "New wells spudded since 2020 by county."

### Honest limits

The register is a **status snapshot**, not a production ledger: it carries **no depth, plug-report or bond columns**, and no per-well "last updated" timestamp (CalGEM exposes those only through other systems). Spud date is a text column, so year filtering happens after a bounded scan. Don't build depth-history claims on this data.

### Inputs

| Input | What it does |
|---|---|
| `status` | `Active` (default when no other filter is set) / `Idle` / `Plugged` / `Canceled` / `PluggedOnly` / `New` / `Unknown`. Leave empty to search all statuses (use with a county/operator/well-type filter for a full-status view) |
| `county` / `operator` / `leaseName` / `wellNumber` | name substrings |
| `wellType` | code or label (OG / 'Oil & Gas', WF / 'Waterflood', ...) |
| `apiNumber` | exact 10-digit API - single well |
| `inHPZ` / `confidential` / `directional` | yes/no flags |
| `spudYearFrom` / `spudYearTo` | first-drilled year range |
| `latMin/latMax/lonMin/lonMax` | bounding box |
| `aggregate` / `groupBy` | one row per group (county / status / wellType / operator / field / district) with a count |
| `maxResults` | cap records (default 200) |

**Default run = up to 200 active wells** - fast enough for the daily auto-test, and a live slice of California's operating wells.

### Low cost

**From $0.001 per record** - billed only for the rows you use, with a per-run charge cap so a broad query can't surprise-bill.

The register is **242,545 wells** across California's oil, gas and geothermal fields. The source publishes its drill dates as *strings*, not dates - so a naive year filter would silently mis-sort records - and its aggregate endpoint ignores its own row-count limit. We sidestep both: year filtering runs as a bounded scan on our side, aggregates are recomputed correctly client-side, and the source's quirky status values (a whitespace-less `NotCalGEMJurisdiction`, for one) are matched exactly rather than by sloppy substring. You query a clean well register by county / operator / status / API number; the data quirks stay on our side.

### Source

- [CalGEM WellSTAR (California Dept of Conservation)](https://gis.conservation.ca.gov/server/rest/services/WellSTAR/Wells/MapServer) - official, free public map service.

# Actor input Schema

## `status` (type: `string`):

Active = producing/operable (53.9k). Plugged = permanently sealed (146.6k). Idle / Canceled / New / PluggedOnly / Unknown. Leave empty to search any status (or when querying by API number / exact well).

## `county` (type: `string`):

County name substring (e.g. 'Kern', 'Los Angeles'). Offshore areas carry a suffix like 'Los Angeles Offshore'.

## `operator` (type: `string`):

Operator (well owner/operator) name substring (e.g. 'Chevron', 'Aera Energy').

## `wellType` (type: `string`):

Well type code or label, e.g. OG / 'Oil & Gas', WF / 'Waterflood', SC / 'Cyclic Steam', GS / 'Gas Storage'.

## `apiNumber` (type: `string`):

Exact 10-digit API number for a single well (e.g. 0403062844).

## `leaseName` (type: `string`):

Lease or property name substring.

## `wellNumber` (type: `string`):

Well number on the lease (e.g. '509 i').

## `inHPZ` (type: `string`):

HPZ status. yes = Verified HPZ. no = Not Within HPZ. You can also pick a specific source state: Potentially HPZ, Potentially Not Within HPZ, Uncertainty Area. Leave empty for any.

## `confidential` (type: `string`):

yes = only confidential wells. no = only non-confidential.

## `directional` (type: `string`):

yes = only directionally drilled wells. no = only vertical.

## `spudYearFrom` (type: `integer`):

Only wells first drilled (spudded) in or after this year.

## `spudYearTo` (type: `integer`):

Only wells spudded in or before this year.

## `latMin` (type: `number`):

Southern edge of a lat/lon bounding box (e.g. 35.0).

## `latMax` (type: `number`):

Northern edge of a lat/lon bounding box.

## `lonMin` (type: `number`):

Western edge of a lat/lon bounding box (e.g. -122.0).

## `lonMax` (type: `number`):

Eastern edge of a lat/lon bounding box.

## `aggregate` (type: `boolean`):

When on, returns one summary row per group with a well count - computed server-side.

## `groupBy` (type: `string`):

county / status / wellType / operator / field / district.

## `maxResults` (type: `integer`):

Cap records pushed (0 = a reasonable ceiling). Default = up to 200 active wells.

## Actor input object example

```json
{
  "status": "",
  "inHPZ": "",
  "aggregate": false,
  "groupBy": "county",
  "maxResults": 200
}
```

# Actor output Schema

## `recordsUrl` (type: `string`):

California oil & gas well records - as JSON

## `datasetUrl` (type: `string`):

No description

## `runUrl` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("j0401/ca-wells").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("j0401/ca-wells").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 '{}' |
apify call j0401/ca-wells --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,j0401/ca-wells"
        }
    }
}

```

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/xvR6AXzJZASJqbfY6/builds/YWCjfDFIkqpx7JA7K/openapi.json
