# FSBO.com Property Listings (`bovi/fsbo-scraper`) Actor

Scrape public FSBO.com listings by state or city. Get addresses, prices, rooms, and property details. Run by location; no login or buyer API key. Free-plan pricing: $0.0011 per returned listing plus $0.00005 per GB of run memory; minimum one event.

- **URL**: https://apify.com/bovi/fsbo-scraper.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** Real estate, Lead generation
- **Features:** Limited permissions
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.10 / 1,000 fsbo.com property listings

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?

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

## FSBO.com Property Listings Scraper

Scrape public For Sale By Owner listings from fsbo.com by U.S. state or city, one dataset item per listing: address, asking price, rooms, square footage, photos and more. No source-site login or buyer API key. Priced per returned listing (see Pricing).

- Filter listing cards by location, price, bedrooms, or bathrooms.
- Build real-estate research datasets from public listing pages.
- Listings keep their card fields even when the detail page cannot be read.
- Export the dataset as JSON or CSV.

### What you get

The Actor loads a public fsbo.com state or city page, parses listing cards, and enriches each listing with its public structured data when available. Apart from `url`, `address`, `source` and `scraped_at`, a field is omitted when unavailable or empty.

| Field | Type | Meaning |
|---|---|---|
| `url` | string | Listing URL; always present. |
| `listing_id` | string | Listing identifier from structured detail data. |
| `title` | string | Listing title. |
| `address` | string | Street address and locality; present when the card is parsed. |
| `city` | string | City. |
| `state` | string | State code. |
| `postal_code` | string | Postal code when exposed on the page. |
| `price` | integer | Asking price. |
| `price_currency` | string | Price currency. |
| `bedrooms` | number | Bedroom count. |
| `bathrooms` | number | Bathroom count. |
| `square_feet` | integer | Square footage. |
| `year_built` | integer | Year built. |
| `property_type` | string | Property type. |
| `description` | string | Listing description. |
| `date_posted` | string | Posting date. |
| `latitude` | number | Latitude. |
| `longitude` | number | Longitude. |
| `photos` | array of strings | fsbo.com photo URLs exposed by the page. |
| `source` | string | Always `fsbo.com`. |
| `scraped_at` | ISO 8601 string | UTC timestamp of the scrape; always set. |

### Sample output

One record with a shortened `description`; fields absent from that record are not shown.

```json
{
  "url": "https://fsbo.com/search/801-w-ward-ave-ridgecrest-ca-93555-1789585295113",
  "address": "801 W Ward Ave, Ridgecrest, CA, 93555",
  "source": "fsbo.com",
  "city": "Ridgecrest",
  "state": "CA",
  "postal_code": "93555",
  "price": 99900,
  "bedrooms": 3,
  "bathrooms": 2,
  "photos": ["https://fsbo.com/api/fsbo/photos?key=listings%2Fcmu4gvnek0vfrs601treskmaa%2Fscraped%2Fthumbs%2Fmu4gwavy5xns1bmd.webp", "https://fsbo.com/api/fsbo/photos?key=listings%2Fcmu4gvnek0vfrs601treskmaa%2Fscraped%2Fmu4gwavy5xns1bmd.jpg"],
  "title": "$99,900 - 3 BD, 2 BA - 801 W Ward Ave, Ridgecrest, CA",
  "listing_id": "cmu4gvnek0vfrs601treskmaa",
  "description": "This move-in-ready manufactured home is located in Santiago Ridgecrest Estates, a welcoming All Age Community in Ridgecrest, California. ...",
  "price_currency": "USD",
  "year_built": 2019,
  "property_type": "Landform",
  "latitude": 35.6433928,
  "longitude": -117.6852841,
  "scraped_at": "2026-10-17T02:15:41.491304+00:00"}
```

### Pricing

You pay only for the events below. This Actor does not use the Pay per event + usage option, so compute, proxy traffic and storage are not billed to you separately.

On the Free plan, `apify-default-dataset-item` costs $0.0011 per returned listing, and `apify-actor-start` costs $0.00005, charged once per GB of run memory with a minimum of one event.

Free plan: 1,000 results cost 1,000 × $0.0011 = $1.10, and 10,000 results cost 10,000 × $0.0011 = $11.00.

The Free plan's monthly $5 credit covers 4,545 results.

### How to use

1. **Enter** a two-letter state code such as `CA`, or a city and state such as `Los Angeles, CA`.
2. **Add** `maxResults` and any optional price or room filters.
3. **Configure** optional Apify proxy settings.
4. **Run** the Actor to load the location page and parse its listing cards.
5. **Review** the dataset, or repeat the run through Apify Schedules.

