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

Scrape Housing.com buy and rent listings by city or canonical search URL. Get deduplicated prices, locations, areas, media, tags, RERA, sellers, and optional detail enrichment.

- **URL**: https://apify.com/hermandev/housing-com-property-scraper.md
- **Developed by:** [Herman Fassett](https://apify.com/hermandev) (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

from $1.00 / 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.

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

## Housing.com Listings Scraper

A production-minded, API-first Apify Actor for public Housing.com buy and rent listings. It uses Housing.com's structured GraphQL responses and does not launch a browser, keeping runs fast and inexpensive.

Use it for property-market research, inventory monitoring, price comparisons, broker and developer analysis, scheduled exports, and real-estate datasets.

### What you get

- Easy city search for 12 major Indian markets, with buy and rent selection.
- Advanced canonical-URL mode that preserves filters already encoded by Housing.com.
- Optional minimum/maximum price and listing-age filters.
- Correct multi-page extraction with global listing-ID deduplication.
- A stable schema for projects, resale listings, buy listings, and rentals.
- Useful default data without per-listing requests: prices, locations, areas, configurations, images, dates, tags, features, and trust/status flags.
- Optional detail enrichment for deeper addresses, descriptions, amenities, RERA details, nearby places, floor plans, and sellers.
- Incremental dataset writes, transparent run statistics, conservative retries, and Apify Proxy support.

### Input modes

Choose exactly one mode per run.

#### Easy city mode

```json
{
  "cities": ["bengaluru", "mumbai"],
  "transactionTypes": ["buy", "rent"],
  "minPrice": 2000000,
  "maxPrice": 20000000,
  "daysOld": 30,
  "maxItems": 500,
  "maxPagesPerSearch": 40,
  "maxImages": 6,
  "enrichDetails": false
}
```

Supported city values are `mumbai`, `bengaluru`, `hyderabad`, `pune`, `chennai`, `new-delhi`, `gurgaon`, `noida`, `kolkata`, `ahmedabad`, `thane`, and `navi-mumbai`. Common aliases such as Bangalore, Delhi, Gurugram, and Calcutta are also accepted through API input.

City mode creates one search for each city and transaction-type combination and validates the city returned by Housing.com before continuing.

#### Exact URL mode

```json
{
  "startUrls": [
    { "url": "https://housing.com/in/buy/searches/M8vP38f9yfbk7p3m2h1f" }
  ],
  "maxItems": 100,
  "enrichDetails": false
}
```

Supported URL patterns:

- Buy: `https://housing.com/in/buy/searches/<HASH>`
- Rent: `https://housing.com/rent/search-<HASH>`

Friendly locality, project, and SEO URLs are rejected with a clear error. The Actor never silently falls back to expensive browser automation.

### Input reference

- `cities`: supported cities for easy mode.
- `transactionTypes`: `buy`, `rent`, or both; defaults to both in city mode.
- `startUrls`: canonical hashed Housing.com search URLs for exact-search mode.
- `maxItems`: maximum matching unique listings saved across the whole run; default `100`.
- `minPrice` / `maxPrice`: optional overlapping price-range filter in INR.
- `daysOld`: optional maximum listing age in days. Records without a usable posted date are excluded when active.
- `maxPagesPerSearch`: safety/cost cap per generated search or URL; default `40`.
- `maxImages`: maximum property and floor-plan URLs retained per listing; default `6`, maximum `50`.
- `enrichDetails`: request deeper listing data after cheap filters have passed.
- `includeRaw`: include parsed search and detail records under `raw`.
- `proxyConfiguration`: standard Apify Proxy or custom proxy configuration.
- `maxConcurrency`: concurrent detail requests from 1 to 5; search pages remain sequential.

`maxItems` counts emitted unique IDs, not raw API rows. Duplicate and filtered rows do not consume the result limit. Price ranges match when the listing range overlaps the requested range.

### Output

Every record uses the same null-preserving structure. Important field groups include:

- Identity: `id`, `originalId`, `url`, `source`, `searchUrl`, `scrapedAt`.
- Classification: `transactionType`, `propertyType`, `title`, `subtitle`, `projectName`, `saleType`.
- Price: `price`, `pricePerArea`.
- Location: `address`, `subAddress`, `longAddress`, `city`, `locality`, `sublocality`, `housingRegion`, IDs, state, and coordinates.
- Property: `bedrooms`, `bedroomOptions`, bathrooms, built-up/carpet area, furnishing, floor, parking, balcony, facing, age, possession, and construction status.
- Media: cover image, source image count, property images, floor plans, video tour, and brochure.
- Trust and status: verification/certification, RERA, MyGate, exclusivity, brokerage, recency, activity, and promotion flags.
- Dates and discovery: `postedAt`, `updatedAt`, display date, property/source tags, feature labels, rating, labels, and badges.
- Parties and enrichment: developer, sellers, configurations, amenities, nearby places, highlights, and description.

Unavailable scalar values remain `null`; unavailable collections are empty arrays. The Actor does not invent values. For a multi-configuration project, `bedrooms` remains null and all known values appear in `bedroomOptions` and `configurations`.

### Detail enrichment and cost

The default mode uses roughly one request per 30 raw rows. Detail enrichment adds approximately one request per matching emitted listing. Filters run before enrichment, so rejected listings do not incur detail requests.

Enable enrichment when you need the deepest available descriptions, overview attributes, amenities, nearby places, sellers, RERA/configuration data, or full listing media. Housing.com does not publish every field for every property, so enrichment improves coverage but cannot guarantee every nullable field.

### Proxy and reliability

A proxy is not required for typical smaller runs. By default, `proxyConfiguration.useApifyProxy` is `false`, so the Actor connects directly and still applies conservative request spacing, retries, jittered exponential backoff, and block detection. Without a proxy, however, retries use the same outgoing IP address.

Enable Apify Proxy for larger, repeated, scheduled, or detail-enriched runs, or if a run reports HTTP 403, HTTP 429, blocked requests, or exhausted retries. When Apify Proxy is enabled, the Actor uses sticky sessions for pagination and can attempt an Indian residential proxy after a detected block if residential proxies are available to the account running the Actor.

Apify Proxy does not require manually entering proxy credentials in the Actor input. Proxy availability and usage may affect run cost. Custom proxy URLs are also supported through `proxyConfiguration`.

### Correctness and resilience

- Uses Housing.com's service-specific page flow: buy page 2+ includes `meta.pagination_flow: true`; rent currently omits it because the rent backend otherwise returns an empty page.
- Validates returned page numbers, page fingerprints, and new IDs.
- Retries one suspicious repeated page with proxy rotation, then stops safely rather than duplicating page 1 forever.
- Uses global deduplication across pages, URLs, cities, and transaction targets.
- Uses conservative spacing, jittered exponential backoff, block detection, sticky pagination sessions, and rotated retries.
- Attempts an Indian residential proxy after a block when Apify Proxy and account access allow it.
- Continues with base data when an individual detail request fails.
- Writes `RUN_STATS` to the default key-value store even when a run fails.

Run diagnostics include searches planned/completed, pages fetched, raw rows, unique rows examined, filtered rows, duplicates, emitted rows, detail outcomes, retries, blocks, search failures, pagination stops, page-cap stops, city validation failures, and timing.

### Verification

The automated suite covers four-page pagination, cross-page and cross-search duplicates, unique-result limits, city discovery and aliases, price/date filtering before details, maximum-page stops, independent enrichment, malformed/unsupported input, empty results, repeated-page protection, 403, 429, timeouts, malformed JSON, retry backoff, and residential proxy fallback.

Release acceptance on 2026-08-14 retrieved 100 unique Bengaluru buy listings and 100 unique Bengaluru rent listings across four pages each. A separate 20-listing detail run enriched all 20 records successfully. The deployed Apify build then passed a real cloud city-mode smoke test. These checks had no blocks, request retries, search failures, pagination stops, or city-validation failures.

Housing.com uses private frontend contracts that can change. The city catalog and GraphQL field selection are isolated so they can be updated without replacing the crawler architecture.

See [RESEARCH.md](./RESEARCH.md) for the technical investigation and [PARITY\_SPEC.md](./PARITY_SPEC.md) for the competitor-parity scope.

# Actor input Schema

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

Easy mode. Enter one or more supported cities: mumbai, bengaluru, hyderabad, pune, chennai, new-delhi, gurgaon, noida, kolkata, ahmedabad, thane, or navi-mumbai.

## `transactionTypes` (type: `array`):

Buy, rent, or both. Used with city mode; canonical URLs already contain their transaction type.

## `startUrls` (type: `array`):

Exact-search mode. One or more URLs matching /in/buy/searches/<HASH> or /rent/search-<HASH>. Leave cities empty when using URLs.

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

Maximum number of unique listings saved across every city or URL, after filters are applied.

## `minPrice` (type: `number`):

Optional minimum listing price in Indian rupees. Listings without a usable price are excluded when a price filter is active.

## `maxPrice` (type: `number`):

Optional maximum listing price in Indian rupees.

## `daysOld` (type: `integer`):

Optional listing-age filter. Listings without a parseable posted date are excluded when enabled.

## `maxPagesPerSearch` (type: `integer`):

Safety and cost cap for each city/transaction or canonical URL.

## `maxImages` (type: `integer`):

Limits property and floor-plan image URL arrays. Use 0 to omit image arrays while retaining the cover image.

## `enrichDetails` (type: `boolean`):

Make one additional request per matching listing for richer address, configuration, amenity, RERA, media, and seller fields.

## `includeRaw` (type: `boolean`):

Include parsed source objects under raw. This can significantly increase dataset size.

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

Optional Apify Proxy or custom proxy configuration. Indian residential fallback is attempted after blocks when available.

## `maxConcurrency` (type: `integer`):

Concurrent detail requests. Search pages remain sequential to protect pagination correctness.

## Actor input object example

```json
{
  "cities": [
    "bengaluru"
  ],
  "transactionTypes": [
    "buy",
    "rent"
  ],
  "maxItems": 100,
  "maxPagesPerSearch": 40,
  "maxImages": 6,
  "enrichDetails": false,
  "includeRaw": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxConcurrency": 2
}
```

# Actor output Schema

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

No description

## `runStats` (type: `string`):

No description

# 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 = {
    "cities": [
        "bengaluru"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("hermandev/housing-com-property-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 = { "cities": ["bengaluru"] }

# Run the Actor and wait for it to finish
run = client.actor("hermandev/housing-com-property-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 '{
  "cities": [
    "bengaluru"
  ]
}' |
apify call hermandev/housing-com-property-scraper --silent --output-dataset

```

## MCP server setup

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