# FSBO Scraper (`solidcode/fsbo-scraper`) Actor

\[💰 $5.0 / 1K] Extract For Sale By Owner property listings from FSBO.com. Get direct seller contact info (name + phone), price, address, beds/baths, square footage, photos, and full property description. Search by state, city, ZIP code, or paste FSBO.com URLs.

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

## Pricing

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

## FSBO Scraper

Pull For Sale By Owner listings from FSBO.com at scale — direct seller names, prices, addresses, photos, beds/baths/sqft, lat/lng, full descriptions, HOA fees, year built, and seller phone numbers extracted from listing text. Covers all 50 US states plus DC across a live catalog of more than 20,000 active owner-listed properties. Built for real estate investors sourcing off-MLS deals, lead-generation agencies hunting direct-owner contacts, and market analysts tracking FSBO inventory shifts without paying for MLS subscriptions or building their own scraper.

### Why This Scraper?

- **3x cheaper than the leading competitor** — $5.00 per 1,000 results, down to $4.25 on the Gold discount tier, against $15.00 for the nearest FSBO extractor on the Apify Store, with at least as many fields per row.
- **All 50 US states plus DC, 20,000+ live listings** — every state returns results, from Florida and Texas at the deep end (2,000+ and 1,500+ listings each) down to Rhode Island and DC with a couple of dozen apiece.
- **Multi-location runs in one invocation** — mix state names ("Florida"), 2-letter codes ("FL"), city+state ("Austin, TX"), and 5-digit ZIPs ("78641") in a single `searchLocations` array.
- **Owner names, not agent names** — `sellerName` carries the seller's own name on every owner-claimed listing, a field MLS-aggregator scrapers never carry at all. State-wide sweeps of Florida and Texas came back with it filled on more than 60% of rows, and roughly one row in three across all search types. A best-effort `sellerPhone` is pulled from the listing text on top.
- **Latitude and longitude on every row** — stitched into the output so you can map results, geofence by drive-time, or compute distance-to-feature in your own pipeline.
- **Seven property type filters** — Single Family, Condo, Townhouse, Multi-Family, Mobile / Manufactured Home, Land / Lot, or Other (mixed-use).
- **Pre-computed `pricePerSqft` and `daysOnMarket`** — price per square foot on every row that carries a square-footage figure, which is the large majority of them, and days on market wherever FSBO.com publishes a list date, so your downstream queries skip the math.
- **Inline photo arrays** — every photo the seller uploaded, as absolute URLs with sort order and primary-photo flags preserved. Most listings carry a single photo; premium-plan sellers routinely post 30 or more, and the deepest galleries run past 150.
- **Friendly zero-result messaging** — runs that return no matches name the locations and filters tried in the status message, so you can copy-paste an alternative without digging through logs.

### Use Cases

**Investor Sourcing & Off-MLS Deal Flow**

- Surface owner-listed properties below MLS comps for direct-to-seller offers
- Track new FSBO inventory daily in your target ZIPs and counties
- Build a buy-box pipeline filtered by min beds, max price, and property type

**Lead Generation for Real Estate Services**

- Build direct-owner contact lists for listing-agent recruiting (sellers who tried FSBO and may convert)
- Source leads for title, escrow, photography, staging, and home-inspection services
- Target investor-friendly markets with bulk seller name + phone exports

**Market Research & FSBO Inventory Tracking**

- Monitor FSBO market share by state, city, or ZIP over time
- Detect price-per-square-foot trends in owner-listed vs. MLS-listed segments
- Quantify days-on-market for FSBO inventory in growth markets

**Comparable-Property & Valuation Analysis**

- Pull comparable sqft/bed/bath/year-built sets for CMA reports
- Feed FSBO asking prices into iBuyer and AVM training datasets
- Layer FSBO inventory onto MLS heatmaps for full-market coverage

**Real-Estate-Tech Data Ingestion**

- Power FSBO-specific listing aggregators with a fresh feed
- Enrich CRM records with FSBO listing activity by owner name
- Build alerting on new FSBO listings in saved geographies

