# Off-Market Leads Scraper (`buff_pineapple/offmarket-leads-scraper`) Actor

Collects off-market, time-sensitive real-estate leads (sheriff sales, trustee sales, tax-delinquent auctions, probate notices) from official state/county sources across all 50 US states. Per-field provenance on every lead.

- **URL**: https://apify.com/buff\_pineapple/offmarket-leads-scraper.md
- **Developed by:** [yossef Nagy](https://apify.com/buff_pineapple) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $70.00 / 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.

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

## Off-Market Leads Scraper

Off-market, time-sensitive real-estate leads collected directly from official
public records across all 50 US states - sheriff and trustee sale lists,
tax-delinquent auctions, probate notices and legal-notice boards. Every field
of every lead ships with its own provenance: the exact source URL, how it was
collected, and a confidence score.

### Who this is for

- **Wholesalers and investors** who need motivated sellers whose properties are
  NOT listed on the MLS - before the crowd finds them.
- **Agents and brokers** building farm-area pipelines around distress events
  (foreclosure auctions, tax sales, probate).
- **Analysts and data teams** who need auditable public-record data where every
  value can be traced back to its origin.

A single closed wholesale deal routinely returns thousands of dollars. This
actor automates the discovery work: it reads county sheriff dockets, trustee
notices, tax-sale rosters and court/legal notice boards week after week, and
hands you structured leads with hard deadlines attached.

### How it works

1. **Collect** - the actor reads official state/county sources for every state
   you select (all 50 by default), through Apify residential proxies with
   sticky sessions.
2. **Verify off-market status** - every candidate passes an always-on
   OFF-MARKET GATE: the actor searches for active listings of that property and
   kills anything MLS-listed. Only genuinely off-market properties survive.
   Killed candidates never reach your dataset.
3. **Enrich** - when available, owner phone numbers are skip-traced from public
   people-search snippets and attached with their source and confidence.
4. **Score and filter** - each field gets a confidence score with the rule that
   produced it, and each lead keeps its deadline and the reason it is
   time-sensitive (auction date, hearing date, redemption window).
5. **Deliver** - clean, schema-validated JSON items land in the run dataset,
   ready for CSV export, webhooks, API or AI workflows.

### What you get

- **Hard deadlines, not vague signals** - auction/hearing/tax-sale dates and the
  reason each lead is urgent, so you can prioritize outreach this week.
- **Proof on every field** - value, source URL and collection method for owner
  name, addresses, phones, emails, property details and distress signals.
- **Honest confidence scores** - each field carries the anchor rule that fired
  plus corroboration info, including a wrong-person risk flag where relevant.
- **Self-healing collection** - three extraction tiers (stealth HTTP,
  adaptive selectors that relocate when a site changes, stealth browser
  fallback) keep working when county portals redesign.
- **Postponement tracking on repeat runs** - distressed sales get adjourned for
  weeks (11-week chains were observed in ground-truth research). Run weekly on
  a schedule and each run diffs against the last: new, postponed and removed
  leads are reported in run stats.

### Input

| Field | Default | Description |
| --- | --- | --- |
| States | all 50 | US state codes to collect from. |
| Time-sensitive leads only | true | Keep only leads with a hard deadline. Turn off to also receive deadline-free distress signals (tax-delinquent, code enforcement, absentee owner). |
| Max leads per state | 5 | Cap per state. 0 = unlimited (up to 500/state). |
| Proxy configuration | Apify residential, US | Required. Several sources hard-block datacenter IPs - leave residential on. |
| Search engines | DuckDuckGo, Google, Bing | Failover order for the internal search module (off-market gate + phone enrichment). |
| Stealth-browser fallback | true | Allow escalation to a fingerprint-spoofed headless browser when a source soft-blocks. Recommended - several sources are browser-only. |
| Max search queries per lead | 6 | Upper bound on search-module queries spent per lead (gate + phone enrichment combined). |

### Output

Each dataset item is one verified lead:

```json
{
  "lead_id": "WI-0001",
  "state": "WI",
  "lead_type": "pre_foreclosure",
  "deadline": "2026-09-15",
  "time_sensitivity_reason": "Sheriff sale scheduled 2026-09-15",
  "off_market": "pass",
  "off_market_evidence": "No active listing found for this address",
  "fields": {
    "owner_name": {
      "value": "SAMPLE, JANE Q",
      "source_url": "https://www.examplecounty.wi.gov/sheriff/sale-list",
      "collection_method": "direct"
    },
    "property_address": {
      "value": "1360 SAMPLE BRIDGE RD, MADISON, WI 53704",
      "source_url": "https://www.examplecounty.wi.gov/sheriff/sale-list",
      "collection_method": "direct"
    },
    "distress_signal": {
      "value": "Judgment of foreclosure - sale listed on county docket",
      "source_url": "https://www.examplecounty.wi.gov/sheriff/sale-list",
      "collection_method": "direct"
    }
  },
  "confidence": {
    "owner_name": { "confidence": 0.9, "anchor": "official_list_full_name" }
  },
  "source_id": "wi_dane_sheriff",
  "parse_part_used": "direct",
  "extraction_path": "primary",
  "collected_at": "2026-08-21"
}
```

Lead types include pre\_foreclosure, tax\_delinquent, probate, absentee\_owner,
code\_enforcement and other. The `off_market` field records the gate verdict:
`pass` means no active listing was found; `unchecked` means the gate could not
complete and the lead was kept conservatively (counted transparently in run
stats). Properties confirmed MLS-active never appear in the dataset.

### Usage tips

- **Run weekly on a schedule.** Distress sources re-post the same property with
  moved deadlines; weekly runs catch postponements and removed properties via
  automatic diffing.
- **Start small, then widen.** Try a few states with the default cap, inspect
  the data quality, then raise Max leads per state or select more states.
- **Keep the browser fallback on** unless you have a specific reason - several
  official portals require JavaScript rendering.

### Support

Questions, feature requests or a source you would like added? Open an issue on
the actor page or contact the developer via Apify.

# Actor input Schema

## `states` (type: `array`):

US state codes to collect leads from. Default: all 50 states.

## `timeSensitiveOnly` (type: `boolean`):

When on, keep only leads with a hard deadline (auction date, tax-sale date, probate hearing date). When off, deadline-free distress signals (tax-delinquent, code enforcement, absentee owner) are kept too.

## `maxLeadsPerState` (type: `integer`):

Maximum number of leads to collect per state. 0 = unlimited.

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

REQUIRED. All source fetching and search-module queries route through this proxy configuration. Preset to Apify residential proxies, US only, with sticky sessions for maximum reliability. Do not switch off residential - datacenter IPs are hard-blocked by several sources.

## `searchEngines` (type: `array`):

Search engines the internal search module may use, in failover order. Powers the off-market gate, phone snippet enrichment and source-cache fallback.

## `includeBrowserFallback` (type: `boolean`):

Allow the fetch router to escalate from stealth HTTP to a fingerprint-spoofed headless browser when a source soft-blocks (403/429/503, challenge pages, JS shells). Strongly recommended - several sources are browser-only.

## `maxSearchQueriesPerLead` (type: `integer`):

Upper bound on search-module queries spent on a single lead (off-market gate + phone enrichment combined).

## Actor input object example

```json
{
  "states": [
    "AL",
    "AK",
    "AZ",
    "AR",
    "CA",
    "CO",
    "CT",
    "DE",
    "FL",
    "GA",
    "HI",
    "ID",
    "IL",
    "IN",
    "IA",
    "KS",
    "KY",
    "LA",
    "ME",
    "MD",
    "MA",
    "MI",
    "MN",
    "MS",
    "MO",
    "MT",
    "NE",
    "NV",
    "NH",
    "NJ",
    "NM",
    "NY",
    "NC",
    "ND",
    "OH",
    "OK",
    "OR",
    "PA",
    "RI",
    "SC",
    "SD",
    "TN",
    "TX",
    "UT",
    "VT",
    "VA",
    "WA",
    "WV",
    "WI",
    "WY"
  ],
  "timeSensitiveOnly": true,
  "maxLeadsPerState": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "countryCode": "US"
  },
  "searchEngines": [
    "duckduckgo",
    "google",
    "bing"
  ],
  "includeBrowserFallback": true,
  "maxSearchQueriesPerLead": 6
}
```

# Actor output Schema

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

JSON array of lead items pushed to 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 = {};

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

# Run the Actor and wait for it to finish
run = client.actor("buff_pineapple/offmarket-leads-scraper").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 buff_pineapple/offmarket-leads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,buff_pineapple/offmarket-leads-scraper"
        }
    }
}

```

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/1x5vqTQqHagB2AdTe/builds/bL61JFKh23sQhydxB/openapi.json
