# Real Estate Aggregator (`tri_angle/real-estate-aggregator`) Actor

Multi-source scraper for real estate data. Supports rent and sale listings and details, deduplication, and consistent output from Zillow, Realtor, Zumper, Apartments.com, and Redfin.

- **URL**: https://apify.com/tri\_angle/real-estate-aggregator.md
- **Developed by:** [Tri⟁angle](https://apify.com/tri_angle) (Apify)
- **Categories:** Real estate
- **Stats:** 534 total users, 19 monthly users, 100.0% runs succeeded, 11 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

### What does Real Estate Aggregator do?

**Real Estate Aggregator** aggregates US real-estate listings from five providers —
**Realtor.com**, **Apartments.com**, **Zumper**, **Zillow**, and **Redfin** — into
one consistent dataset with a single search. Give it a location and an offer type,
and it queries every relevant provider, normalizes their results to one schema, and
(optionally) removes cross-provider duplicates.

Runs on Apify — with API access, scheduling, integrations, proxy rotation, and monitoring.

### Why use Real Estate Aggregator?

- **One search, every source** — no need to run and reconcile five separate scrapers.
- **Comparable results** — every listing uses the same fields, so you can sort, filter, and dedupe across providers directly.
- **Optional cross-provider dedup** — the same building listed on multiple sites collapses to one record.
- **Detail enrichment on demand** — flip `includeDetails` and every provider that supports it returns richer records.

### How to use Real Estate Aggregator

1. Click **Try for free**.
2. Set a **`location`** (e.g. `90210` or `Austin, TX`) and an **`offerType`** (`rent` or `sale`).
3. *(Optional)* Choose which `providers` to include, toggle `includeDetails`, and turn on `deduplicateResults`.
4. Click **Start**, then download the dataset as JSON, CSV, Excel, or query it via the [Apify API](https://docs.apify.com/api).

### Input

| Field | Type | Description |
|---|---|---|
| `location` (required) | string | A place name, ZIP, or postcode. Run it once per location. |
| `offerType` (required) | `rent` | `sale` | Default `sale`. Rent-only providers are skipped for `sale`. |
| `providers` | array | Which providers to call. Default: all five. Providers that don't match the request are skipped. |
| `maxResults` | integer | Max results **per provider**. Default `100`. |
| `includeDetails` | boolean | Providers fetch each listing's detail page and emit richer records where supported. Default `false`. |
| `deduplicateResults` | boolean | Remove duplicate listings across providers (keep the first occurrence of each address). Default `false`. |
| `units` | `metric` | `imperial` | Output area unit, applied by every provider. Default `imperial` (square feet); `metric` converts to square meters. |
| `propertyTypes` | array | Optional filter (`house`, `condo`, `apartment`, `townhouse`, `land`, `multifamily`, `other`). Providers drop types they don't support. |
| `radiusMiles` | number | Optional search radius. Providers that don't support radius ignore it. |

### Output

A dataset of `Listing` records (or `ListingDetail` when `includeDetails: true`), all sharing one canonical shape. With `deduplicateResults: true`, cross-provider duplicates are removed (same shape, fewer rows).

```json
{
    "source": {
        "provider": "zillow",
        "localId": "12345678",
        "url": "https://www.zillow.com/homedetails/...",
        "scrapedAt": "2026-05-23T14:50:00.000Z"
    },
    "offerType": "sale",
    "propertyType": "house",
    "propertyTypeRaw": "Single Family",
    "address": {
        "street": "123 Main St",
        "city": "Beverly Hills",
        "state": "CA",
        "county": null,
        "zip": "90210",
        "country": "US",
        "formattedAddress": "123 Main St, Beverly Hills, CA 90210"
    },
    "gps": { "lat": 34.09, "lng": -118.41 },
    "price": { "value": 1500000, "currency": "USD", "frequency": "one-time" },
    "livingArea": 2150,
    "landArea": 5400,
    "areaUnit": "sqft",
    "bedrooms": 4,
    "bathrooms": 3,
    "title": null,
    "description": null,
    "pictures": ["https://photos.zillowstatic.com/p1.jpg"],
    "extras": {}
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

#### Provider coverage

| Provider | Offer types | Detail support |
|---|---|---|
| Realtor.com | rent, sale | yes |
| Apartments.com | rent only | yes |
| Zumper | rent only | yes |
| Zillow | rent, sale | yes |
| Redfin | rent, sale | yes |

When you request `offerType: 'sale'`, the rent-only providers (Apartments.com, Zumper) are skipped and noted in the run log.

### 💰 Pricing

This Actor uses a **pay-per-event** pricing model. You're charged a fixed amount for specific actions, so your costs are easy to estimate and control.

The **Deduplicate Results** add-on is charged only once per run, regardless of how many duplicates it removes.

#### Pricing breakdown

| Event | Price (USD) |
|---|---|
| Actor start | $0.003 |
| Extracted listing | $0.002 |
| Extracted listing with details | $0.002 |
| Add-on: Deduplicate results | $0.05 |

Enabling `includeDetails` bills each record as a detailed listing, charged at the same rate as a standard listing.

### FAQ, disclaimers, and support

- **Is this legal?** It aggregates publicly available listing data via each provider. Comply with each site's Terms of Service and your local laws.
- **Why fewer results from some providers?** Providers are skipped when their coverage doesn't match the request (e.g. rent-only providers on a `sale` search).
- **Multiple locations?** Run it once per location.
- **Bugs / requests** → file an issue from the Actor's **Issues** tab.

# Actor input Schema

## `location` (type: `string`):

A single place name, ZIP code, or postcode to search. Multi-location fan-out is a caller concern — invoke it once per location.

## `offerType` (type: `string`):

Whether to search for rentals or properties for sale. Apartments.com and Zumper are rent-only and will be skipped when 'sale' is selected.

## `providers` (type: `array`):

Which provider actors to call. Defaults to all providers. Providers whose capabilities don't match the requested offerType are silently skipped.

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

Maximum number of listings to fetch from each provider.

## `includeDetails` (type: `boolean`):

When true, providers fetch each listing's detail page and emit richer ListingDetail records where supported. Materially more expensive — charged as 'listing-detailed'.

## `deduplicateResults` (type: `boolean`):

When true, duplicate listings are removed across providers: items are matched by normalized (offerType, country, zip, street), and only the first occurrence is kept. Charged as a flat 'deduplicate-addon' fee.

## `units` (type: `string`):

Output area unit, applied by every sub-actor. Default `imperial` keeps each provider's native square feet; `metric` converts area to square meters. The output `areaUnit` field records which unit each record uses.

## `propertyTypes` (type: `array`):

Optional filter on property type. Providers silently drop types they don't support.

## `radiusMiles` (type: `number`):

Optional radius in miles around the location. Providers that don't honor radius silently ignore it.

## Actor input object example

```json
{
  "location": "90210",
  "offerType": "sale",
  "providers": [
    "realtor",
    "apartments",
    "zumper",
    "zillow",
    "redfin"
  ],
  "maxResults": 100,
  "includeDetails": false,
  "deduplicateResults": false,
  "units": "imperial"
}
```

# 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 = {
    "location": "90210"
};

// Run the Actor and wait for it to finish
const run = await client.actor("tri_angle/real-estate-aggregator").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 = { "location": "90210" }

# Run the Actor and wait for it to finish
run = client.actor("tri_angle/real-estate-aggregator").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 '{
  "location": "90210"
}' |
apify call tri_angle/real-estate-aggregator --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/7mcQAVcB4AKIoWrJR/builds/6JcD6cnG2HaaBdsph/openapi.json