### Getting Started

#### Simple State Sweep

The simplest possible run — pull the first 100 active FSBO listings in Florida:

```json
{
    "searchLocations": ["Florida"],
    "maxResults": 100
}
```

#### Multi-Location with Filters

Mix a state, a city, and a ZIP in one run, narrowed to single-family homes between $250k and $750k with at least 3 beds:

```json
{
    "searchLocations": ["TX", "Austin, TX", "78641"],
    "propertyType": "single_family",
    "minPrice": 250000,
    "maxPrice": 750000,
    "minBeds": 3,
    "maxResults": 500
}
```

#### Cheap Fast Card-Level Run

Skip the per-listing lookup when you only need card-level data (price, full address, beds/baths/sqft, year built, description, primary photo). Owner names need the full lookup, so leave it on if you are building a contact list:

```json
{
    "searchLocations": ["California"],
    "includePropertyDetails": false,
    "maxResults": 1000
}
```

#### Paste a URL or Sweep Everything

Copy a search results page or a listing page straight out of your browser's address bar, or set `maxResults` to 0 to sweep an entire small-inventory state:

```json
{
    "startUrls": [
        "https://fsbo.com/search/list/miami-fl",
        "https://fsbo.com/search/123-main-st-austin-tx-78701"
    ],
    "searchLocations": ["Vermont"],
    "maxResults": 0
}
```

### Input Reference

#### What to Scrape

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `startUrls` | string\[] | `[]` | Paste FSBO.com URLs copied from your browser: a results page (`https://fsbo.com/search/list/state/fl`, `https://fsbo.com/search/list/miami-fl/land`) or a single listing page. Search filters in the URL (state, city, price, beds, type) are honored as-is. Mix freely with `searchLocations`. |
| `searchLocations` | string\[] | `["Florida"]` | Search by US state name ("Florida"), 2-letter code ("FL"), city + state ("Austin, TX"), or 5-digit ZIP ("78641"). Add multiple entries to sweep several markets in one run. |

#### Filters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `propertyType` | select | `All Types` | All Types, Single Family Home, Condo, Townhouse, Multi-Family, Mobile / Manufactured Home, Land / Lot, or Other (mixed-use, unusual). Applies to search locations only. |
| `minPrice` | integer | null | Only return listings priced at or above this amount in USD. Leave blank for no minimum. |
| `maxPrice` | integer | null | Only return listings priced at or below this amount in USD. Leave blank for no maximum. |
| `minBeds` | integer | null | Only return listings with at least this many bedrooms. Ignored for Land and Other. |
| `minBaths` | integer | null | Only return listings with at least this many bathrooms. Ignored for Land and Other. |

#### Output

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `includePropertyDetails` | boolean | `true` | Open each listing to capture the owner's name, county, neighborhood, school district, lot size, HOA fee, room-level features, and the complete photo array. Disable for faster, cheaper card-level runs — price, address, beds/baths/sqft, year built, description, and the primary photo all still come through. |

