# Housing.com Scraper - Buy & Rent Property Listings (`abotapi/housing-com-scraper`) Actor

From $0.70/1K. Scrape residential property listings from Housing.com across 750+ cities. Extract structured data for properties available to buy or rent, including prices, locations, property details, and more.

- **URL**: https://apify.com/abotapi/housing-com-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** Real estate, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 76 total users, 13 monthly users, 87.2% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Housing.com Scraper: India Property Listings, Prices & BHK Configurations

Housing.com Scraper turns Housing.com into structured property data across 750+ Indian cities. Search by city and locality, or paste Housing.com search links, to get price, BHK configurations, area, coordinates, amenities, images, seller details, EMI estimates and RERA tags for buy and rent listings. Run it once for a snapshot, or schedule it to track only new and changed listings, then export to JSON, CSV or Excel, or pull results straight into your app through the API.

### Why This Scraper?

- **Two ways to find listings.** Build a search from city, locality and service, or paste Housing.com search URLs directly.
- **750+ Indian cities**, with common aliases resolved automatically (Bangalore/Bengaluru, Bombay/Mumbai, Calcutta/Kolkata, Madras/Chennai, Gurgaon/Gurugram).
- **Rich property data.** Price, individual BHK configurations with their own pricing and area, coordinates, amenities, images, seller and agency names, EMI estimates and tags such as RERA verification.
- **Buy and rent, new projects and resale**, all through the same scraper.
- **Post-search filters** for price range, BHK count and property type, so the dataset only contains what matches.
- **Built for schedules.** Incremental mode returns only new and changed listings on recurring runs, and a run that stalls before completing fails loudly instead of returning an empty dataset.
- **Resume an interrupted pull** without paying to recollect properties you already have.

### Use Cases

- **Real estate investors and analysts:** track prices per locality over time to spot undervalued areas or fast-moving markets.
- **Property portals and aggregators:** enrich or cross-list Housing.com inventory inside your own site or app.
- **Agents and brokers:** monitor competing listings, new projects and price changes in your service area.
- **Home buyers and renters:** build a structured shortlist across multiple localities and cities instead of browsing page by page.
- **Market researchers:** build historical datasets of listings, EMI estimates and amenities for analysis.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live record.

| Field | Example |
| --- | --- |
| `listingId` | `"P123ab4567cd"` |
| `title` | `"Sunrise Heights"` |
| `subtitle` / `address` | `"2, 3 BHK Flats"` / `"Andheri West, Mumbai"` |
| `propertyType` | `"resale"` (also `"project"`, `"rent"`) |
| `price_display` | `"Rs 1.85 Cr"` |
| `price_values` | `[16500000, 21000000]` |
| `currency` | `"INR"` |
| `area_value` / `area_unit` | `950` / `"sq.ft"` |
| `latitude` / `longitude` | `19.1197` / `72.8468` |
| `features` | `["2, 3 BHK", "Possession: Dec 2026", "Avg. Price: Rs 19,500/sq.ft"]` |
| `bhk_configs` | individual BHK options, each with its own `price_display`, `area` and `label` |
| `amenities` | `["Swimming Pool", "Gym", "Power Backup"]` |
| `sellers` / `seller_firms` / `highlights` | `["Anita Sharma"]` / `["Sharma Realty"]` / `["Covered Parking"]` |
| `emi` / `tags` | `"Rs 1,28,450/mo"` / `["rera_verified"]` |
| `images` / `image_count` | up to 15 image URLs / `12` |
| `url` | full listing URL on Housing.com |
| `postedAt` / `updatedAt` / `city` / `transactionType` | ISO timestamps posted / last updated; `"Mumbai"`; `"buy"` or `"rent"` |
| `bedrooms` / `furnishing` / `facing` | `2` / `"Semi Furnished"` / `"west facing"` (when the listing states them) |
| `floorNumber` / `totalFloors` | `"12"` / `21` |
| `constructionStatus` / `possessionDate` / `ageOfProperty` / `pricePerArea` | `"Ready to move"` / `"Sep, 2029"` / `"1 Years Old"` / `"31.43 K/sq.ft"` |
| `isVerified` / `verificationStatus` / `isReraVerified` | verification flags and type (e.g. `DC_VERIFIED`) |
| `isBrokerageChargeable` / `isMostContacted` / `projectName` / `projectId` | listing flags and the project the listing belongs to |
| `coverImageUrl` / `configurations` / `carpet_area_value` / `carpet_area_unit` | cover image, available BHK configurations, carpet area (only when listed) |
| `scraped_at` | `"2026-09-28T05:12:33"` |
| `changeType` / `changedFields` / `firstSeenAt` / `lastSeenAt` | incremental mode only: change label, changed field names and ISO timestamps for this state key |