```json
{
  "searchLocation": "Los Angeles, CA",
  "maxResults": 50,
  "minPrice": 500000,
  "maxPrice": 1500000,
  "minBedrooms": 3,
  "minBathrooms": 2
}
```

### Input parameters

| Parameter | What it does | Default |
|---|---|---|
| `searchLocation` | Two-letter state code or city and state. Required by the input schema; if the key is absent, the run uses `CA`. | Required |
| `maxResults` | Number of listings to return, integer 1 to 60. | `50` |
| `minPrice` | Keeps listings at or above this asking price. | Not set |
| `maxPrice` | Keeps listings at or below this asking price. | Not set |
| `minBedrooms` | Keeps listings with at least this many bedrooms. | Not set |
| `minBathrooms` | Keeps listings with at least this many bathrooms. | Not set |
| `proxyConfiguration` | Apify proxy settings for requests to fsbo.com. If you omit the key or disable the proxy, requests go directly to fsbo.com. | Apify Proxy, `RESIDENTIAL` group |

### Limits and edge cases

| Condition | What you see | What to do |
|---|---|---|
| A state or city page exposes up to 60 listing cards. | `maxResults` limits the records returned from the parsed cards. | Set `maxResults` between 1 and 60. |
| A price or room filter is set but a card lacks that field. | The card does not pass that filter and is not returned. | Remove or loosen the filter. |
| No listing cards match the location or filters. | The Actor logs that no cards matched and returns no items. | Check the location format and filters. |
| A detail page is unavailable or cannot be parsed. | The record is built from the listing card; unavailable structured fields are omitted. | Use the card fields or run again. |
| `maxResults` is less than 1. | The Actor logs that no records were requested and pushes nothing. | Use a value from 1 through 60. |
| `searchLocation` is empty or not a supported state, city-state, or hyphenated format. | The run raises a validation error before the search page is processed. | Use `CA` or `Los Angeles, CA`. |
| The first request returns an HTTP error, non-HTML content, or a redirect outside fsbo.com. | The request raises an error before cards are processed. | Check the location; review the proxy settings. |
| A run is aborted, times out, or fails after records were pushed. | Pushed records remain in the dataset; the rest are absent. | Review the partial dataset and run status. |

### FAQ

#### How much does it cost to scrape FSBO.com listings?

See Pricing for the per-event prices, worked totals and the Free-plan credit.

#### Why did my run return no listings?

No parsed listing card matched the location or the price and room filters. Check the location format, and whether a filter excludes cards that lack the field.

#### What should I check if a run fails?

Use a supported state or city-state value and confirm the fsbo.com page can be loaded. An initial HTTP error, non-HTML response, or redirect outside fsbo.com raises an error; proxy settings go in `proxyConfiguration`.

#### Does the Actor require a source-site login?

No. It reads public fsbo.com pages and needs no buyer API keys, cookies, or proxy credentials.

#### Is it legal to use public FSBO.com listing data?

The Actor collects public pages. Legality depends on your use case, so review FSBO.com's terms and applicable law, including when contacting property owners.

### Related actors

- [4zida.rs Scraper - Serbia Property Listings](https://apify.com/bovi/4zida-scraper) — related property-listing extraction for Serbia.
- [Aruodas.lt Property Listings Scraper](https://apify.com/bovi/aruodas-scraper) — related property-listing extraction for Lithuania.
- [At Home Japan Rental Listings](https://apify.com/bovi/athome-scraper) — related rental-listing extraction for Japan.

# Actor input Schema

## `searchLocation` (type: `string`):

Use a two-letter state code such as CA, or a city and state such as Los Angeles, CA.

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

Maximum number of listings to return. One public city or state page currently shows up to 60 listings.

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

Keep listings at or above this asking price.

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

Keep listings at or below this asking price.

## `minBedrooms` (type: `integer`):

Keep listings with at least this many bedrooms.

## `minBathrooms` (type: `number`):

Keep listings with at least this many bathrooms.

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

Optional Apify proxy settings. If omitted or disabled, requests go directly to fsbo.com.

## Actor input object example

```json
{
  "searchLocation": "CA",
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Dataset with the scraped listing records.

# 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 = {
    "searchLocation": "CA",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/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 = {
    "searchLocation": "CA",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("bovi/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 '{
  "searchLocation": "CA",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call bovi/fsbo-scraper --silent --output-dataset

```

## MCP server setup

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