#### Limits

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxResults` | integer | `100` | Hard cap on total listings across all URLs and searches. Set to `0` for no cap. The run stops exactly on this number, so you are never charged for more listings than you asked for. Caps below 50 return the first page of results, the smallest page FSBO.com serves. |

### Output

One flat row per listing — no nested children, no duplicate rows. Photos are inlined as an array of absolute URLs.

```json
{
    "listingId": "clxyz0123abc",
    "url": "https://fsbo.com/search/123-main-st-austin-tx-78701",
    "source": "fsbo.com",
    "scrapedAt": "2026-05-16T14:30:00+00:00",
    "title": "Charming 3-Bed Bungalow Near Downtown",
    "headline": "Charming 3-Bed Bungalow Near Downtown",
    "propertyType": "SINGLE_FAMILY",
    "status": "ACTIVE",
    "price": 525000,
    "priceUsd": 525000,
    "pricePerSqft": 315,
    "address": "123 Main St, Austin, TX 78701",
    "street": "123 Main St",
    "city": "Austin",
    "state": "TX",
    "zipCode": "78701",
    "county": "Travis",
    "neighborhood": "East Austin",
    "latitude": 30.2672,
    "longitude": -97.7431,
    "beds": 3,
    "baths": 2,
    "sqft": 1665,
    "lotSize": 6500,
    "yearBuilt": 1972,
    "description": "Updated bungalow with open floor plan. Call (512) 555-1234 to schedule a viewing...",
    "features": ["Open Floor Plan", "Hardwood Floors", "Updated Kitchen"],
    "interiorFeatures": ["Walk-In Closet", "Granite Counters"],
    "utilities": ["City Water", "Natural Gas"],
    "hoaFee": null,
    "primaryPhotoUrl": "https://fsbo.com/api/fsbo/photos?key=abc-001",
    "photoUrls": ["https://fsbo.com/api/fsbo/photos?key=abc-001", "https://fsbo.com/api/fsbo/photos?key=abc-002"],
    "photos": [
        { "url": "https://fsbo.com/api/fsbo/photos?key=abc-001", "sortOrder": 0, "isPrimary": true }
    ],
    "sellerName": "Jane Smith",
    "sellerPhone": "(512) 555-1234",
    "mlsListed": false,
    "isUnclaimed": false,
    "publishedAt": "2026-04-01T00:00:00Z",
    "daysOnMarket": 45
}
```

#### Core Identity

| Field | Type | Description |
|-------|------|-------------|
| `listingId` | string | Unique FSBO.com listing identifier |
| `url` | string | Direct link to the listing on FSBO.com |
| `source` | string | Always `"fsbo.com"` |
| `scrapedAt` | string | ISO timestamp of data extraction |
| `title` | string | Ready-to-use label for every row. The seller's own headline when they wrote one, otherwise built from the property itself, e.g. `2 bed, 2 bath Condo - 1148 Redwood Ln, Gulf Breeze, FL` |
| `headline` | string | Seller's listing headline, exactly as written. Blank on most listings because most sellers never add one |
| `propertyType` | string | SINGLE\_FAMILY, CONDO, TOWNHOUSE, MULTI\_FAMILY, LAND, MOBILE\_HOME, OTHER |
| `status` | string | Listing status (ACTIVE, etc.) |

#### Address & Location

| Field | Type | Description |
|-------|------|-------------|
| `address` | string | Complete one-line address, ready to paste into a mail merge or a mapping tool, e.g. `1148 Redwood Ln, Gulf Breeze, FL 32563` |
| `street` | string | Street line on its own, without the city, state or ZIP |
| `city` | string | City name |
| `state` | string | Two-letter state code |
| `zipCode` | string | 5-digit ZIP code |
| `county` | string | County name |
| `neighborhood` | string | Neighborhood name when present |
| `schoolDistrict` | string | School district name when present |
| `latitude` | number | Decimal latitude |
| `longitude` | number | Decimal longitude |

#### Pricing

| Field | Type | Description |
|-------|------|-------------|
| `price` | number | Asking price in USD |
| `priceUsd` | number | The same number as `price`, kept so existing spreadsheets and workflows keep working. Build new work on `price` |
| `pricePerSqft` | number | Derived: price divided by square footage |
| `hoaFee` | number | Monthly HOA fee in USD when present |
| `hoaName` | string | HOA name when present |

#### Property Details

| Field | Type | Description |
|-------|------|-------------|
| `beds` | number | Number of bedrooms |
| `baths` | number | Number of bathrooms |
| `sqft` | number | Living area in square feet |
| `lotSize` | number | Lot size value |
| `lotUnit` | string | Unit FSBO.com states for `lotSize` — almost always `acres`, occasionally `sqft`. Returned only when `lotSize` has a value |
| `yearBuilt` | number | Year constructed |
| `description` | string | Full seller-written listing description |
| `features` | string\[] | Exterior and overall features |
| `interiorFeatures` | string\[] | Interior features (flooring, fixtures, etc.) |
| `utilities` | string\[] | Utilities and connections |

#### Photos

| Field | Type | Description |
|-------|------|-------------|
| `primaryPhotoUrl` | string | Absolute URL of the primary listing photo |
| `photoUrls` | string\[] | All listing photos as a flat array of absolute URLs |
| `photos` | object\[] | Photos with `{url, sortOrder, isPrimary}`. `sortOrder` follows FSBO.com's own gallery order, lowest first, and is filled whether or not you turn on the per-listing lookup |

#### Seller & Listing Meta

| Field | Type | Description |
|-------|------|-------------|
| `sellerName` | string | Owner's own name. Filled on every owner-claimed listing — roughly one row in three overall, and 60%+ on state-wide sweeps |
| `sellerPhone` | string | Phone number lifted from the listing text when the seller typed one in. Around 1 row in 12 |
| `mlsListed` | boolean | True if also cross-listed on MLS |
| `isUnclaimed` | boolean | True if the listing was MLS-scraped rather than owner-posted |
| `planName` | string | Seller's plan tier on FSBO.com |

#### Dates & Derived

| Field | Type | Description |
|-------|------|-------------|
| `publishedAt` | string | ISO date the seller listed the property. FSBO.com publishes this on owner-claimed listings only |
| `daysOnMarket` | number | Derived from `publishedAt` — days since the listing went live, so it follows the same availability |

### Tips for Best Results

- **City names need a state.** Use `"Austin, TX"`, not just `"Austin"` — bare city names cross-collide across states and are rejected. State name alone (`"Florida"`) or 2-letter code (`"FL"`) is fine for state-wide sweeps.
- **Smaller-inventory states are catalog-exhaustible.** Vermont, Wyoming, and North Dakota each sit around 100 active listings, and Rhode Island and DC under 25. Set `maxResults: 0` to sweep one of them completely — the run stops cleanly when the catalog ends.
- **Toggle `includePropertyDetails` for speed vs. depth.** Off gives you fast card-level rows (price, address, beds/baths/sqft, year built, description, primary photo). On adds owner names, county, school district, lot size, HOA fees, room-level features, and the complete photo array.
- **Claimed listings are the gold standard for lead generation.** Every row with `isUnclaimed: false` carries the seller's real name in `sellerName`, and every row with `isUnclaimed: true` does not. It's a clean split with no partial cases, so filtering on that single flag gives you a contact list with no empty rows in it. Broad state sweeps return the most names.
- **`sellerPhone` is best-effort from the listing text.** It only appears when the seller typed a 10-digit number into their own write-up, which is about 1 row in 12. Treat `sellerName` as the reliable owner-identity field and the phone as a bonus.
- **ZIP codes are for pinning a neighborhood, not for volume.** FSBO inventory is thin per ZIP: even the densest ZIPs carry only around 20 listings and plenty carry none at all. Use a ZIP when you want one exact pocket of a metro, and `"Austin, TX"` or `"TX"` when you want a workable sample size.
- **Mix `startUrls` and `searchLocations` in one run.** Paste a few specific listing URLs you already know about alongside broader location sweeps, and they all flow into the same dataset.

### Pricing

**From $4.25 per 1,000 results** — $5.00 undiscounted, still roughly 3x cheaper than the leading FSBO scraper on the Apify Store at $15.00 per 1,000. No compute or time-based charges: you pay per result, plus a small fixed start fee each time a run begins. Bronze, Silver, and Gold subscribers pay progressively less, and the table below shows the total cost at each discount tier.

| Results | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.50 | $0.475 | $0.45 | $0.425 |
| 1,000 | $5.00 | $4.75 | $4.50 | $4.25 |
| 10,000 | $50.00 | $47.50 | $45.00 | $42.50 |
| 100,000 | $500.00 | $475.00 | $450.00 | $425.00 |

A "result" is any property row in the output dataset. The per-run start fee and standard platform fees (storage, data transfer) 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

FSBO.com is a public marketplace where sellers list their properties for buyers to discover. This actor is designed for legitimate real estate market analysis, comparable-property research, investor sourcing, and lead generation for real estate services. Users are responsible for complying with applicable laws and FSBO.com's terms of service, including any limits on automated access and downstream use of contact information. Do not use extracted data for spam, harassment, or any illegal purpose. Be especially mindful of telephone consumer protection rules (TCPA) and CAN-SPAM when contacting sellers from this dataset.

# Actor input Schema

## `startUrls` (type: `array`):

Paste one or more FSBO.com search or listing URLs directly. Any filters in the URL (state, city, price, beds, property type) are honored as-is. Mix URLs and search locations freely — both are scraped in one run.

## `searchLocations` (type: `array`):

Search by US state, city + state, or ZIP code. Accepted formats: 'Florida', 'Austin, TX', '78701'. Add multiple entries to scrape several markets in one run.

## `propertyType` (type: `string`):

Filter results by property type. Only applies to Search Locations — ignored when using URLs (URLs carry their own type filter).

## `minPrice` (type: `integer`):

Only return listings priced at or above this amount. Leave blank for no minimum.

## `maxPrice` (type: `integer`):

Only return listings priced at or below this amount. Leave blank for no maximum.

## `minBeds` (type: `integer`):

Only return listings with at least this many bedrooms. Listings that publish no bedroom count at all (typically land, mobile homes and 'other') are left out when you set this, so every result really has the number you asked for.

## `minBaths` (type: `integer`):

Only return listings with at least this many bathrooms. Listings that publish no bathroom count at all (typically land, mobile homes and 'other') are left out when you set this, so every result really has the number you asked for.

## `includePropertyDetails` (type: `boolean`):

Open each listing's own page to capture the owner's name, county, neighborhood, school district, lot size, HOA fee, room-level features, and the complete photo array. Disable for faster, cheaper card-level runs — price, address, beds/baths/sqft, year built, description and the primary photo all still come through, but owner names are only published on a listing's own page, so they come back empty when this is off.

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

Hard cap on total listings across all URLs and searches. Default 100 — increase for bigger runs, or set to 0 for no cap (an internal upper limit of 100,000 still applies to prevent infinite pagination). The run stops exactly on this number, so you are never charged for more listings than you asked for. Caps below 50 return the first page of results (up to 50 listings), which is the smallest page FSBO.com serves.

## Actor input object example

```json
{
  "startUrls": [],
  "searchLocations": [
    "Florida"
  ],
  "propertyType": "all",
  "includePropertyDetails": true,
  "maxResults": 100
}
```

# Actor output Schema

## `overview` (type: `string`):

Table of scraped FSBO listings — photo, price, street, city, state and ZIP, beds/baths/sqft, year built, property type, and the listing URL. Every column here is filled on virtually every row, with or without detail enrichment. The full one-line address is in the `address` field of the raw data and in the Seller contacts view.

## `sellers` (type: `string`):

Direct-owner contact view — seller name and phone alongside the property's full one-line address. Seller names come from owner-claimed listings (rows where isUnclaimed is false) and require detail enrichment, so sort or filter on that flag to get a clean contact list.

# 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 = {
    "startUrls": [],
    "searchLocations": [
        "Florida"
    ],
    "propertyType": "all",
    "includePropertyDetails": true,
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/fsbo-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 = {
    "startUrls": [],
    "searchLocations": ["Florida"],
    "propertyType": "all",
    "includePropertyDetails": True,
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/fsbo-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 '{
  "startUrls": [],
  "searchLocations": [
    "Florida"
  ],
  "propertyType": "all",
  "includePropertyDetails": true,
  "maxResults": 100
}' |
apify call solidcode/fsbo-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,solidcode/fsbo-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/G36hzSdOjE4myZ9yh/builds/PQUoBa51strZeohyH/openapi.json