### How to Use

1. Pick a **mode**: `search` (build a query from city, locality and service) or `url` (paste Housing.com search links).
2. Fill in the fields for that mode, and set any price, BHK or property type filters you want.
3. Set **Max Properties** and **Max Pages** to control run size and cost, then click **Start**. Max Properties is capped at 100,000 per run (0 means that cap).
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Buy properties in Mumbai:**

```json
{
  "mode": "search",
  "service": "buy",
  "city": "Mumbai",
  "max_properties": 30
}
```

**3 BHK apartments in Andheri West under a price cap:**

```json
{
  "mode": "search",
  "service": "buy",
  "city": "Mumbai",
  "locality": "andheri_west",
  "min_bhk": 3,
  "max_bhk": 3,
  "max_price": 50000000,
  "max_properties": 50
}
```

**Paste a Housing.com search link:**

```json
{
  "mode": "url",
  "urls": ["https://housing.com/in/rent/bangalore/koramangala"]
}
```

**Daily monitoring of a search (incremental mode):**

```json
{
  "mode": "search",
  "service": "rent",
  "city": "Bangalore",
  "locality": "koramangala",
  "max_properties": 200,
  "incrementalMode": true,
  "emitExpired": true
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/housing-com-scraper").call(run_input={"mode": "search", "service": "buy", "city": "Mumbai", "max_properties": 30})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item["price_display"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/housing-com-scraper').call({ mode: 'search', service: 'buy', city: 'Mumbai', max_properties: 30 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### Filters and Max Properties

`min_price`, `max_price`, `min_bhk`, `max_bhk` and `property_type` are post-filters: the actor fetches full pages of results from Housing.com first, then keeps only the properties that match. `max_properties` counts properties that passed those filters, not raw pages fetched, so a narrow filter combined with a low `max_pages` can return fewer properties than `max_properties` asks for simply because the scan ran out of pages to filter from. Raise `max_pages` to give it more to filter from.

#### Resume and recurring updates

Two distinct features:

- **Resume** (`resumeFromRunId`) continues **one** interrupted pull. Paste a previous run ID or dataset ID to pick up where it left off.
- **Incremental mode** (`incrementalMode`) is for scheduling this actor daily or weekly against the **same** city/locality/service (or URL set) and filters, and getting only what changed. The first run returns every matching property as `NEW`. Later runs return `NEW`, `UPDATED` and `REAPPEARED` properties by default; `UNCHANGED` properties are suppressed (not returned, not billed) unless `emitUnchanged` is on. `EXPIRED` properties (tracked previously, no longer found; a property that is still listed but aged past `days_old` is retired quietly with no row) are only produced when `emitExpired` is on and the run fully scanned the tracked search to its natural end, not when `max_properties` or `max_pages` capped it, and not when `resumeFromRunId` was used. `stateKey` names a monitoring campaign explicitly, or shares state across differently configured runs. `ignoreFieldsForChanges` lists extra fields to leave out of change detection; changing the list never causes a one-time wave of `UPDATED` rows. Fields added to the output in a later version (for example `postedAt`, `updatedAt`, `isVerified`, `cityId`, `locality`) are compared only once your saved baseline already contains them, so upgrading never causes a one-time wave of `UPDATED` rows; from the next run on they are compared like every other field.

#### Supported URL shapes and output views

In `url` mode the scraper accepts these Housing.com search links:

- `https://housing.com/in/buy/<city>` and `https://housing.com/in/rent/<city>` (whole city)
- `https://housing.com/in/buy/<city>/<locality>` and `https://housing.com/in/rent/<city>/<locality>` (one locality)

Links to a single project or listing page cannot be fetched and are skipped with a warning in the run log. If none of your links is usable the run fails with "No valid URLs parsed from input". Leaving `urls` untouched scrapes the four prefilled examples.

