PropertyGuru MY Scraper - Properties, Prices & Agents
Pricing
from $1.00 / 1,000 results
PropertyGuru MY Scraper - Properties, Prices & Agents
Scrape PropertyGuru.com.my sale and rental listings with 30+ structured fields, including MYR price, built-up area, tenure, nearby transit, property details, agent information and GPS coordinates. Fast and reliable at scale.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
14
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
PropertyGuru Malaysia Scraper: Sale & Rent Listings with Price, Coordinates & Agent Data
PropertyGuru Malaysia Scraper turns propertyguru.com.my into structured data. Get sale and rent listings with price in MYR, built up and land area, tenure, nearest transit, agent and agency details, and GPS coordinates. Search by state or free text location, filter by property type, price and bedrooms, or paste a search URL you already built in the browser, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.
Why This Scraper?
- Two ways to search. Pick a state or federal territory from the dropdown, or type a free text location like "Mont Kiara" or "Bukit Bintang". Paste your own propertyguru.com.my search URL instead if you need filters the built in fields don't cover.
- Condo, landed, commercial and land. Filter by property type on top of listing type (sale or rent), price range and bedroom count. "Landed" narrows to terrace houses only; for bungalows, semi-D or cluster homes, use URL mode instead.
- Detail page enrichment on demand. Turn on detail pages to add coordinates, full description, project name, total units, facilities, floor plans and nearby schools to every listing.
- Project level caching. For condos, the actor fetches one unit's detail page per project and reuses the shared project fields (facilities, coordinates, developer, total units) across every other unit in the same development, cutting the cost of condo heavy runs.
- All 13 states plus the 3 federal territories. A single dropdown covers every Malaysian state and federal territory, so state wide monitoring needs no manual URL building.
- Built for schedules. Incremental mode returns only new and changed listings on recurring runs, and a resume option continues one interrupted crawl without re paying for listings you already collected.
- Bounded access retries. If access is refused, the actor retries through its configured connections and reports a clear retryable failure when access remains blocked.
Use Cases
- Property portals and listing aggregators: pull structured MYR pricing, area and location data to power a search or comparison site.
- Investment and market research: track price per square foot, tenure and bedroom mix across states to spot undervalued areas.
- Lead generation for agents and agencies: collect agent names, licenses and contact details alongside the listings they represent.
- Recurring monitoring: schedule the actor on a saved search (a state, a project, a price band) and get only new, updated or reappeared listings on each run.
- Mapping and location apps: feed latitude and longitude, nearest transit and nearby schools into a map based property tool.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
id | 36124001 |
title | "Mont Kiara Pelangi" |
address | "Jalan Kiara, Mont Kiara, Kuala Lumpur" |
url | "https://www.propertyguru.com.my/property-listing/mont-kiara-pelangi-36124001" |
status | "active" |
listing_type | "sale" (also "rent") |
property_type | "Condo" (also "Landed", "Commercial") |
price / price_formatted | 680000 / "RM 680,000" |
currency | "MYR" |
price_psf | "RM 680 psf" |
bedrooms / bathrooms | 3 / 2 |
floor_area | 1000 |
land_area | 1800 (landed listings) |
tenure | "Freehold" |
state / region / city | "Kuala Lumpur" / "Mont Kiara" / "Kuala Lumpur" |
nearby_mrt | "5 min (450 m) to Sri Hartamas MRT" |
agent_name / agent_license | "Kevin Chai" / "PEA1234" |
agency_name | "ABC Realty Sdn Bhd" |
developer / is_developer_listing | "Sample Developer Bhd" / false |
posted_date / recency | "30 Jul 2026" / "Listed 8m ago" |
images / image_count | array of photo URLs / 8 |
latitude / longitude | 3.1698 / 101.6509 (with detail pages on) |
project_name / total_units | "Mont Kiara Pelangi" / 545 (with detail pages on) |
When detail pages are switched on, listings also carry description, headline, facilities, nearby_schools, floor_plans, unit_features, furnishing, unit_floor, virtual_tour_url, top_year, postal_code, reference_number, agent_mobile, agent_job_title and agency_license, all folded straight into the same listing record rather than a separate object. Fields the site does not expose for a given listing are simply left out of that record rather than filled with a placeholder.
A new-launch/project collection URL (see the URL mode table below) returns one row per development rather than per unit, so bedrooms/bathrooms on those rows are the project's full configuration range as text (e.g. "2, 3") rather than a single number, and price_formatted is often prose like "Price on ask" when the developer hasn't published a fixed price.
How to Use
- Choose Search mode (build a URL from state and filters) or URL mode (paste your own propertyguru.com.my search URLs).
- In search mode, pick listing type, property type, a state or a free text location, and any of price, bedrooms and sort.
- Turn on Fetch Detail Pages if you want coordinates, description, project facts and schools added to every listing.
- Set Max Properties and Max Pages to control run size and cost, then click Start.
All condos for sale in Kuala Lumpur:
{"mode": "search","listing_type": "sale","property_type": "condo","state": "kuala-lumpur","max_properties": 20,"max_pages": 5}
Rentals near a specific neighbourhood:
{"mode": "search","listing_type": "rent","search": "Mont Kiara","bedrooms": 3,"enable_detail_pages": true}
Terrace houses in Selangor under a price ceiling:
{"mode": "search","listing_type": "sale","property_type": "landed","state": "selangor","max_price": 1500000,"sort": "price","sort_order": "asc"}
A pre built search URL:
{"mode": "url","urls": ["https://www.propertyguru.com.my/condo-for-sale?freetext=Bangsar&bedrooms=3"],"max_pages": 10}
URL mode: every supported link shape
Paste any of these propertyguru.com.my URL shapes into urls. An unrecognized shape (for example,
there is no public per-agency profile page on this site) logs a loud warning in the run log instead of
silently returning 0 items.
| Shape | Example | What you get |
|---|---|---|
| Search results | /property-for-sale?freetext=Kuala+Lumpur | Every listing on the search, paginated |
| Category path | /condo-for-sale, /bungalow-for-rent, /shops-for-sale, /residential-land-for-sale | Same as search, scoped to that property type |
| Location path | /condo-for-sale/in-kuala-lumpur-58jok | Same as search, scoped to that city/region slug |
| Paginated start | /property-for-sale/2?freetext=Kuala+Lumpur | Resumes from page 2 onward (page 1 is never walked, so this scope can't confirm EXPIRED listings in incremental mode) |
| New launch / project collection | /new-property-launch?region_code=58jok | Every project card on the collection (project name, developer, price range, tenure) |
| Single listing detail | /property-listing/<slug>-<id> | That one listing, matched on its stable id |
| Project detail | /property-listing/project/<slug>-<id> | That one project, matched on its stable id |
| Agent profile | /agent/<slug>-<id> | Resolved to that agent's own active sale + rent listings |
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/propertyguru-my-scraper").call(run_input={"mode": "search","listing_type": "sale","state": "kuala-lumpur","max_properties": 20,})for listing in client.dataset(run["defaultDatasetId"]).iterate_items():print(listing["title"], listing["price_formatted"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/propertyguru-my-scraper').call({mode: 'search',listing_type: 'sale',state: 'kuala-lumpur',max_properties: 20,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one interrupted crawl. Paste its run or dataset ID and this run skips every listing ID already collected there, so you don't pay twice. - Incremental mode (
incrementalMode) is for scheduling the same search or URL setup repeatedly, for example daily. State is kept separately per search (mode, state, listing type, property type, bedrooms, price range, sort, or your own URLs), or share it deliberately with your ownstateKey. Each listing is classifiedNEW,UPDATED(withchangedFields),UNCHANGED(suppressed and not billed unlessemitUnchangedis on),REAPPEARED(a listing that was previously marked gone and is now found again) orEXPIRED.EXPIREDrows, gated behindemitExpired, are only produced once a run reaches the natural end of the tracked search, meaning it was not cut short by Max Properties, Max Pages, a blocked page, or a resumed run. If a run was capped or blocked before reaching the end, the previous state for those listings is left as is and noEXPIREDrows are emitted that run. With incremental mode off, output is exactly as a normal run.
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 listing, 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.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto 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 (build a URL from the filters below) or url (use provided URLs). |
urls | array | none (prefill: one sample Kuala Lumpur search URL) | Search or listing URLs to scrape. URL mode only; ignored in search mode. |
listing_type | string | sale | sale or rent. Search mode only. |
property_type | string | none | condo (condos and apartments), landed (terrace houses only), commercial (shop, office, factory), or land (residential land). For bungalows, semi-D or cluster homes, use URL mode. |
state | string | none | Malaysian state or federal territory. Use this or search, not both. |
search | string | none | Free text location, for example "Mont Kiara" or "Bangsar". Use this or state, not both. |
min_price | integer | none | Minimum price in MYR. |
max_price | integer | none | Maximum price in MYR. |
bedrooms | integer | none | Number of bedrooms (0 = studio). |
sort | string | date | Sort by date, price, or psf. |
sort_order | string | desc | asc or desc. |
enable_detail_pages | boolean | true | Fetch each listing's detail page for coordinates, description, project name, total units, facilities, floor plans and nearby schools. |
max_properties | integer | 10 | Maximum number of listings to scrape (0 = unlimited). |
max_pages | integer | 20 | Maximum number of search result pages to walk (20 listings per page). |
proxy | object | Apify Residential, Malaysia | Connection settings. Residential proxy in Malaysia is required because the site is geo restricted to Malaysian IPs. |
detail_concurrency | integer | 1 | Number of parallel detail page fetches. 1 to 3 is recommended. |
session_ttl_seconds | integer | 600 | How often the scraper refreshes its connection state. |
reuse_project_cache | boolean | true | Reuse cached project level fields (project name, total units, facilities, schools, coordinates, developer, tenure) across listings in the same condo project instead of fetching each one's detail 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 | Continue one interrupted run without re-collecting or re-charging listings already in it. |
incrementalMode | boolean | false | Track this same search, filter or URL setup run to run and return only NEW, UPDATED and REAPPEARED listings by default. |
stateKey | string | none | Name or share an incremental mode monitoring campaign. Left empty, the actor derives a key automatically from your search and filter settings. |
emitUnchanged | boolean | false | Incremental mode only. Also return, and bill, listings unchanged since the last run. |
emitExpired | boolean | false | Incremental mode only. Also return, and bill, listings no longer found, once a run fully scans the tracked search. |
mcpConnectors | array | none | Optional: send a summary of each listing to apps you authorized under Integrations. |
notionParentPageUrl | string | none | Notion connector only: page under which listings 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.
{"id": 36124001,"title": "Mont Kiara Pelangi","address": "Jalan Kiara, Mont Kiara, Kuala Lumpur","listing_type": "sale","property_type": "Condo","price": 680000,"price_formatted": "RM 680,000","currency": "MYR","price_psf": "RM 680 psf","bedrooms": 3,"bathrooms": 2,"floor_area": 1000,"tenure": "Freehold","state": "Kuala Lumpur","city": "Kuala Lumpur","nearby_mrt": "5 min (450 m) to Sri Hartamas MRT","agent_name": "Kevin Chai","agent_license": "PEA1234","agency_name": "ABC Realty Sdn Bhd","posted_date": "30 Jul 2026","images": ["https://my1-cdn.pgimgs.com/listing/36124001/UPHO.157827896.V800/a.jpg"],"image_count": 8,"url": "https://www.propertyguru.com.my/property-listing/mont-kiara-pelangi-36124001","status": "active","latitude": 3.1698,"longitude": 101.6509,"project_name": "Mont Kiara Pelangi","total_units": 545,"facilities": ["Swimming Pool", "Gymnasium", "24-hour Security"]}
Plan Requirement
The default proxy setting (Apify Residential, Malaysia) works out of the box, since propertyguru.com.my is geo restricted to Malaysian IPs and needs a Malaysian residential connection either way. The actor uses bounded access retries. If all configured connection attempts are blocked, the run fails with a retry message and preserves any results already collected. Check the Pricing tab for the current rates.
FAQ
How much does it cost?
You pay per listing returned, with detail page enrichment billed only for listings whose detail page was actually fetched. The Pricing tab shows the current rates. Use Max Properties and Max Pages to cap the cost of any run.
Is it legal to scrape PropertyGuru?
This actor collects only publicly available property listing data. You are responsible for how you use it: follow PropertyGuru's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing facts such as price and area are generally not protected, but photos and some descriptive text may be subject to third party rights.
Can I get only new or changed listings on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared listings, and unchanged ones are not billed unless you turn on Emit unchanged listings.
Why does incremental mode sometimes return nothing?
If nothing changed since the last run, that is the expected result: incremental mode suppresses UNCHANGED listings by default, so a quiet run legitimately returns zero rows while still recording that it scanned everything.
Why did my run fail or return nothing?
If the site refuses access, the actor uses its bounded access retries and then stops with a clear "please retry" message if access remains blocked. Run it again in a few minutes. A resumeFromRunId value that does not point to a valid run or dataset in your account also fails the run immediately, before anything is scraped or charged.
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 PropertyGuru data?
Pair this actor with these related scrapers from the same team:
| 🏠 PropertyGuru SG Scraper From $0.80/1K. Scrape PropertyGuru.com.sg sale and rental listings with 30+ structured... | 🏠 iProperty MY Scraper Scrape property listings from iProperty.com.my for sale or rent: price, PSF, bedrooms... |
| 🏠 DDproperty Thailand Scraper Scrape DDproperty.com Thailand listings at scale. Extract prices, property features... | 🏷️ Mudah.my Cars, Property, Jobs & Marketplace Scraper Scrape Mudah.my listings across every category: cars, motorcycles, property, mobiles... |
| 🏠 591.com.tw Scraper Extract property listings from 591房屋交易網 591.com.tw, Taiwan’s largest real estate... | 🏨 Hipflat Scraper Thailand Property & Projects Scrape hipflat.co.th property listings and new-project data across Thailand: price, price... |
💬 Support
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. 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.