# 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, Developer tools
- **Features:** Limited permissions
- **Stats:** 5 total users, 1 monthly users, 96.4% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$8.10 / 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/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

### 🏠 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, market value, property tax, 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. |
| `marketValue` | number | Source-provided market value when available. |
| `propertyTax` | number | Source-provided property tax amount 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 a complete row from a successful current-beta search run:

```json
{
  "propertyId": "674277",
  "sourceUrl": "https://www.propertyshark.com/mason/Property/674277/168-11-116-Ave-Queens-NY-11434/",
  "address": {
    "full": "168-11 116th Avenue, Jamaica, NY 11434",
    "street": "168-11 116th Avenue",
    "city": "Jamaica",
    "state": "NY",
    "zipCode": "11434",
    "borough": "Queens",
    "county": "Queens County",
    "neighborhood": "Jamaica"
  },
  "propertyType": "Two Family Converted from One Family (B3)",
  "propertyClass": "B3",
  "buildingAreaSqFt": 1688,
  "lotAreaSqFt": 3000,
  "lotDimensions": {
    "widthFt": 30,
    "depthFt": 100
  },
  "stories": 2,
  "yearBuilt": 1930,
  "coordinates": {
    "longitude": -73.7793082313508,
    "latitude": 40.6876953634613
  },
  "sales": [
    {
      "saleDate": "2003-03-27",
      "salePrice": 205000
    },
    {
      "saleDate": "2003-03-14",
      "salePrice": 155000
    },
    {
      "saleDate": "2001-09-05",
      "salePrice": 141938
    }
  ],
  "breadcrumbs": [
    "New York City",
    "11434",
    "116th Ave",
    "16811 116th Ave"
  ],
  "marketValue": 834000,
  "propertyTax": 6236,
  "walkability": {
    "score": 75,
    "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.

**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.1: Added market value and property tax data**

- Added market value and property tax data.

**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.
- [PropertyShark Commercial Property Transactions Scraper](https://apify.com/parseforge/commercial-property-transactions-scraper): Compare commercial PropertyShark sale records with broader property rows.
- [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(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 '{
  "target": "search",
  "geography": "New York, NY",
  "maxItems": 1
}' |
apify call maximedupre/propertyshark --silent --output-dataset

```

## MCP server setup

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

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/jKIfvo89fTibbyrda/builds/Kex0X1XW1TDEFBdWK/openapi.json
