# PropertyShark Scraper (`maximedupre/propertyshark`) Actor

Collect public PropertyShark property records by geography or public property page URLs. Get addresses, sale history, building and lot details, coordinates, breadcrumbs, and walkability data when available in structured dataset rows.

- **URL**: https://apify.com/maximedupre/propertyshark.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Real estate, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$7.25 / 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.

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

### 🏠 PropertyShark property records for real estate research

Real estate researchers, property appraisers, investors, and market analysts can collect public PropertyShark records for one supported geography or a list of public property page URLs. Get structured rows with property IDs, addresses, sale history, building and lot details, coordinates, breadcrumbs, and walkability when the source provides them, so you can review a market without copying fields by hand.

**Use cases**

- Review one public property page with **[Property Data By Address](https://apify.com/maximedupre/propertyshark/examples/property-data-by-address)**.
- Review a New York market with **[NYC Property Records](https://apify.com/maximedupre/propertyshark/examples/nyc-property-records)** and its matching property rows.
- Track past transactions with **[Property Sales Records](https://apify.com/maximedupre/propertyshark/examples/property-sales-records)** for a supported place.
- Search public records with **[Property Records Search](https://apify.com/maximedupre/propertyshark/examples/property-records-search)** and set sale, price, or building-size filters.
- Help a **[Property Appraiser](https://apify.com/maximedupre/propertyshark/examples/property-appraiser)** review addresses, IDs, and property details from public pages.

#### 📊 PropertyShark property records

Each saved row represents one public PropertyShark property. Rows can include the property ID, source page, address parts, property type and class, sale history, building and lot measurements, stories, year built, coordinates, page breadcrumbs, and walkability details when PropertyShark provides them.

#### ▶️ Run PropertyShark searches or page collections

Choose Property search for one geography and optional sale, price, and building-size filters. Choose Property pages to submit one or more public PropertyShark page URLs. The first eligible match for a property is saved; later matches of the same source property are ignored.

#### ⚙️ Input

Only fields for the selected `target` are used in a run. Use `search` for one geography or `propertyPages` for submitted public page URLs.

| Field | Type | What it does |
| --- | --- | --- |
| `target` | string | Required. Choose `search` for one geography or `propertyPages` for public PropertyShark page URLs. |
| `geography` | string | Place for Property search, such as a city, county, state, or ZIP code. |
| `saleDateFrom` | string | First sale date to include. Use a calendar date or a relative date. |
| `saleDateTo` | string | Last sale date to include. Use a calendar date or a relative date. |
| `salePriceMin` | number | Include sales at or above this price. |
| `salePriceMax` | number | Include sales at or below this price. |
| `buildingSizeMin` | number | Include buildings at or above this size in square feet. |
| `buildingSizeMax` | number | Include buildings at or below this size in square feet. |
| `propertyPageUrls` | array of objects | Add at least one public PropertyShark property page URL for Property pages, with one URL in each row. |
| `propertyPageUrls[]` | object | One submitted property-page URL object. |
| `propertyPageUrls[].url` | string (URL) | A public PropertyShark property page URL. |
| `maxItems` | integer | Positive upper bound for property records in the run; the form starts at 1. Leave this empty to return all available results until the source is exhausted. |

The date, price, and building-size fields are used only for Property search. Leave a filter blank when you do not want that boundary. `maxItems` applies to both targets; leaving it empty returns all available results until the source is exhausted.

Each run reads public source pages at run time, so its rows reflect the PropertyShark data available then.

This example matches the public input from a successful current-beta default-input search run:

```json
{
  "target": "search",
  "geography": "New York, NY",
  "maxItems": 1
}
```

#### 🧾 Output

Property search and Property pages use the same output shape. The public run output has one `dataset` field (`string` URL), which opens the default dataset of structured property rows. The table below covers every field in each dataset row. Fields other than `propertyId`, `sourceUrl`, and `address.full` are included when the source returns them.

| Field | Type | What it does |
| --- | --- | --- |
| `propertyId` | string | Stable PropertyShark ID for the property. |
| `sourceUrl` | string (URL) | PropertyShark source page for the property. |
| `address` | object | Property address and place details. |
| `address.full` | string | Full property address; the required address value. |
| `address.street` | string | Street name and number when available. |
| `address.city` | string | City when available. |
| `address.state` | string | State or region when available. |
| `address.zipCode` | string | ZIP code when available. |
| `address.county` | string | County when available. |
| `address.borough` | string | Borough when available. |
| `address.neighborhood` | string | Neighborhood when available. |
| `propertyType` | string | Property type from PropertyShark when available. |
| `propertyClass` | string | Property class from PropertyShark when available. |
| `buildingAreaSqFt` | number | Building area in square feet when available. |
| `lotAreaSqFt` | number | Lot area in square feet when available. |
| `lotDimensions` | object | Lot width and depth when available. |
| `lotDimensions.widthFt` | number | Lot width in feet when available. |
| `lotDimensions.depthFt` | number | Lot depth in feet when available. |
| `stories` | number | Number of building stories when available. |
| `yearBuilt` | integer | Building year when available. |
| `coordinates` | object | Property latitude and longitude when available. |
| `coordinates.latitude` | number | Latitude in decimal degrees. |
| `coordinates.longitude` | number | Longitude in decimal degrees. |
| `sales` | array of objects | Sale history found for the property. |
| `sales[]` | object | One sale transaction with a date and price. |
| `sales[].saleDate` | string (date) | Date of one sale. |
| `sales[].salePrice` | number | Price of one sale. |
| `breadcrumbs` | array of strings | Labels in the PropertyShark page path. |
| `breadcrumbs[]` | string | One label from the PropertyShark page path. |
| `walkability` | object | Walkability score and text when available. |
| `walkability.score` | number | Walkability score from 0 to 100. |
| `walkability.description` | string | Text that explains the walkability score. |

Here is the complete row returned by that successful current-beta search run:

```json
{
  "propertyId": "130719",
  "sourceUrl": "https://www.propertyshark.com/mason/Property/130719/215-33-St-Brooklyn-NY-11232/",
  "address": {
    "full": "215 33rd Street, Brooklyn, NY 11232",
    "street": "215 33rd Street",
    "city": "Brooklyn",
    "state": "NY",
    "zipCode": "11232",
    "borough": "Brooklyn",
    "county": "Brooklyn County",
    "neighborhood": "Greenwood Heights"
  },
  "propertyType": "Over Six Families without Stores (C1)",
  "propertyClass": "C1",
  "buildingAreaSqFt": 13400,
  "lotAreaSqFt": 5000,
  "lotDimensions": {
    "widthFt": 50,
    "depthFt": 100.17
  },
  "stories": 4,
  "yearBuilt": 1917,
  "coordinates": {
    "longitude": -74.000705003735,
    "latitude": 40.6550748138328
  },
  "sales": [
    {
      "saleDate": "2021-09-01",
      "salePrice": 4725000
    },
    {
      "saleDate": "2017-07-06",
      "salePrice": 5800000
    }
  ],
  "breadcrumbs": [
    "Kings",
    "11232",
    "33rd St",
    "215 33rd St"
  ],
  "walkability": {
    "score": 83,
    "description": "Very Walkable"
  }
}
```

#### 💳 Pricing

This Actor's PropertyShark pricing uses pay-per-event billing. You pay once for each successfully collected property. The charge applies to a property only after that property is saved.

The `maxItems` limit can help you control how many property rows a run may save. A blank limit means the Actor keeps collecting available results until the source is exhausted.

#### 🔌 Integrations

Use Apify Console to start a run and open the default dataset link. The Actor does not include third-party delivery connections or automation integrations.

**Walkthrough**

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### Can I collect one property's details from a public page URL?

Yes. Choose `propertyPages` and add the public PropertyShark page URL in `propertyPageUrls`. You can add a list of URLs in one run.

##### Can I set exact sale-date boundaries?

Yes. In Property search, use `saleDateFrom` and `saleDateTo`. Each accepts a calendar date or a relative date, and either field can be left blank.

##### What does leaving Maximum number of records empty do?

It returns all available results until the source is exhausted. Set a positive `maxItems` value when you want an upper bound for the run.

##### Does the Actor return prior sales and walkability?

It returns sale history, breadcrumbs, and walkability details when those values are available on the public PropertyShark page.

##### What happens if the same property appears more than once?

The first eligible match is saved. Later matches of the same source property are ignored.

##### Does this Actor need a PropertyShark subscription?

No PropertyShark credentials are required. The Actor collects public PropertyShark records, and this Actor uses Apify pay-per-event pricing.

##### Is this a PropertyShark homes for sale tool?

No. It collects public property records and sale history, not a listing feed for homes for sale.

##### Is the PropertyShark data verified by this Actor?

The rows come from public PropertyShark pages. Check each `sourceUrl` and the fields returned for that page; this Actor does not add an independent verification service.

##### Can one run search several geographies?

No. Property search accepts one geography per run. To collect several direct pages, use `propertyPages` and submit their public URLs.

### 📝 Changelog

**0.0: Initial release**

- Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~propertyshark/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [Realtor Scraper](https://apify.com/maximedupre/realtor-scraper) — Compare active, sold, or pending Realtor.com listings with PropertyShark records by location.
- [Zillow Foreclosure & Pre-Foreclosure Scraper](https://apify.com/maximedupre/zillow-foreclosure-pre-foreclosure-scraper) — Add Zillow distress type, price, Zestimate when shown, and source URL data to a market review.
- [ForRent Scraper](https://apify.com/maximedupre/forrent-scraper) — Check rental listings, rent ranges, floor plans, and nearby places for the same market.
- [FazWaz Thailand Property Scraper — Sale & Rent](https://apify.com/maximedupre/fazwaz-scraper) — Compare Thailand sale and rental listings with PropertyShark property records.
- [Propertyshark ProductInfo Scraper](https://apify.com/getdataforme/propertyshark-productInfo-scraper) — Collect detailed PropertyShark property data for real estate research.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `target` (type: `string`):

Choose what to collect from PropertyShark.

## `geography` (type: `string`):

Enter one place supported by PropertyShark, such as a city, county, state, or ZIP code. Used only for Property search.

## `saleDateFrom` (type: `string`):

Enter the first sale date to include. Use a calendar date or a relative date. Leave blank for no start date. Used only for Property search.

## `saleDateTo` (type: `string`):

Enter the last sale date to include. Use a calendar date or a relative date. Leave blank for no end date. Used only for Property search.

## `salePriceMin` (type: `number`):

Include sales at or above this price. Leave blank for no minimum. Used only for Property search.

## `salePriceMax` (type: `number`):

Include sales at or below this price. Leave blank for no maximum. Used only for Property search.

## `buildingSizeMin` (type: `number`):

Include buildings at or above this size in square feet. Leave blank for no minimum. Used only for Property search.

## `buildingSizeMax` (type: `number`):

Include buildings at or below this size in square feet. Leave blank for no maximum. Used only for Property search.

## `propertyPageUrls` (type: `array`):

Add one public PropertyShark property page URL in each row. Used only for Property pages.

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

Stop after this many property records. Leave blank to return all available results until the source is exhausted.

## Actor input object example

```json
{
  "target": "search",
  "geography": "New York, NY",
  "maxItems": 1
}
```

# Actor output Schema

## `dataset` (type: `string`):

A link to the PropertyShark property records in 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 = {
    "target": "search",
    "geography": "New York, NY",
    "maxItems": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/propertyshark").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 = {
    "target": "search",
    "geography": "New York, NY",
    "maxItems": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/propertyshark").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 '{
  "target": "search",
  "geography": "New York, NY",
  "maxItems": 1
}' |
apify call maximedupre/propertyshark --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/jKIfvo89fTibbyrda/builds/uho5gV5WxGkCfqo1j/openapi.json
