# Florida Well Data Lookup (`cwayr/florida-well-lookup`) Actor

Look up Florida well depth, casing and initial water level records by coordinates, address, ZIP code (ZCTA area) or county. Answers from a bundled data snapshot. Blank depth means not reported.

- **URL**: https://apify.com/cwayr/florida-well-lookup.md
- **Developed by:** [Caleb Waymeyer](https://apify.com/cwayr) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $40.00 / 1,000 well records

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Florida Well Data Lookup

Look up Florida well records near any point, street address, ZIP code or county. Each record gives the well's
reported **total depth**, **casing depth and diameter**, **static water level at construction**, well use,
permit ID, district and map coordinates. Use it as a **Florida well depth lookup** before buying land, planning
a new well, pricing a drilling job, or checking what nearby wells reached. Every run also tells you the
**typical water-supply well depth** across all matching records.

**Coverage: North and Central Florida.** 52 of Florida's 67 counties have 2,000 or more records each. South
Florida (Miami-Dade, Broward, Palm Beach, Lee, Collier and nearby counties) has only partial coverage: a few
hundred to about 2,000 records per county, mostly USGS observation wells, and no county well permits; see
[Coverage by county](#coverage-by-county). Searches with no results are not charged.

Answers come from a snapshot of about 1.47 million well records from Florida's five water management districts
and U.S. Geological Survey (USGS) groundwater sites, bundled inside the Actor, so runs take a few seconds and
don't depend on any outside map server. Only address
search makes a network call, to the U.S. Census Bureau Geocoder.

### What you can search

| Search by | Input | Returns |
|---|---|---|
| Latitude / longitude | `latitude`, `longitude`, `radiusMiles` (0.1 to 25, default 3) | Nearest records within the radius, closest first, with `distanceMiles` |
| Street address | `address` (a Florida address) | Same as above, around the geocoded point |
| ZIP code | `zip` (5 digits) | Records inside that ZIP code (ZCTA area) |
| County | `county` (any of the 67 Florida counties) | Records in that county |

Optional filters: `wellUse` (`domestic`, `irrigation`, `public_supply`, `agricultural`, `livestock`,
`monitoring`, `injection`, `other` or `unknown`). The form is prefilled with the water-supply uses
(`domestic`, `irrigation`, `public_supply`, `agricultural` and `livestock`). Leaving `wellUse` empty
returns every use, including USGS sites, which have use `unknown` and dominate South Florida.
`sources` (one or more water management districts; USGS sites count in the district they lie in),
`onlyWithDepth` (on by default, so records with no reported depth are skipped), and `maxResults`
(1 to 1000, default 25). The Store form opens on Orlando (28.5383, -81.3792), radius 3 miles, 25 records.

#### Example inputs

Well data by coordinates:

```json
{ "queryType": "point", "latitude": 28.5383, "longitude": -81.3792, "radiusMiles": 3, "maxResults": 25 }
```

Well data by address:

```json
{ "queryType": "address", "address": "number street, city, FL ZIP", "radiusMiles": 1 }
```

Well data by ZIP code or county. The ZIP example leaves `wellUse` empty (every use, including USGS
sites) and turns `onlyWithDepth` off. The county example keeps domestic wells only:

```json
{ "queryType": "zip", "zip": "32801", "wellUse": [], "onlyWithDepth": false, "maxResults": 100 }
{ "queryType": "county", "county": "Alachua", "wellUse": ["domestic"], "maxResults": 200 }
```

### Output

One dataset row per well record. Every row is a billed result. Keys are flat, so the dataset exports cleanly
to CSV, Excel or JSON.

| Field | Meaning |
|---|---|
| `recordId` | Record identifier within this data snapshot |
| `distanceMiles` | Distance from your search point (null for ZIP and county searches) |
| `latitude`, `longitude` | Map point as published by the district, to 6 decimal places |
| `county`, `zcta` | County and ZIP code (ZCTA area) |
| `wmd`, `sourceId`, `sourceName`, `permitId`, `flUniqueWellId` | District code, source layer id, readable source name, permit ID, Florida unique well ID (only when the district gave one in the official `ABC1234` format). `sourceName` is derived from `sourceId`: USGS, FDEP, St. Johns River WMD, Southwest Florida WMD, Northwest Florida WMD, Suwannee River WMD, or South Florida WMD. An unrecognized id is left unchanged, and a missing id is null. For USGS sites, `wmd` is the district the site lies in, `permitId` is null, and `recordId` ends in the USGS site ID |
| `wellUse` | Well use category |
| `totalDepthFt` | Total depth in feet. **Null means not reported, never zero.** |
| `depthKind` | `well_depth`, `proposed_well_depth`, `permit_depth` (SFWMD), or `hole_depth` (USGS drilled hole depth, when the well depth is not reported) |
| `casingDepthFt`, `casingDiameterIn` | Casing depth (feet) and diameter (inches) |
| `staticWaterLevelFt` | Water level below land surface **reported at construction**, not today. Negative = above ground (flowing well) |
| `vintage`, `vintageNote` | Record date. Null when there is no date (all SJRWMD, NWFWMD, SRWMD and USGS records, and some SWFWMD records); `vintageNote` then says why |
| `locationConfidence` | How the map point was located, for example `gps`, `address_match` or `digitized`. For USGS sites, the stated accuracy: `usgs_within_1_second` (about 100 ft), `usgs_within_5_seconds`, `usgs_within_10_seconds` or `usgs_within_1_minute` (about 1 mile) |
| `dataBuild` | Date of the data snapshot |

#### Sample record

```json
{
  "recordId": "wmd-sjrwmd-well-completions:stn:000225",
  "distanceMiles": 0.1923,
  "latitude": 28.535627,
  "longitude": -81.378316,
  "county": "Orange",
  "zcta": "32803",
  "wmd": "SJRWMD",
  "sourceId": "wmd-sjrwmd-well-completions",
  "sourceName": "St. Johns River WMD",
  "permitId": "000225",
  "flUniqueWellId": null,
  "wellUse": "domestic",
  "totalDepthFt": 168,
  "depthKind": "well_depth",
  "casingDepthFt": 54,
  "casingDiameterIn": null,
  "staticWaterLevelFt": null,
  "vintage": null,
  "vintageNote": "district_layer_publishes_no_date",
  "locationConfidence": "gps",
  "dataBuild": "2026-10-23"
}
```

(Sample values are made up; the format matches real records.)

#### Typical depth in the area

The status message gives the typical depth of **water-supply wells** (domestic, irrigation, public supply,
agricultural and livestock) across **every** matching record, not just the ones returned. For example:

> Returned 25 well records within 5 mi (9,865 matched). Typical water-supply well depth 110 ft (middle half
> 90-145 ft, from 5,071 records).

Monitoring wells are left out of this figure on purpose. They are usually shallow test holes (10 to 40 ft), and
in cities they make up most of the records, so including them would understate how deep a drinking or
irrigation well needs to go. USGS sites have no well use in the source, so they count as `unknown` and are left
out of the water-supply figure too. The form is prefilled with water-supply uses, so a South Florida run from
that form often returns nothing: USGS sites (use `unknown`) dominate there. Leave `wellUse` empty to return
every use, including those sites. `areaStats.allMatching` then gives their depth range. The run summary has the full numbers (median, middle half, minimum and maximum) for
total depth, casing depth and static water level, both for water-supply wells (`areaStats.waterSupplyWells`)
and for all matches (`areaStats.allMatching`). These stats are free: they are in the summary, not in billed
dataset rows.

#### Run summary

Each run also writes a `RUN_SUMMARY` record to the key-value store (turn off with `includeSummary: false`). It
holds `totalWithinRadius` (or the area total), `returned`, `charged`, why results were capped, the area depth
stats above, the geocode match type for address searches, the data snapshot date, and the disclaimers below. The summary is not a
dataset row and is never charged. If a run fails (invalid input, or the geocoder not responding), the summary
still records the status and the reason, with zero records returned.

### Pricing and limits

- Pay per result: one `well-record` event per returned record ($0.04 per record). Nothing else is charged per
  record, and the run summary is free.
- If your maximum cost per run allows fewer records than you asked for, the Actor returns as many as fit and
  stops cleanly.
- **Free Apify plan:** at most 100 records per run. The status message tells you when this limit applied.
- Address searches that can't be matched, invalid input, and searches with no results return no records, so no
  records are charged.

### Coverage by county

Records per county in the current snapshot:

| Records | Counties |
|---|---|
| 10,000 or more | Alachua, Bay, Brevard, Charlotte, Citrus, Clay, DeSoto, Duval, Escambia, Flagler, Hardee, Hernando, Highlands, Hillsborough, Indian River, Jackson, Lake, Leon, Levy, Manatee, Marion, Nassau, Okaloosa, Orange, Pasco, Pinellas, Polk, Putnam, Santa Rosa, Sarasota, Seminole, St. Johns, Sumter, Volusia, Walton |
| 2,000 to 9,999 | Baker, Bradford, Calhoun, Columbia, Dixie, Gadsden, Gilchrist, Gulf, Hamilton, Holmes, Jefferson, Madison, Osceola, Suwannee, Taylor, Wakulla, Washington |
| 500 to 1,999 | Franklin, Lafayette, Liberty, Union; and in South Florida (mostly USGS sites) Broward, Collier, Lee, Miami-Dade, Palm Beach |
| Fewer than 500 (sparse) | Glades, Hendry, Martin, Monroe, Okeechobee, St. Lucie |

Field completeness also varies by source. Total depth is reported for about 90% of district records and for every
USGS site (sites without a depth are not included). Static water level at construction is reported for about
52-69% of records in every district except SFWMD, and never for USGS sites (64% overall). Only SWFWMD records
(Tampa Bay and Southwest Florida) carry a date.

### Coverage and limitations (please read)

- **Not an official record or survey.** Records are map points published by Florida's water management
  districts (SJRWMD, SWFWMD, NWFWMD, SRWMD and SFWMD) and USGS groundwater sites. No agency endorses this Actor.
- **Not every well in Florida is included.** Wells built before permitting began and unreported domestic wells
  are missing.
- **South Florida is only partly covered.** It has about 6,500 USGS groundwater sites (mostly observation wells,
  use unknown) and fewer than 1,000 SFWMD permit records. Well permits from the South Florida counties with
  delegated well permitting are missing. This is the most common reason for few or no results.
- **USGS sites** have no well use, casing, water level or date in this Actor. Sites 3,000 ft or deeper (oil and
  gas test holes) are left out.
- **Blank means not reported.** A null depth, casing or water level was not reported. It is never zero. Records
  without a depth are skipped by default (`onlyWithDepth` is on). Set `onlyWithDepth` to false to include them.
- SFWMD depths are **permit depths**, not measured depths.
- The static water level was measured **at construction**, not today.
- **A record is not a unique well.** One well can appear in several permits or districts, or as both a district
  record and a USGS site. Only exact duplicates (same source, permit, coordinates, depth and casing) were removed.
  Records are not merged across sources.
- Depths are stored to the nearest 0.25 ft. Coordinates are rounded to 6 decimal places (about 10 cm).
- The data is a fixed snapshot (see `dataBuild`) with no freshness guarantee.
- **Verify with the water management district or a licensed well driller** before relying on this data for
  drilling, design or a sale.

### ZIP codes

ZIP search uses Census ZIP Code Tabulation Areas (ZCTA). A ZCTA is close to the USPS ZIP code area but not
identical, so a few records near a ZIP boundary may be assigned to a neighboring ZIP.

### FAQ

**How deep are wells near me?** Run an address search with a radius of 1 to 5 miles. The status message gives
the typical water-supply well depth around that point, and the returned records show individual wells.

**Why are there no results near me?** Coverage is incomplete, especially in South Florida (see
[Coverage by county](#coverage-by-county)), and some areas simply have few permitted wells. The form is
prefilled with water-supply uses. Leaving `wellUse` empty returns every use, including USGS sites (use
`unknown`), which dominate South Florida. You can also try a larger radius or a county search.

**Why is there no typical depth for my South Florida search?** Most South Florida records are USGS sites,
whose well use is `unknown`, so they aren't counted as water-supply wells. Leave `wellUse` empty to include
them. The run summary's `areaStats.allMatching` then gives the depth range of every match.

**Why is `totalDepthFt` null?** The district record didn't report a depth. We never fill in a guess or a zero.
The default search skips those records. Set `onlyWithDepth` to false to include them.

**Can I get well depth by address?** Yes. Use `queryType: "address"`. Your address is used only for geocoding and
is not stored in the output.

**Is this the same as a well completion report?** No. These are summary map records. For the full report, ask
the water management district.

### Address geocoding attribution

Address geocoding uses the U.S. Census Bureau Geocoder. This product uses the Census Bureau Data API but is not
endorsed or certified by the Census Bureau.

# Actor input Schema

## `queryType` (type: `string`):

How to find wells. Point and address searches return the nearest records within the radius, closest first. ZIP and county searches return records inside that area (radius is ignored).

## `latitude` (type: `number`):

Decimal degrees, WGS84. Florida only (24.4 to 31.1). Used when "Search by" is point.

## `longitude` (type: `number`):

Decimal degrees, WGS84, negative west. Florida only (-87.7 to -79.8). Used when "Search by" is point.

## `address` (type: `string`):

A Florida street address, in the form "number street, city, FL ZIP". Geocoded with the U.S. Census Bureau Geocoder. If the address cannot be matched, the run ends with a message and nothing is charged. The address text is not stored in the output.

## `zip` (type: `string`):

5-digit ZIP code. Matched against the Census ZIP Code Tabulation Area (ZCTA) each record falls in, which is close to but not identical to the USPS ZIP code.

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

Florida county. Used when "Search by" is county.

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

Search radius around the point or address, 0.1 to 25 miles. Defaults to 3.

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

Maximum number of well records to return (and be charged for), 1 to 1000. Defaults to 25. Users on the free Apify plan get at most 100 records per run.

## `wellUse` (type: `array`):

Only return records with one of these well use values. The form is prefilled with the water-supply uses domestic, irrigation, public_supply, agricultural and livestock. Leave it empty to return every use, including USGS sites (well use "unknown"), which dominate South Florida. Unknown values are rejected with the list of valid values.

## `onlyWithDepth` (type: `boolean`):

On by default. Skip records whose total depth was not reported. Turn this off to include those records with totalDepthFt = null.

## `sources` (type: `array`):

Only return records from these districts (USGS sites count in the district they lie in). Leave empty for all five. SFWMD is mostly USGS observation wells plus a few permit records.

## `includeSummary` (type: `boolean`):

Write counts, geocode match info, the data snapshot date and disclaimers to the RUN_SUMMARY record in the key-value store. The summary is not a dataset row and is not charged.

## Actor input object example

```json
{
  "queryType": "point",
  "latitude": 28.5383,
  "longitude": -81.3792,
  "radiusMiles": 3,
  "maxResults": 25,
  "wellUse": [
    "domestic",
    "irrigation",
    "public_supply",
    "agricultural",
    "livestock"
  ],
  "onlyWithDepth": true,
  "includeSummary": true
}
```

# Actor output Schema

## `wells` (type: `string`):

No description

## `summary` (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 = {
    "queryType": "point",
    "latitude": 28.5383,
    "longitude": -81.3792,
    "radiusMiles": 3,
    "maxResults": 25,
    "wellUse": [
        "domestic",
        "irrigation",
        "public_supply",
        "agricultural",
        "livestock"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cwayr/florida-well-lookup").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 = {
    "queryType": "point",
    "latitude": 28.5383,
    "longitude": -81.3792,
    "radiusMiles": 3,
    "maxResults": 25,
    "wellUse": [
        "domestic",
        "irrigation",
        "public_supply",
        "agricultural",
        "livestock",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("cwayr/florida-well-lookup").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 '{
  "queryType": "point",
  "latitude": 28.5383,
  "longitude": -81.3792,
  "radiusMiles": 3,
  "maxResults": 25,
  "wellUse": [
    "domestic",
    "irrigation",
    "public_supply",
    "agricultural",
    "livestock"
  ]
}' |
apify call cwayr/florida-well-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cwayr/florida-well-lookup"
        }
    }
}
```

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/eeMB68lM0dxcIspCg/builds/siXXcSlr0o6NVR0Nb/openapi.json