The dataset has four views: **Overview**, **Map View**, **Full Details**, and **Changes (incremental)**, which shows `changeType`, `changedFields`, `firstSeenAt`, `lastSeenAt`, title, price and URL for runs with incremental mode on.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each record, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` builds a query from city, locality and service; `url` extracts listings from Housing.com search URLs you paste. |
| `urls` | array | one example per supported shape (buy city, buy locality, rent city, rent locality) | Housing.com URLs: `/in/buy/<city>`, `/in/rent/<city>`, and `/in/<buy\|rent>/<city>/<locality>`. Search-result links (`/search?f=...`, `/searches/...`) are not supported (those pages do not exist on the site). Single project or listing pages are skipped with a warning. Used only in url mode; a URL-mode run with the field untouched now scrapes these four examples instead of failing. |
| `service` | string | `buy` | `buy` or `rent`. Used only in search mode. |
| `city` | string | `Mumbai` | City name (e.g. Mumbai, Delhi, Bangalore, Pune). Used only in search mode. |
| `locality` | string | (none) | Locality within the city (e.g. andheri_west, bandra_west). Leave empty for the entire city. Used only in search mode. |
| `cities` | array | (none) | Extra cities to scrape in the same run, on top of `city`. Same service for all; Max Properties is the total across cities. Search mode only. |
| `days_old` | integer | (none) | Keep only listings posted within the last N days. Post-filter; listings with no posted date are kept. |
| `min_price` | integer | (none) | Minimum price in INR. Post-filter, applied after fetching results. |
| `max_price` | integer | (none) | Maximum price in INR. Post-filter, applied after fetching results. |
| `min_bhk` | number | (none) | Minimum BHK, 1 to 6. Post-filter. |
| `max_bhk` | number | (none) | Maximum BHK, 1 to 6. Post-filter. |
| `property_type` | string | (none) | `project`, `resale`, or `rent`. Post-filter. |
| `max_properties` | integer | `30` | Maximum number of properties to scrape, up to 100,000. `0` means that 100,000 maximum. |
| `max_pages` | integer | `1000` | Maximum number of result pages to fetch, 30 listings per page. |
| `dataset_name` | string | (none) | Custom dataset name. Leave empty for the default dataset. |
| `clear_dataset` | boolean | `false` | Clear the dataset before scraping. |
| `resumeFromRunId` | string | (none) | Paste a previous run ID or dataset ID to continue an interrupted pull, picking up where it left off. |
| `incrementalMode` | boolean | `false` | Turn on for daily or recurring monitoring of the same search. Later runs return only new, updated and reappeared properties. |
| `stateKey` | string | (none) | Name a monitoring campaign, or share state across differently configured runs. Incremental mode only. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) properties unchanged since the last run. Incremental mode only. |
| `emitExpired` | boolean | `false` | Also return (and bill) properties no longer found, once a run fully scans the tracked search. Incremental mode only. |
| `ignoreFieldsForChanges` | string list | empty | Field names (for example `tags` or `highlights`) that must not make a property `UPDATED` when only they change. They stay in the output but are left out of the comparison and of `changedFields`; `scraped_at` is always ignored. Incremental mode only. |
| `proxy` | object | (none) | Optional proxy configuration. The scraper works without one. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each property to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which property pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live record.

```json
{
  "listingId": "P123ab4567cd",
  "title": "Sunrise Heights",
  "subtitle": "2, 3 BHK Flats",
  "address": "Andheri West, Mumbai",
  "propertyType": "resale",
  "price_display": "Rs 1.85 Cr",
  "price_values": [16500000, 21000000],
  "currency": "INR",
  "area_value": 950,
  "area_unit": "sq.ft",
  "latitude": 19.1197,
  "longitude": 72.8468,
  "features": ["2, 3 BHK", "Possession: Dec 2026", "Avg. Price: Rs 19,500/sq.ft"],
  "bhk_configs": [
    { "id": "cfg1", "price_display": "Rs 1.65 Cr", "area": "750 sq.ft", "label": "2 BHK" },
    { "id": "cfg2", "price_display": "Rs 2.1 Cr", "area": "950 sq.ft", "label": "3 BHK" }
  ],
  "amenities": ["Swimming Pool", "Gym", "Power Backup", "Covered Parking"],
  "sellers": ["Anita Sharma"],
  "seller_firms": ["Sharma Realty"],
  "highlights": ["Covered Parking", "24x7 Security"],
  "emi": "Rs 1,28,450/mo",
  "tags": ["rera_verified"],
  "images": ["https://img.housingcdn.com/sample1.jpg", "https://img.housingcdn.com/sample2.jpg"],
  "image_count": 12,
  "url": "https://housing.com/in/buy/resale/mumbai/andheri-west/sunrise-heights-p123ab4567cd",
  "scraped_at": "2026-09-28T05:12:33.123456"
}
```

### Plan Requirement

No proxy is needed by default: the scraper reads Housing.com's public search data directly, and the run does not use a proxy unless you configure one. Under **Proxy & connection** you can optionally add Apify Proxy (with your chosen groups, which needs a paid Apify plan) or your own proxy URL; when set, every request goes through it. Proxy traffic is billed to your account, so leave it off unless you need extra headroom for large multi-city runs or frequent monitoring.

### FAQ

#### How much does it cost?

You pay per property returned. Two events apply: `apify-default-dataset-item` is charged once per property written to the dataset (the unit is one property row), and `apify-actor-start` is charged once per run, at the start. The **Pricing** tab on the actor page shows the current rates. Suppressed unchanged properties in incremental mode are not returned and not billed. Use **Max Properties** to cap the cost of any run.

#### Is it legal to scrape Housing.com?

This actor collects only publicly available property listings. You are responsible for how you use the data: follow Housing.com's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Seller and agent contact details may be personal data in some jurisdictions, handle them accordingly.

#### Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. The first scheduled run returns every matching property as `NEW`; later runs return only `NEW`, `UPDATED` and `REAPPEARED` properties, and unchanged ones are not billed unless you turn on `emitUnchanged`.

#### Why did I get fewer properties than Max Properties?

`min_price`, `max_price`, `min_bhk`, `max_bhk` and `property_type` are post-filters: the actor fetches full pages of results from Housing.com first, then keeps only the properties that match. If your filters are narrow, raise **Max Pages** so the actor has more listings to filter from; a low page cap can run out of pages before reaching your target count.

#### Why did my run fail instead of returning an empty dataset?

If a search stops before reaching Housing.com's own end of results, and nothing was collected, the run fails with a clear message instead of finishing as an empty success. When the requests themselves keep failing (five in a row) the run stops at once instead of retrying every remaining search, and the message says it is a connection problem: run it again in a few minutes. When the city or locality is not recognised, the message names the value you entered and asks you to check its spelling (the way Housing.com writes it, for example andheri_west) instead. A search that genuinely has no matching properties, or whose results were all excluded by your filters, still finishes successfully with an empty or partial dataset.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

### 🔗 Want more real estate data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🏨 <a href="https://apify.com/abotapi/hipflat-scraper"><b>Hipflat Scraper Thailand Property &amp; Projects</b></a><br>Scrape hipflat.co.th property listings and new-project data across Thailand: price, price...</td><td>🏠 <a href="https://apify.com/abotapi/propertyfinder-ae-scraper"><b>Property Finder UAE Scraper</b></a><br>Scrape PropertyFinder.ae listings at scale. Extract prices, property details, images...</td></tr>
<tr><td>🏠 <a href="https://apify.com/abotapi/fotocasa-es-scraper"><b>Fotocasa.es</b></a><br>From $1/1K. Scrape Spain property listings from fotocasa.es. Get price, surface, rooms...</td><td>🏠 <a href="https://apify.com/abotapi/immoscout24-scraper"><b>ImmobilienScout24.de Scraper</b></a><br>$0.9💰/1K for Gold discount. Extract property listings from immobilienscout24.de...</td></tr>
<tr><td>🏠 <a href="https://apify.com/abotapi/idealista-scraper"><b>Idealista Scraper</b></a><br>From $1/1K. Scrape Idealista properties across Spain, Italy, and Portugal. Extract 35+...</td><td>🏠 <a href="https://apify.com/abotapi/propertyguru-sg-scraper"><b>PropertyGuru SG Scraper</b></a><br>From $0.80/1K. Scrape PropertyGuru.com.sg sale and rental listings with 30+ structured...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/housing-com-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

Scraping mode: 'search' builds query from city/locality, 'url' extracts locality from provided housing.com URLs

## `urls` (type: `array`):

Housing.com URLs (url mode only): city pages /in/buy/<city> or /in/rent/<city>, locality pages /in/buy/<city>/<locality>, (buy or rent). Search-result links such as /search?f=... are not supported. Single project or listing pages are not supported and are skipped with a warning.

## `service` (type: `string`):

Buy or Rent

## `city` (type: `string`):

City name (e.g. 'Mumbai', 'Delhi', 'Bangalore', 'Pune'). Use the city listing to find exact names.

## `locality` (type: `string`):

Locality/area within the city (e.g. 'andheri_west', 'bandra_west'). Leave empty for entire city.

## `cities` (type: `array`):

Extra cities to scrape in the same run, in addition to City (e.g. \["Pune", "Bangalore"]). Same Service applies to all. Max Properties is a total across all cities. Ignored in URL mode.

## `min_price` (type: `integer`):

Minimum price in INR. Post-filter — applied client-side after fetching results. For buy: e.g. 5000000 = 50 Lakhs. For rent: e.g. 30000 = ₹30K/month.

## `max_price` (type: `integer`):

Maximum price in INR. Post-filter — applied client-side.

## `min_bhk` (type: `number`):

Minimum BHK (e.g. 2 for 2+ BHK). Post-filter — applied client-side.

## `max_bhk` (type: `number`):

Maximum BHK (e.g. 3 for up to 3 BHK). Post-filter — applied client-side.

## `property_type` (type: `string`):

Filter by property type. Post-filter — applied client-side.

## `days_old` (type: `integer`):

Only keep listings posted within the last N days. Post-filter on the listing's posted date; listings with no posted date are kept. In incremental mode a tracked listing that is still live but has aged past the window is retired quietly, with no EXPIRED row.

## `max_properties` (type: `integer`):

Maximum number of properties to scrape (0 = the 100,000 maximum)

## `max_pages` (type: `integer`):

Maximum number of result pages (30 listings per page)

## `dataset_name` (type: `string`):

Custom dataset name (leave empty for default)

## `clear_dataset` (type: `boolean`):

Clear the dataset before scraping

## `proxy` (type: `object`):

Proxy configuration. Optional — the API works without proxy.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a large pull of properties without returning or charging for properties already collected there. Use this after an interrupted run, or when continuing a pull in another run. For recurring daily monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring of the same city/locality/URL search. The first run returns all matching properties as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED properties -- a property is UPDATED only when its own listed details change (price, title, area, amenities, images, etc.); the scraped_at timestamp is ignored for this comparison since it always differs run to run by construction (every returned property still carries its current scraped_at value). Turn on "Emit unchanged" or "Emit expired" only when you also want those properties returned (and billed). State is kept separately for each city/locality/service or URL set and filter combination; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the city/locality/service (or URLs) and filters used -- different search setups then never mix state with each other.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return properties that have not changed since the last run, marked UNCHANGED. This returns -- and bills -- extra rows you already have, so leave it off unless you specifically want the full snapshot every run.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return properties that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search to its natural end -- not when Max Properties or Max Pages capped it, or when Resume was used. This returns -- and bills -- extra synthetic rows, so leave it off unless you need expiry tracking.

## `ignoreFieldsForChanges` (type: `array`):

Incremental mode only. Field names (for example tags or highlights) that must NOT make a property count as UPDATED when only they change. The fields are still returned in every row; they are just left out of the comparison and out of changedFields. scraped_at is always ignored. Fields added in a later version are compared only once your saved baseline already contains them (no one-time wave of UPDATED rows). Leave empty to compare every other field.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON — the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "urls": [
    "https://housing.com/in/buy/mumbai",
    "https://housing.com/in/buy/mumbai/andheri_west",
    "https://housing.com/in/rent/pune",
    "https://housing.com/in/rent/mumbai/bandra_west"
  ],
  "service": "buy",
  "city": "Mumbai",
  "locality": "andheri_west",
  "max_properties": 30,
  "max_pages": 1000,
  "clear_dataset": false,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `listings` (type: `string`):

Individual property listing records with price, BHK configurations, coordinates, and detail data.

## `metadata` (type: `string`):

Scraping run metadata including timing, counts, and configuration.

# 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 = {
    "mode": "search",
    "urls": [
        "https://housing.com/in/buy/mumbai",
        "https://housing.com/in/buy/mumbai/andheri_west",
        "https://housing.com/in/rent/pune",
        "https://housing.com/in/rent/mumbai/bandra_west"
    ],
    "city": "Mumbai",
    "locality": "andheri_west",
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/housing-com-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 = {
    "mode": "search",
    "urls": [
        "https://housing.com/in/buy/mumbai",
        "https://housing.com/in/buy/mumbai/andheri_west",
        "https://housing.com/in/rent/pune",
        "https://housing.com/in/rent/mumbai/bandra_west",
    ],
    "city": "Mumbai",
    "locality": "andheri_west",
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/housing-com-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 '{
  "mode": "search",
  "urls": [
    "https://housing.com/in/buy/mumbai",
    "https://housing.com/in/buy/mumbai/andheri_west",
    "https://housing.com/in/rent/pune",
    "https://housing.com/in/rent/mumbai/bandra_west"
  ],
  "city": "Mumbai",
  "locality": "andheri_west",
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/housing-com-scraper --silent --output-dataset

```

## MCP server setup

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