# LandWatch Scraper — Land, Farm & Ranch Listings (`solidcode/landwatch-com-scraper`) Actor

\[💰 $1.0 / 1K] Extract land, farm, ranch and hunting property listings from LandWatch. Price, price per acre, acreage, GPS coordinates, availability, photos, documents and broker contacts in one clean dataset — paste any LandWatch search URL and every filter in it carries through.

- **URL**: https://apify.com/solidcode/landwatch-com-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 properties

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

## LandWatch Scraper — Land, Farm & Ranch Listings

Pull rural land, farm, ranch, and hunting-property listings from LandWatch at scale — asking price, price per acre, acreage, GPS coordinates, availability, photos, and the agent behind every parcel, in one clean dataset. Built for land brokers, rural real-estate investors, and timberland and agricultural analysts who need current listing data without working through county search pages by hand or maintaining a scraper of their own.

LandWatch carries rural inventory right across the US — more than 75,000 listings in Texas alone. Set your filters on the site, paste the address bar URL, and get structured rows back.

### Why This Scraper?

- **GPS coordinates on 100% of listings** — measured across 250 listings spanning five states (Texas, Florida, Montana, Georgia, Ohio) and five property categories: latitude and longitude on every single row, ready for mapping, radius search, and acreage overlays without a geocoding pass.
- **69 fields per property — 48 straight from search results, 21 more with full details on** — price per acre, parcel and MLS identifiers, bed and bath counts, county, ZIP, and the exact timestamp the listing last changed.
- **Four availability values, not just "for sale"** — every row reads `Available`, `Under Contract`, `Off Market`, or `Sold`, each one verified against the site's own availability filter. Sold rows carry the closed sale price and the date it closed, which is the comparables data rural appraisal and CMA work runs on.
- **Withheld and auction prices reported as missing, never as $1** — LandWatch stores a placeholder figure on listings whose seller hides the price and on auction lots, and 15 of 306 sampled rows carry one. Those rows come back with no asking price and no price per acre at all, so your averages, sorts, and price filters stay correct.
- **Price-change history on 44% of listings** — the dollar amount, the percentage, and the date of the most recent change; 92 of the 109 changes in the sample were reductions. Reprice signals without diffing weekly runs.
- **An average of 48 photos per listing at full width** — and a main photo URL on 100% of rows even where the site withholds the rest of the gallery. Turn on full details and every photo arrives with the caption the seller wrote for it.
- **Agent, brokerage, and profile link on every listing** — agent name on 100% and brokerage on 98% of sampled rows, plus a link to the agent's LandWatch profile. The agent's direct phone number is passed straight through whenever the brokerage publishes it on the listing.
- **Seller paperwork surfaced, not just described** — aerial maps, plats, and survey PDFs come back linked and named on 36% of full-detail rows, alongside an interactive parcel-map link on 56% and the seller's own four highlight bullets.
- **One row per property, however many searches you run** — a parcel matching two of your search URLs is collected once and billed once, so a twelve-county sweep never pays for its overlaps.

### Use Cases

**Land Brokerage & Comparables**

- Build price-per-acre comparables by county, state, and property category
- Pull closed sale prices and dates from `Sold` listings for appraisal and CMA work
- Benchmark a new listing against active inventory before agreeing an asking price
- Track how long inventory sits by comparing `listedDate` against `lastUpdated`

**Investment & Acquisition**

- Screen for under-priced acreage by comparing price per acre against county medians
- Watch a target county for new listings, reductions, and status changes
- Separate parcels with a residence from raw land using bed, bath, and square-footage fields
- Shortlist auction lots ahead of the sale date from the auction start, end, and timezone fields

**Timber, Agriculture & Conservation**

- Map candidate tracts by GPS coordinates and acreage for overlay against soil or timber data
- Filter for irrigated ground, riverfront, and lakefront parcels
- Pull aerial maps, plats, and survey documents attached to a listing in one pass
- Assemble regional acreage inventories from the named region on each property

**Lead Generation**

- Build county-level agent and brokerage lists from live listing inventory
- Route new listings to the right desk using county, state, and property category
- Identify the brokerages carrying the most inventory in a market before pitching

**Data Enrichment & Integration**

- Feed a CRM or valuation model with structured rows on a schedule
- Join to county assessor data using the parcel identifier and location fields
- Enrich an existing parcel list with photos, description text, and current asking price

### Getting Started

#### Simplest run

```json
{
  "maxItems": 100
}
```

#### Paste a filtered search URL from the site

