# iProperty Scraper with Contacts| Enterprise Grade (`fatihtahta/iproperty-scraper`) Actor

Extract iProperty Malaysia listings at scale with rich property detail, agent contacts, project data, nearby places, and transaction history. Built for enterprise-grade Malaysia real estate intelligence, lead enrichment, and automated analytics pipelines.

- **URL**: https://apify.com/fatihtahta/iproperty-scraper.md
- **Developed by:** [Fatih Tahta](https://apify.com/fatihtahta) (community)
- **Categories:** Real estate, Agents, Automation
- **Stats:** 6 total users, 0 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 property listings

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?

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

## iProperty Scraper | Malaysia Real Estate

**Slug:** `fatihtahta/iproperty-scraper`

### Overview

iProperty Scraper collects structured Malaysia real estate listing records, including property details, prices, locations, layout attributes, media, agent details, agency information, project metadata, nearby places, and available transaction history. [iProperty Malaysia](https://www.iproperty.com.my) is a major public real estate marketplace for Malaysian sale and rental inventory, making its listing data valuable for market research, monitoring, lead qualification, and operational reporting. The actor turns matching public listings into repeatable JSON outputs that can be used by analytics systems, enrichment workflows, CRM processes, and data pipelines. It is designed for recurring data acquisition with consistent input controls, predictable output records, and practical limits for validation or larger collection runs.

### Why Use This Actor

- **Market research and analytics teams:** build structured extraction workflows for pricing, availability, location coverage, floor area, property category, and transaction-history analysis.
- **Product and content teams:** normalize public listing data for company catalogs, market pages, content audits, and property-comparison experiences.
- **Developers and data engineering teams:** feed downstream systems with repeatable JSON records suitable for ETL, warehouses, enrichment pipelines, and monitoring jobs.
- **Lead generation and enrichment teams:** collect public agent, agency, project, and contact fields when available for outreach-ready real estate intelligence.
- **Monitoring and competitive tracking teams:** run scheduled collection for market intelligence, category movement, recently posted listings, and operational reporting.

### Common Use Cases

- **Market intelligence:** monitor Malaysian sale and rental supply by location, price range, property type, floor area, and listing freshness.
- **Lead generation:** build targeted prospect lists from public property listings, agents, agencies, and available contact fields.
- **Competitive monitoring:** track changes in pricing, inventory, verified-agent listings, media richness, and category coverage over time.
- **Catalog and directory building:** populate private property, project, agent, or agency databases with structured public records.
- **Data enrichment:** add current public property attributes, media, location, nearby-place, and transaction-history fields to CRM, BI, or analytics datasets.
- **Recurring reporting:** schedule periodic runs for dashboards, alerts, valuation workflows, and historical trend analysis.

### Quick Start

1. Choose the listing mode with `deal_type`: `buy` for sale listings or `rent` for rental listings.
2. Enter one Malaysian `location`, such as a city, state, township, neighborhood, or market name.
3. Select a `property_type` and add optional filters such as price, area, bedroom count, amenities, listing freshness, or verified-agent status.
4. Set a small `limit` for the first validation run, such as 10 or 25 records.
5. Run the actor in Apify Console and inspect the first dataset records.
6. Increase the limit, adjust filters, or schedule recurring runs once the output matches your workflow.

### Input Parameters

The actor accepts one required Malaysian location plus optional listing mode, category, filter, enrichment, contact, transaction-history, and limit controls.

| Parameter | Type | Description | Default |
| --- | --- | --- | --- |
| `deal_type` | string | Listing segment to collect. Allowed values: `buy` for sale listings, `rent` for rental listings. | `buy` |
| `location` | string | Required Malaysian location, such as a city, state, township, neighborhood, or market name. | – |
| `property_type` | string | Property category filter. Allowed values: `all_residential`, `all_commercial`, `residential_bungalow_villa`, `residential_apartment_condo`, `residential_semi_detached_house`, `residential_terrace_link_house`, `residential_residential_land`, `commercial_commercial_property`, `commercial_industrial_property`, `commercial_agricultural_land`, `commercial_other`. | `all_residential` |
| `min_price` | integer | Minimum asking price in Malaysian ringgit (MYR). | – |
| `max_price` | integer | Maximum asking price in Malaysian ringgit (MYR). | – |
| `min_price_psf` | integer | Minimum price per square foot in MYR per sqft. | – |
| `max_price_psf` | integer | Maximum price per square foot in MYR per sqft. | – |
| `min_floor_area` | integer | Minimum built-up floor area in square feet. | – |
| `max_floor_area` | integer | Maximum built-up floor area in square feet. | – |
| `min_land_area` | integer | Minimum land area in square feet. | – |
| `max_land_area` | integer | Maximum land area in square feet. | – |
| `min_building_year` | integer | Earliest building completion year. Allowed range: 1977 to 2032. | – |
| `max_building_year` | integer | Latest building completion year. Allowed range: 1977 to 2032. | – |
| `bedroom` | array of strings | Bedroom counts to include. Allowed values: `studio`, `1`, `2`, `3`, `4`, `5+`. | – |
| `bathroom` | array of strings | Bathroom counts to include. Allowed values: `1`, `2`, `3`, `4`, `5+`. | – |
| `parking` | array of strings | Parking-space counts to include. Allowed values: `1`, `2`, `3`, `4`, `5+`. | – |
| `unit_type` | string | Unit layout or lot-position filter. Allowed values: `duplex`, `triplex`, `studio`, `corner_lot`, `intermediate`, `end_lot`, `loft`, `dual_key`, `soho`, `penthouse`. | – |
| `floor_level` | array of strings | Floor-level categories to include. Allowed values: `ground`, `low`, `mid`, `high`, `penthouse`. | – |
| `furnishing` | array of strings | Residential furnishing statuses to include. Allowed values: `unfurnished`, `partially_furnished`, `fully_furnished`. | – |
| `unit_amenities` | array of strings | Residential in-unit amenities to include. Allowed values: `aircon`, `balcony`, `bath_tub`, `corner_unit`, `helpers_room`, `private_pool`, `renovated`, `terrace`. | – |
| `building_amenities` | array of strings | Residential building amenities to include. Allowed values: `gym`, `parking`, `swimming_pool`, `tennis_court`. | – |
| `keyword` | string | Short keyword for a property, area, feature, or project term. | – |
| `publication_date` | string | Listing freshness window. Allowed values: `3_days`, `7_days`, `14_days`, `30_days`. | – |
| `with_video` | boolean | When enabled, collect only listings with video or virtual-tour media. | `false` |
| `tenure` | array of strings | Sale-listing tenure filter. Allowed values: `freehold`, `malay_reserved_land`, `private_lease_scheme`, `leasehold`, `bumi_lot`. | – |
| `verified_agent` | boolean | When enabled, collect only listings marked as coming from verified agents. | `false` |
| `enrich_data` | boolean | Adds richer listing details when available, including descriptions, listing dates, furnishing, facilities, nearby places, and extra media. | `true` |
| `get_contact` | boolean | Adds available agent phone and contact fields to saved records. | `true` |
| `get_transaction_history` | boolean | Adds available sale and rental transaction-history fields to saved records. | `true` |
| `limit` | integer | Maximum number of listings to save. Minimum: 1. Leave empty to collect available matching listings until the run naturally finishes. | – |

### Choosing Inputs

Use `location` as the primary scope control, then choose `deal_type` and `property_type` to define the market segment. Narrow filters such as price, price per square foot, area, bedroom count, amenities, tenure, listing freshness, and verified-agent status produce more targeted datasets; broader filters improve discovery and help identify available supply. For validation, start with a small `limit`, review the dataset shape, then increase the limit for recurring or broader collection. Use `enrich_data`, `get_contact`, and `get_transaction_history` when your workflow needs richer records; disable them when standard listing fields are sufficient and faster runs are preferred.

### Example Inputs

#### Example: Recently Posted Rental Monitoring

```json
{
  "deal_type": "rent",
  "location": "Bukit Bintang",
  "property_type": "residential_apartment_condo",
  "publication_date": "7_days",
  "verified_agent": true,
  "limit": 25
}
```

#### Example: Sale Market Price Band

```json
{
  "deal_type": "buy",
  "location": "Mont Kiara",
  "property_type": "all_residential",
  "min_price": 800000,
  "max_price": 1800000,
  "bedroom": ["2", "3"],
  "limit": 50
}
```

#### Example: Commercial Discovery With Enrichment

```json
{
  "deal_type": "buy",
  "location": "Johor Bahru",
  "property_type": "all_commercial",
  "min_floor_area": 1000,
  "enrich_data": true,
  "get_contact": true,
  "get_transaction_history": false,
  "limit": 30
}
```

### Output

#### Output destination

The actor writes normalized JSON records to the default Apify dataset. Each normal dataset item is a `property_listing` record for an iProperty.com.my listing.

#### Record envelope and stable identifiers

Use `record_id` as the primary idempotency key. It is a string and is based on the iProperty listing ID when the source provides one. The same value is also preserved as `listing.listing_id`, `entity.id`, `entity.external_ids.listing_id`, and `source_context.external_ids.listing_id` for source traceability.

Primary display and audit fields are easy to find:

- `entity.title`, `entity.url`, `entity.headline`, and `entity.description` describe the listing.
- `source_context.source_url`, `source_context.listing_url`, `source_context.seed_id`, `source_context.seed_type`, `source_context.seed_value`, and `source_context.page_index` describe where the record came from.
- `listing`, `pricing`, `location`, `property`, `availability`, `media`, `contact_details`, `relationships`, and `attributes` hold the normalized real estate data.

#### Example: property listing

```json
{
  "record_type": "property_listing",
  "record_id": "108113501",
  "entity": {
    "id": "108113501",
    "url": "https://www.iproperty.com.my/property/kl-city-centre/megan-avenue/sale-108113501/",
    "title": "Megan Avenue, KLCC, KL City Centre",
    "external_ids": {
      "listing_id": "108113501"
    }
  },
  "listing": {
    "listing_id": "108113501",
    "listing_type": {
      "label": "For Sale",
      "deal_type": "buy"
    },
    "deal_type": "buy",
    "status": {
      "code": "ACT"
    }
  },
  "pricing": {
    "price": 929760,
    "price_text": "RM 929,760",
    "currency": "MYR",
    "price_per_area": "RM 520.00 psf"
  },
  "location": {
    "address": "Jalan Mayang Sari, KLCC, KL City Centre, Kuala Lumpur"
  },
  "property": {
    "property_type": "Office",
    "bathrooms": {
      "label": "2"
    },
    "floor_area": {
      "formatted": "1,788 sqft"
    }
  },
  "media": {
    "images": [
      {
        "url": "https://img.iproperty.com.my/example.jpeg"
      }
    ],
    "image_count": 1
  },
  "contact_details": {
    "name": "Jocelyn Shu"
  },
  "relationships": {
    "agent": {
      "id": 1024341,
      "name": "Jocelyn Shu",
      "license": "REN 06297",
      "profile_url": "https://www.iproperty.com.my/property-agent/jocelyn-shu-1024341/"
    },
    "agency": {
      "id": 50602,
      "name": "The Roof Realty - Kuchai Lama"
    }
  },
  "source_context": {
    "source_name": "iProperty Malaysia",
    "source_domain": "www.iproperty.com.my",
    "source_url": "https://www.iproperty.com.my/_next/data/build/property-for-sale.json?page=1",
    "listing_url": "https://www.iproperty.com.my/property/kl-city-centre/megan-avenue/sale-108113501/",
    "seed_id": "51c163c5f04353dcccce",
    "seed_type": "search",
    "seed_value": "klcc",
    "page_index": 1,
    "external_ids": {
      "listing_id": "108113501"
    }
  }
}
```

#### Property listing record

**record\_type** *(string, required)*: Stable row discriminator. Normal listing rows use `property_listing`.
**record\_id** *(string, required)*: Stable listing idempotency key.

**entity.id** *(string, optional)*: Source listing ID.
**entity.url** *(string, optional)*: Public iProperty listing URL.
**entity.title** *(string, optional)*: Listing, project, or location title.
**entity.headline** *(string, optional)*: Short listing headline.
**entity.description** *(string, optional)*: Public listing description when detail enrichment exposes one.
**entity.external\_ids.listing\_id** *(string, optional)*: Source listing ID preserved as a source-specific external identifier.

**listing.listing\_id** *(string, optional)*: Source listing ID.
**listing.deal\_type** *(string, optional)*: Normalized deal type, such as `buy` or `rent`.
**listing.listing\_type.label / listing.listing\_type.code** *(string, optional)*: Human-readable listing segment and source segment code.
**listing.status.code** *(string, optional)*: Source listing status code.
**listing.status.source\_status\_code** *(string, optional)*: Secondary source status code when it differs from the main listing status code.
**listing.status.is\_verified** *(boolean, optional)*: Whether the listing is marked verified.
**listing.status.is\_official\_listing** *(boolean, optional)*: Whether the listing is marked as an official listing.
**listing.status.verification** *(object, optional)*: Additional source verification details.
**listing.dates** *(object, optional)*: Posted, recency, available, first-posted, last-posted, updated, content-updated, expiry, and source date details.

**pricing.price** *(number/string, optional)*: Listing price amount when safely available.
**pricing.price\_text** *(string, optional)*: Human-readable source price text.
**pricing.currency** *(string, optional)*: Currency code, typically `MYR`.
**pricing.price\_per\_area** *(string/object, optional)*: Price per unit area as source text or a structured range.
**pricing.price\_min / pricing.price\_max** *(number, optional)*: Minimum and maximum price values when represented as a range.
**pricing.price\_type** *(string/object, optional)*: Price-type label or structured source value.
**pricing.maintenance\_fee / pricing.maintenance\_fee\_per\_unit** *(number, optional)*: Maintenance fee details when available.

**location.address** *(string, optional)*: Full public address text.
**location.postal\_code** *(string, optional)*: Postal code as a string.
**location.street** *(string, optional)*: Street name.
**location.coordinates.latitude / location.coordinates.longitude** *(number, optional)*: Listing coordinates when available.

**property.property\_type** *(string, optional)*: Property type label.
**property.bedrooms / property.bathrooms** *(object, optional)*: Bedroom and bathroom labels plus numeric counts when available.
**property.floor\_area / property.land\_area** *(object, optional)*: Area value, display text, and unit.
**property.furnishing** *(object, optional)*: Furnishing label and source code.
**property.unit\_type / property.unit\_type\_details** *(string, optional)*: Unit type and lot-position detail.
**property.floor\_level** *(string, optional)*: Floor level label.
**property.rental\_type** *(string, optional)*: Rental scope, such as entire unit.
**property.tenancy** *(object, optional)*: Tenancy status details.
**property.is\_bumi\_lot** *(boolean, optional)*: Whether the listing is marked as Bumi lot.
**property.project\_id** *(string/integer, optional)*: Source project identifier.
**property.developer** *(string, optional)*: Developer or associated name when available.
**property.is\_new\_project / property.is\_premium\_project\_listing** *(boolean, optional)*: Project-related listing flags.

**availability.is\_available\_now** *(boolean, optional)*: Whether the listing is marked available now.
**availability.available\_from** *(string, optional)*: Availability date when exposed by the source.
**availability.tenancy** *(object, optional)*: Occupancy or tenancy context when available.

**media.cover\[] / media.floor\_plans\[] / media.images\[]** *(array, optional)*: Image objects with public media URLs and source media metadata such as IDs, captions, type, MIME type, cover flags, and sort order when available.
**media.has\_floor\_plans / media.has\_stream** *(boolean, optional)*: Source media flags.
**media.thumbnail\_url** *(string, optional)*: Thumbnail image URL.
**media.image\_count** *(integer, optional)*: Number of image objects represented by the record.

**contact\_details.name** *(string, optional)*: Primary contact display name.
**contact\_details.contacts\[]** *(array, optional)*: Contact values collected from listing, agent, organization, or contact enrichment data.

**relationships.agent** *(object, optional)*: Embedded agent details, including ID, name, license, profile URL, verification flags, awards, and agent-specific attributes.
**relationships.agency** *(object, optional)*: Embedded agency details.
**relationships.organization** *(object, optional)*: Embedded organization details.
**relationships.project** *(object, optional)*: Embedded project details, including IDs, type, tenure, facilities, category, property subtype, developer, floors, total units, and completion fields.

**attributes.nearby\_places** *(object, optional)*: Nearby MRT, school, mall, and other point-of-interest groups when detail enrichment exposes them.
**attributes.transaction\_history.sales / attributes.transaction\_history.rentals** *(object, optional)*: Sale and rental transaction-history counts, items, filter level, insight type, and source flags.
**attributes.source\_specific** *(object, optional)*: Remaining meaningful source-specific values such as external IDs, cross-listing type, co-broke flags, offering flags, title type, land title type, and other source fields that do not fit a stronger normalized group.

**source\_context.source\_name** *(string, optional)*: Source marketplace name.
**source\_context.source\_domain** *(string, optional)*: Source domain.
**source\_context.source\_url** *(string, optional)*: Source URL associated with the listing collection context.
**source\_context.listing\_url** *(string, optional)*: Public listing page URL.
**source\_context.detail\_url** *(string, optional)*: Detail-enrichment source URL when available.
**source\_context.seed\_id / source\_context.seed\_type / source\_context.seed\_value** *(string, optional)*: Run seed context for tracing the record back to the input scope.
**source\_context.page\_index** *(integer, optional)*: Source result page index.
**source\_context.external\_ids.listing\_id** *(string, optional)*: Source listing ID.
**source\_context.publishing\_source** *(object, optional)*: Source publishing metadata.
**source\_context.contact\_url** *(string, optional)*: Contact-source URL when contact enrichment is enabled.
**source\_context.transaction\_history\_urls.sales / source\_context.transaction\_history\_urls.rentals** *(string, optional)*: Transaction-history source URLs when transaction history is enabled.

### Data Quality, Guarantees, And Handling

- **Structured records:** results are normalized into predictable JSON objects for downstream use.
- **Best-effort extraction:** fields may vary by region, session, availability, listing type, or public interface changes.
- **Optional fields:** null-check optional fields in downstream code, especially contact details, media, nearby places, transaction history, and source-provided flags.
- **Deduplication:** use `record_id` as the primary stable key, with `entity.url` or `source_context.listing_url` as a secondary key when needed.
- **Freshness:** results reflect the publicly available data at run time.
- **Repeated runs:** use the recommended idempotency key when syncing data into warehouses, CRMs, or search indexes.

### Tips For Best Results

- Start with a small `limit` to validate the output shape before scaling up.
- Use one `location`, `deal_type`, and `property_type` combination per run when you need cleaner segmentation.
- Leave optional filters empty when the goal is broad discovery.
- Add price, area, room, amenity, freshness, and verified-agent filters gradually to understand how each field changes coverage.
- Enable `enrich_data`, `get_contact`, and `get_transaction_history` when richer records are required for analysis or outreach.
- Schedule recurring runs for monitoring workflows instead of relying on manual one-off collection.
- Use `id` for deduplication when storing results over time.

### How to Run on Apify

1. Open the actor in Apify Console.
2. Configure the available input fields for the target location, listing mode, category, filters, and enrichment options.
3. Set the maximum number of outputs to collect with `limit`.
4. Click **Start** and wait for the run to finish.
5. Open the dataset and download results in JSON, CSV, Excel, or other supported formats.

### Scheduling & Automation

#### Scheduling

**Automated Data Collection**

You can schedule runs to keep Malaysian real estate datasets fresh for reporting, monitoring, and enrichment workflows. Recurring runs are useful when you need consistent snapshots for the same location, category, or filter set.

- Navigate to **Schedules** in Apify Console
- Create a new schedule: daily, weekly, or custom cron
- Configure input parameters
- Enable notifications for run completion
- Add webhooks for automated processing

#### Integration Options

- **CRM enrichment:** sync public listing, agent, agency, contact, and property attributes into account or lead records.
- **BI dashboards:** monitor pricing, availability, location coverage, property categories, and transaction-history trends.
- **Google Sheets or Airtable:** review smaller listing datasets, qualification lists, and monitoring samples with non-technical teams.
- **Webhooks:** trigger validation, notification, or ingestion workflows after each completed run.
- **Data enrichment pipelines:** merge listing records with valuation, territory, or customer datasets.
- **Warehouses and ETL jobs:** load normalized JSON records into historical reporting and analytics systems.

### Export Formats And Downstream Use

Apify datasets can be exported or consumed by downstream systems for analytics, operations, and automation.

- **JSON:** for APIs, applications, and data pipelines
- **CSV or Excel:** for spreadsheet workflows and manual review
- **API access:** for automated ingestion into business systems
- **BI and warehouses:** for reporting, dashboards, and historical analysis

### Performance

Estimated run times:

- **Small runs (< 1,000 outputs):** ~3-5 minutes
- **Medium runs (1,000-5,000 outputs):** ~5-15 minutes
- **Large runs (5,000+ outputs):** ~15-30 minutes

Execution time varies based on filters, result volume, and how much information is returned per record. Highly filtered runs can finish faster, while broad discovery or detail-rich records may take longer.

### Limitations

- Availability depends on what <https://www.iproperty.com.my> publicly exposes at run time.
- Some optional fields may be missing on sparse listings, older listings, commercial records, or listings without public enrichment data.
- Very broad searches may take longer or require higher `limit` values to collect the desired coverage.
- Target-side changes can affect field availability, naming, or formatting.
- Regional, listing-type, account, or availability differences may change visible results.
- Contact and transaction-history fields are included only when available for the listing and enabled in the input.

### Troubleshooting

- **No results returned:** check filters, location or category spelling, and whether iProperty has matching public records for the selected scope.
- **Fewer results than expected:** broaden filters, raise `limit`, or verify that the target contains enough matching records.
- **Some fields are empty:** optional fields depend on what each public listing provides.
- **Run takes longer than expected:** reduce scope, lower `limit` for validation, or split broad collection into smaller location or category segments.
- **Output changed:** compare the current output with the field reference and include a small sample if support is needed.

### FAQ

#### What data does this actor collect?

It collects public iProperty Malaysia real estate listing data, including property details, prices, locations, layout fields, media, agent and agency details, project information, nearby places, and available transaction history.

#### Can I filter by location, category, date, price, or other criteria?

Yes. The schema supports `location`, `deal_type`, `property_type`, price range, price per square foot, floor area, land area, building year, room counts, parking, unit type, floor level, furnishing, amenities, keyword, publication date, tenure, video availability, and verified-agent status.

#### Why did I receive fewer results than my limit?

The selected filters may match fewer public listings than the requested `limit`. Broaden the location, category, price range, room filters, or freshness window to increase coverage.

#### Can I schedule recurring runs?

Yes. Use Apify schedules to run the actor daily, weekly, or on a custom cron pattern for recurring market monitoring and reporting.

#### How do I avoid duplicates across runs?

Use `record_id` as the primary idempotency key. If your destination system is URL-oriented, store `entity.url` or `source_context.listing_url` as a secondary deduplication key.

#### Can I export the data to CSV, Excel, or JSON?

Yes. Apify datasets support exports in JSON, CSV, Excel, and other supported formats from the dataset view.

#### Does this actor collect private data?

The actor is intended to collect publicly available listing information from iProperty Malaysia. Users are responsible for using any personal or contact information lawfully and responsibly.

#### What should I include when reporting an issue?

Include the input used, the run ID, expected versus actual behavior, and a small output sample when helpful. Redact any sensitive private notes before sharing.

### Compliance & Ethics

#### Responsible Data Collection

This actor collects publicly available Malaysia real estate listing information from <https://www.iproperty.com.my> for legitimate business purposes, including:

- **Real estate** research and market analysis
- **Lead qualification and enrichment**
- **Inventory monitoring and operational reporting**

This section is informational and not legal advice. Users are responsible for ensuring their use of collected data complies with applicable laws, regulations, and platform terms.

#### Best Practices

- Use collected data in accordance with applicable laws, regulations, and the target site’s terms
- Respect individual privacy and personal information
- Use data responsibly and avoid disruptive or excessive collection
- Do not use this actor for spamming, harassment, or other harmful purposes
- Follow relevant data protection requirements where applicable, including GDPR and CCPA

### Support

For help, use the actor page or Issues section. Include the input used, with sensitive values redacted if necessary, the run ID, expected versus actual behavior, and a small output sample when it helps explain the issue.

# Actor input Schema

## `deal_type` (type: `string`):

Select the marketplace segment to collect from. This choice shapes the listings returned and affects which sale-only filters, such as tenure, are useful.

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

Enter one Malaysian location, such as a city, state, township, neighborhood, or market. More specific locations produce a more targeted dataset, while broader locations can return a wider set of listings.

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

Collect only listings that match the selected property category. Commercial categories can make some residential-only filters irrelevant.

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

Collect only listings priced at or above this amount. Leave empty when you do not need a lower price boundary.

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

Collect only listings priced at or below this amount. Leave empty when you do not need an upper price boundary.

## `min_price_psf` (type: `integer`):

Collect only listings with a price per square foot at or above this amount. Leave empty when lower value-density filtering is not needed.

## `max_price_psf` (type: `integer`):

Collect only listings with a price per square foot at or below this amount. Leave empty when upper value-density filtering is not needed.

## `min_floor_area` (type: `integer`):

Collect only listings with at least this many square feet of floor area. Leave empty when you do not need a minimum built-up size.

## `max_floor_area` (type: `integer`):

Collect only listings with at most this many square feet of floor area. Leave empty when you do not need a maximum built-up size.

## `min_land_area` (type: `integer`):

Collect only listings with at least this many square feet of land area. Leave empty when you do not need a minimum land size.

## `max_land_area` (type: `integer`):

Collect only listings with at most this many square feet of land area. Leave empty when you do not need a maximum land size.

## `min_building_year` (type: `integer`):

Collect only listings completed in or after this year. Leave empty when you do not need an earliest completion year.

## `max_building_year` (type: `integer`):

Collect only listings completed in or before this year. Leave empty when you do not need a latest completion year.

## `bedroom` (type: `array`):

Collect only listings that match one of the selected bedroom counts. Leave empty to accept any bedroom count.

## `bathroom` (type: `array`):

Collect only listings that match one of the selected bathroom counts. Leave empty to accept any bathroom count.

## `parking` (type: `array`):

Collect only listings that match one of the selected parking-space counts. Leave empty to accept any parking count.

## `unit_type` (type: `string`):

Collect only listings matching this unit layout or lot-position type. Leave empty when unit type is not part of your selection criteria.

## `floor_level` (type: `array`):

Collect only listings matching one of the selected floor-level categories. Leave empty to include any floor level.

## `furnishing` (type: `array`):

Collect only residential listings matching one of the selected furnishing statuses. This filter does not apply to commercial property categories.

## `unit_amenities` (type: `array`):

Collect only residential listings that include one of the selected in-unit features. This filter does not apply to commercial property categories.

## `building_amenities` (type: `array`):

Collect only residential listings that include one of the selected building amenities. This filter does not apply to commercial property categories.

## `keyword` (type: `string`):

Collect only listings that match this keyword. Use a short property, area, feature, or project term; leave empty when location and filters are enough.

## `publication_date` (type: `string`):

Collect only listings posted within the selected time window. Use this when recent market activity matters more than older inventory.

## `with_video` (type: `boolean`):

Enable this to collect only listings that include video or virtual-tour media. This creates a narrower dataset focused on richer listing presentations.

## `tenure` (type: `array`):

Collect only sale listings matching one of the selected tenure values. Leasehold covers the available leasehold options for the selected property category; Bumi Lot applies only to residential categories.

## `verified_agent` (type: `boolean`):

Enable this to collect only listings marked as coming from verified agents. This narrows the dataset toward listings with an additional marketplace trust signal.

## `enrich_data` (type: `boolean`):

Enable this for more complete property listings, including descriptions, listing dates, furnishing, project facilities, nearby points of interest, and extra media when available. Turn it off for faster runs when the standard result fields are enough.

## `get_contact` (type: `boolean`):

Enable this to add available agent phone and contact fields to saved listing records. Leave disabled when you only need listing-level property data.

## `get_transaction_history` (type: `boolean`):

Enable this to add available sale and rental transaction history to saved listing records. This is useful for valuation, comparison, and market-research workflows.

## `limit` (type: `integer`):

Set the maximum number of listings to save for the location. Leave empty to keep collecting available matching listings until the run naturally finishes.

## Actor input object example

```json
{
  "deal_type": "buy",
  "location": "Bukit Bintang",
  "property_type": "all_residential",
  "with_video": false,
  "verified_agent": false,
  "enrich_data": true,
  "get_contact": true,
  "get_transaction_history": true,
  "limit": 100
}
```

# Actor output Schema

## `results` (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 = {
    "location": "Bukit Bintang",
    "limit": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("fatihtahta/iproperty-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 = {
    "location": "Bukit Bintang",
    "limit": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("fatihtahta/iproperty-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 '{
  "location": "Bukit Bintang",
  "limit": 100
}' |
apify call fatihtahta/iproperty-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fatihtahta/iproperty-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/lwt0IjBgS3neETWn9/builds/15RLeDjixee2G76u4/openapi.json