Set your filters on the site, then copy the address bar URL — every filter in it is
carried through.

```json
{
  "searchUrls": [
    "https://www.landwatch.com/texas-land-for-sale"
  ],
  "maxItems": 500
}
```

#### Everything, with full details

```json
{
  "searchUrls": [
    "https://www.landwatch.com/texas-land-for-sale"
  ],
  "maxItems": 500,
  "enrichDetails": true
}
```

### Input Reference

#### What to Scrape

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchUrls` | array | — | Landwatch.com search result URLs. Set your filters on Landwatch.com, then paste the address bar URL here. Overrides the individual filters below when provided. |
| `maxItems` | integer | `100` | Maximum properties per search URL (0 = collect everything each search returns). Landwatch.com pages through at most 500 properties per search, so use several narrower searches to collect more. |

#### Options

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `enrichDetails` | boolean | `false` | Add 21 extra fields per property. Adds one request per property and is billed at the higher rate. |
| `concurrency` | integer | `8` | How many requests to run in parallel. Lower this if you see failures. |
| `proxyConfiguration` | object | Apify Proxy | Proxy settings for the run. |

### Output

Every property is one dataset row. Enabling `enrichDetails` adds 21 further fields to the same row — there is no second record type to join.

This example is a real listing with full details turned on. The agent's name and phone number have been replaced with placeholders, and the photo, caption, and document lists are shown shortened — your dataset carries the actual published values and every entry.

```json
{
  "id": "23734860",
  "propertyId": "423139356",
  "url": "https://www.landwatch.com/madison-county-florida-farms-and-ranches-for-sale/pid/423139356",
  "title": "96-Acre North FL Farmstead",
  "propertyTypes": ["Farms and Ranches", "Recreational Property", "Horse Property", "House"],
  "propertyTypeLabel": "Farms and Ranches, Recreational Property, Horse Property, House",
  "status": "Under Contract",
  "acres": 96,
  "acresDisplay": "96 acres",
  "hasHouse": true,
  "beds": 3,
  "baths": 2,
  "homeSqft": 1450,
  "price": 700000,
  "priceDisplay": "$700,000",
  "pricePerAcre": 7291.67,
  "priceChangeAmount": -100000,
  "priceChangePercentage": -0.125,
  "priceChangeDate": "2026-06-15T13:05:20.203",
  "address": "4087 NW Honey Lake Rd",
  "city": "Greenville",
  "county": "Madison County",
  "state": "Florida",
  "stateAbbreviation": "FL",
  "zip": "32331",
  "latitude": 30.519619,
  "longitude": -83.659009,
  "brokerName": "B. Jones",
  "brokerCompany": "Mossy Oak Properties Southern Land and Homes, LLC",
  "brokerPhone": "(850) 555-0119",
  "brokerProfileUrl": "https://www.landwatch.com/profile/b-jones/318758",
  "imageCount": 48,
  "photos": ["https://assets.landwatch.com/resizedimages/1024/0/h/80/1-6343229990"],
  "thumbnail": "https://assets.landwatch.com/resizedimages/1024/0/h/80/1-6343229990",
  "hasVideo": false,
  "hasVirtualTour": false,
  "hasCustomMap": true,
  "listingLevelTitle": "Signature Partner",
  "listedDate": "2025-06-03T10:20:55.783",
  "firstSeen": "2025-06-03T10:20:55.783",
  "lastUpdated": "2026-07-15T09:51:19.9",
  "description": "4087 NW Honey Lake Rd\n\nDiscover the beauty and freedom of true country living on this expansive 96-acre farmstead, offering the perfect blend of open fields, mature hardwoods, and North Florida charm...",
  "highlight1": "96± acres with open pasture, mature hardwoods, and abundant deer and turkey habitat in North Florida.",
  "highlight2": "Cozy 1,450 sq ft farmhouse plus detached 1BR/1BA cottage ideal for guests, rental income, or family.",
  "highlight3": "Paved road frontage offers easy access while maintaining the peace and privacy of true country living.",
  "highlight4": "Conveniently located 45 miles from Tallahassee and only 18 miles from Madison, FL.",
  "regionName": "North Central Florida",
  "photoCaptions": ["Main Photo", "Photo 0001"],
  "mapUrl": "https://id.land/maps/5ab8c54339b5bf3dc292579d0a5fea7c/embed/",
  "parcelId": "0|361|061N071794000000|1",
  "documentNames": ["Aerial Map", "All Maps", "Brochure", "Locator Map", "Topo Map"],
  "documentUrls": ["https://files.realstack.com/uploads/user/1200/listing-aerial-map/NHHn4GNFtxth6Cp2s6AZPHBuBTMhdubzpXvKs76C/00iVmcCjF7wgB5x6.pdf"],
  "directions": "Hwy 90 W from Greenville, right on Honey lake Rd, proerty on left.",
  "isResidence": true,
  "isIrrigated": false
}
```

#### Core Fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Listing ID |
| `propertyId` | string | Property ID |
| `url` | string | Listing URL |
| `title` | string | Title |
| `propertyTypes` | array | Property types |
| `propertyTypeLabel` | string | Property types (as shown) |
| `status` | string | Availability |
| `acres` | number | Acres |
| `acresDisplay` | string | Acres (as shown) |
| `hasHouse` | boolean | Has a house |
| `beds` | number | Bedrooms |
| `baths` | number | Bathrooms |
| `halfBaths` | number | Half baths |
| `homeSqft` | number | Home sq ft |

#### Price & Value

| Field | Type | Description |
|-------|------|-------------|
| `price` | number | Price (USD) |
| `priceDisplay` | string | Price (as shown) |
| `pricePerAcre` | number | $ / acre |
| `priceChangeAmount` | number | Price change (USD) |
| `priceChangePercentage` | number | Price change (%) |
| `priceChangeDate` | string | Price changed on |
| `soldPrice` | number | Sold price (USD) |
| `soldDate` | string | Sold on |

#### Location

| Field | Type | Description |
|-------|------|-------------|
| `address` | string | Address |
| `city` | string | City |
| `county` | string | County |
| `state` | string | State |
| `stateAbbreviation` | string | State (abbr) |
| `zip` | string | ZIP |
| `latitude` | number | Latitude |
| `longitude` | number | Longitude |
| `lake` | string | Lake |

#### Contacts

| Field | Type | Description |
|-------|------|-------------|
| `brokerName` | string | Agent |
| `brokerCompany` | string | Brokerage |
| `brokerPhone` | string | Phone |
| `brokerProfileUrl` | string | Agent profile |

#### Media

| Field | Type | Description |
|-------|------|-------------|
| `imageCount` | number | Photo count |
| `photos` | array | Photo URLs |
| `thumbnail` | string | Main photo |
| `hasVideo` | boolean | Has video |
| `hasVirtualTour` | boolean | Has virtual tour |
| `hasCustomMap` | boolean | Has a custom map |

#### Details & Timestamps

| Field | Type | Description |
|-------|------|-------------|
| `listingLevelTitle` | string | Listing tier |
| `listedDate` | string | Listed on |
| `firstSeen` | string | First seen |
| `lastUpdated` | string | Last updated |
| `auctionStartDate` | string | Auction starts |
| `auctionEndDate` | string | Auction ends |
| `auctionTimezone` | string | Auction timezone |

#### With `enrichDetails` enabled

| Field | Type | Description |
|-------|------|-------------|
| `description` | string | Description |
| `highlight1` | string | Highlight 1 |
| `highlight2` | string | Highlight 2 |
| `highlight3` | string | Highlight 3 |
| `highlight4` | string | Highlight 4 |
| `regionName` | string | Region |
| `photoCaptions` | array | Photo captions |
| `mapUrl` | string | Interactive map |
| `auctionTitle` | string | Auction name |
| `auctionInfoUrl` | string | Auction details |
| `auctionIsOnlineOnly` | boolean | Online-only auction |
| `parcelId` | string | Parcel ID |
| `mlsId` | string | MLS ID |
| `mlsName` | string | MLS |
| `disclaimer` | string | MLS disclaimer |
| `externalUrl` | string | Source listing link |
| `documentUrls` | array | Document URLs |
| `documentNames` | array | Document names |
| `directions` | string | Directions |
| `isResidence` | boolean | Has a residence |
| `isIrrigated` | boolean | Irrigated |

### Tips for Best Results

- **Plan around the 500-per-search ceiling** — LandWatch pages through at most 500 properties for any one search, however many match. A statewide search reporting 75,000 results still returns 500. To cover a whole state, split it by county, price band, or property category and paste every URL into `searchUrls` — the run collects each property once across all of them, so the splits can safely overlap.
- **Filter on the site first, then copy the URL** — county, acreage range, price band, property category, and availability are all encoded in the address bar and carried through exactly as you set them, so a heavily filtered search needs no extra configuration here.
- **County-level searches give the cleanest comparables** — county is the unit rural appraisal actually works in, and a county search almost always sits under the 500 ceiling, so you get complete coverage in a single run.
- **Add `/sold` to a search URL for closed-sale data** — sold listings carry `soldPrice` and `soldDate`, and closed prices are the gold standard for underwriting and CMA work in a market where asking prices are frequently withheld.
- **Treat a missing `price` as information, not breakage** — around one listing in twenty-five is an auction lot or a "contact for price" seller. Those rows still carry full acreage, location, photos, and agent data, and they skew toward the higher-value tracts. Filter on `price != null` only when you specifically need a figure.
- **Turn on `enrichDetails` when you need the write-up or the paperwork** — the full description, the seller's highlight bullets, photo captions, parcel ID, region, and any attached plats or survey PDFs only arrive on enriched rows. Leave it off for a fast price-and-location sweep at the lower rate.
- **Sort or diff on `lastUpdated` to monitor a market** — schedule a run and compare on that field to surface new, re-priced, and newly-contracted inventory instead of reprocessing everything you already have.

### Pricing

**From $1.00 per 1,000 results** (search only) or **from $2.50 per 1,000 results** (with full details).

| Results | Search Only | With Full Details |
|---------|-------------|-------------------|
| 100 | $0.10 | $0.25 |
| 1,000 | $1.00 | $2.50 |
| 10,000 | $10.00 | $25.00 |
| 100,000 | $100.00 | $250.00 |

Those are the rates on Gold and above. Higher-volume plans pay less per result:

| Your Apify plan | Search Only | With Full Details |
|-----------------|-------------|-------------------|
| No discount | $1.20 | $3.00 |
| Bronze | $1.15 | $2.85 |
| Silver | $1.05 | $2.65 |
| **Gold and above** | **$1.00** | **$2.50** |

Per 1,000 results.

A "result" is any property row in the output dataset. When you run several searches at once, a property matching more than one of them is de-duplicated before it reaches the dataset, so you are never charged twice for the same property. The full-details rate applies only to rows that actually came back enriched — if a property's detail record is unavailable, the row is still delivered and charged at the search-only rate. Platform fees (compute, storage) are additional and depend on your Apify plan.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger custom APIs on run completion
- **Apify API** — Full programmatic access

### Legal & Ethical Use

**This is an unofficial scraper. It is not affiliated with, endorsed by, or connected to Landwatch.com or its operators in any way.** All trademarks belong to their respective owners.

This actor is intended for legitimate market research and analytics. You are responsible for complying with applicable laws and with Landwatch.com's Terms of Service.

Results may include personal data such as contact details. Treat them accordingly: do
not use them for spam, harassment, or any unlawful purpose, and follow applicable
privacy rules when storing or processing them.

# Actor input Schema

## `searchUrls` (type: `array`):

Landwatch.com search result URLs. Set your filters on Landwatch.com, then paste the address bar URL here. Overrides the individual filters below when provided.

## `maxItems` (type: `integer`):

Maximum properties per search URL (0 = collect everything each search returns). Landwatch.com pages through at most 500 properties per search, so use several narrower searches to collect more.

## `enrichDetails` (type: `boolean`):

Add 21 extra fields per property. Adds one request per property and is billed at the higher rate.

## `concurrency` (type: `integer`):

How many requests to run in parallel. Lower this if you see failures.

## `proxyConfiguration` (type: `object`):

Proxy settings for the run.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.landwatch.com/texas-land-for-sale"
  ],
  "maxItems": 100,
  "enrichDetails": false,
  "concurrency": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `core` (type: `string`):

Core Fields for each property.

## `financial` (type: `string`):

Price & Value for each property.

## `location` (type: `string`):

Location for each property.

## `contact` (type: `string`):

Contacts for each property.

## `media` (type: `string`):

Media for each property.

## `meta` (type: `string`):

Details & Timestamps for each property.

# 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 = {
    "searchUrls": [
        "https://www.landwatch.com/texas-land-for-sale"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/landwatch-com-scraper").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 = { "searchUrls": ["https://www.landwatch.com/texas-land-for-sale"] }

# Run the Actor and wait for it to finish
run = client.actor("solidcode/landwatch-com-scraper").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 '{
  "searchUrls": [
    "https://www.landwatch.com/texas-land-for-sale"
  ]
}' |
apify call solidcode/landwatch-com-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=solidcode/landwatch-com-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/apPOXhMmHHBul7473/builds/76zFwTpwmUUY1JJU2/openapi.json
