PropertyGuru Scraper - Singapore & Malaysia Listings avatar

PropertyGuru Scraper - Singapore & Malaysia Listings

Pricing

from $2.50 / 1,000 listings

Go to Apify Store
PropertyGuru Scraper - Singapore & Malaysia Listings

PropertyGuru Scraper - Singapore & Malaysia Listings

Collect sale and rental listings from PropertyGuru Singapore, PropertyGuru Malaysia and CommercialGuru. Export prices, property details and available agent contacts. Billed per delivered listing, plus a start fee.

Pricing

from $2.50 / 1,000 listings

Rating

0.0

(0)

Developer

kane liu

kane liu

Maintained by Community

Actor stats

1

Bookmarked

9

Total users

2

Monthly active users

6 hours ago

Last modified

Security

Limited permissions

Share

PropertyGuru Scraper

Collect PropertyGuru Singapore, PropertyGuru Malaysia and CommercialGuru Singapore listings as structured rows for export and analysis.

  • Sale and rental listings, including homes, rooms and commercial properties.
  • Asking prices, floor areas, room counts and listing URLs.
  • Property addresses, photos and available agent contacts.
  • Search by location, property category or a list of URLs.
  • Row charges cover listings delivered: $2.50 per 1,000 rows on the Free plan, plus a small start fee. Platform usage is separate.

What does PropertyGuru Scraper do?

PropertyGuru Scraper collects listings from propertyguru.com.sg, propertyguru.com.my and commercialguru.com.sg. Each row represents one property listing. Use the rows for market comparisons, inventory tracking or a property research spreadsheet.

  • URL inputs: give search or listing URLs in startUrls; the URL determines the market.
  • Location searches: fill location, then choose the market, sale or rent, and property types.
  • Market searches: choose a non-default market, channel or category without a location to search that market's default area.
  • Details: scrapeDetails is on by default. It adds available contact and property information to the same row, not separately billed rows.

Singapore supports HDB, condos, apartments, landed homes and room rentals. Malaysia supports condos, apartments, terrace houses, semi-detached houses, bungalows, townhouses and room rentals. CommercialGuru supports offices, retail, industrial property, warehouses and land. Rooms require channel: "RENT".

What data can you extract from PropertyGuru?

Fields depend on what the listing provides. These are listing rows, identified by recordType: "listing".

FieldDescriptionExample
idListing identifier12345678
urlListing linkhttps://www.propertyguru.com.sg/listing/12345678
marketSite marketSG, MY, CG
currencyListing currencySGD, MYR
channelSale or rentalBUY, RENT
categorySearch category, when knowncondo
propertyTypeProperty typehdb
titleListing headlineExample Residence
projectNameDevelopment nameExample Residence
priceNumeric asking price1500000
priceFormattedPrice with currencyS$1,500,000
pricePsfPrice per square foot, when available1500
bedroomsBedroom count3
bathroomsBathroom count2
floorAreaSqftFloor area in square feet1000
addressAddress object; parts may be empty{"street":"123 Example Street","country":"SG"}
geoCoordinates, when present{"lat":1.3,"lng":103.8}
districtDistrict value provided by the listingD09
tenureProperty tenureFreehold
builtYearYear built2020
agentNameAgent nameJane Doe
personAgent name and available role{"name":"Jane Doe","role":null}
orgAgency name and identifier{"name":"Example Agency","id":null}
phonesAvailable agent phone numbers[{"value":"+1 555 0100","type":"mobile"}]
imagesUp to 30 photo URLs[]
leadSourceSearch or detail informationdetail
leadAbsencesReasons for missing contact fields{"emails":"本站无"}
scrapedAtCollection timestamp2026-10-24T00:00:00+00:00

emails is currently an empty array. web contains website: null and an empty socials array. In leadAbsences, 本站无 means the field is not provided; 未验证 means it was not verified. These are output values, not instructions to contact the agent.

How to scrape PropertyGuru

  1. Open PropertyGuru Scraper in Apify Console. A free Apify account is enough to try it.
  2. Fill startUrls or location. Clear the sample URL if you want a location search.
  3. Set maxItems to 5 for a small first run.
  4. Click Start and wait for the run to finish.
  5. Download the dataset or read it through the API.

An empty input uses the form's Singapore condo search URL and requests at most 3 rows. Normal fees still apply. Filling a target field selects how to search automatically; there is no mode field to set.

URL inputs

Paste supported search or individual listing URLs into startUrls. URLs take precedence over location and market selections. Put search filters in the URL itself; separate location, price and bedroom filters do not rewrite supplied URLs. Singapore and CommercialGuru listing URLs use /listing/; Malaysia uses /property-listing/.

Location searches

Leave startUrls empty. Enter an area such as orchard or kuala-lumpur in location, select market, and choose channel and propertyType. propertyTypes overrides propertyType when non-empty.

Market searches without a location

Changing market, markets, channel or property types from their defaults starts a market search without the sample URL. Singapore and CommercialGuru default to Singapore; Malaysia defaults to Malaysia. Leaving all those settings at their defaults still selects the example run. Price, bedroom or district filters alone do not select a new target.

What to fill in

FieldWhat to enterDefault
startUrlsSearch or listing URLs, as strings or objects with urlSample URL in form
locationArea or city when no URLs are suppliedEmpty
marketSG, MY, CG, or allSG
marketsMultiple markets; also includes the single market selectionEmpty
channelBUY or RENTBUY
propertyTypeOne type, or all, residential, commercial, landedall
propertyTypesMultiple types, replacing propertyTypeEmpty
districtCodeDistrict filter for a generated search, such as D09Empty
minPriceMinimum price in the market currencyEmpty
maxPriceMaximum price, at least minPriceEmpty
bedroomsBedroom count, 0–20Empty
maxItemsRow limit per input, 1–50070; form sample 3
maxPagesNot a strict page limit in current Actor runs; use maxItems1
scrapeDetailsAdd available detail-page informationtrue
requestDelayMillisRequested navigation pause; not guaranteed between all requests2000

For a Malaysia-only search, use market: "MY". Setting only markets: ["MY"] also includes the default market: "SG". Set market to a member of markets to avoid adding another market.

Search URL:

{
"startUrls": [{"url": "https://www.propertyguru.com.sg/condo-for-sale?market=residential"}],
"maxItems": 5
}

Location search:

{
"location": "orchard",
"market": "SG",
"propertyType": "condo",
"maxItems": 5
}

Market search:

{
"market": "MY",
"channel": "RENT",
"propertyType": "condo",
"maxItems": 5
}
  • maxResults, limit and max_results are aliases of maxItems.
  • Close misspellings of field names can be corrected. Other unknown fields are ignored with a note, rather than failing the run.
  • Invalid filters may be ignored or normalized. Validation failures stop before rows are collected, with a message such as INVALID_INPUT: maxPrice — must be greater than or equal to minPrice. No row charge applies, but the start fee can still apply.
  • INPUT_REPORT in the run's key-value store records fields filled, corrected or ignored. Check it when the search differs from what you intended.

Output example

This illustrative row uses placeholder property and contact details, not a live listing.

{
"id": "12345678",
"url": "https://www.propertyguru.com.sg/listing/12345678",
"source": "propertyguru",
"market": "SG",
"currency": "SGD",
"channel": "BUY",
"recordType": "listing",
"category": "condo",
"propertyType": "condo",
"title": "Example Residence",
"price": 1500000,
"bedrooms": 3,
"bathrooms": 2,
"floorAreaSqft": 1000,
"address": {
"street": "123 Example Street",
"unit": null,
"locality": null,
"region": null,
"postalCode": null,
"country": "SG",
"full": "123 Example Street"
},
"agentName": "Jane Doe",
"phones": [{"value": "+1 555 0100", "type": "mobile"}],
"emails": [],
"web": {"website": null, "socials": []},
"leadSource": "detail",
"leadReveal": "visible",
"leadAbsences": {"emails": "本站无", "web": "本站无"},
"scrapedAt": "2026-10-24T00:00:00+00:00"
}

Export the dataset as JSON, CSV, Excel, XML, RSS or an HTML table. OUTPUT and RUN_SUMMARY in the key-value store contain run summaries, not extra listing rows.

Why use this PropertyGuru scraper?

  • Row-based charges: pay listing fees for rows delivered, not pages attempted.
  • Partial delivery: when collection stops early and returns usable rows, the Actor delivers those rows. A manual abort before delivery is not a guarantee of saved results.
  • Useful details: available contacts and property details remain in the listing row.
  • Missing data stays empty: contact fields are not invented.
  • Multiple inputs: collect several URLs or selections in one run.
  • No setup: you do not need to set up proxies or provide a PropertyGuru account.

How much does it cost to scrape PropertyGuru?

The Actor uses pay-per-event pricing. The start event costs $0.005, with one event per GB of run memory and a minimum of one event. At the default 512 MB, the start fee is $0.005.

Apify planPrice per rowPrice per 1,000 rows
Free$0.0025$2.50
Starter$0.0025$2.50
Scale$0.0025$2.50
Business$0.0025$2.50

These are Actor event fees. Platform usage is billed separately under this Actor's current pricing configuration; it is not included in the table.

maxItems defaults to 70 per input and accepts up to 500. Each start URL is an input. Without URLs, selected markets take precedence for counting inputs, followed by selected property types; scalar settings count as one input. Larger requests are collected in parts, subject to available listings.

The Free plan allows 10 runs of this Actor, with 200 rows total per run. Paid plans remove that trial run limit. Set Maximum cost per run (maxTotalChargeUsd in the API) to cap Actor event charges across all inputs, not just one search.

Example: one 512 MB run delivering 5 rows costs 5 × $0.0025 + $0.005 = $0.0175 in event fees, plus platform usage. Adding details does not create an additional row charge.

What happens when the run timeout is too short

A search can take longer than your chosen timeout. When automatic continuation is accepted, the run pauses with a status message beginning "Queued on the collection backend; this run will resume automatically when results are ready", followed by an estimated wait. It temporarily shows ABORTED.

Once results are ready, the same run resumes, reports "Resumed: delivering N rows.", writes to the same dataset and finishes SUCCEEDED if delivery succeeds. Previously delivered rows are tracked so continuation does not deliver or charge them twice. No manual restart is needed for this pause.

  • Automatic pauses are limited to 3 per run. Keep the default 3600-second timeout to reduce early pauses; it does not guarantee completion.
  • Synchronous API endpoints run-sync and run-sync-get-dataset-items wait at most 300 seconds and can return an empty dataset while a run is paused. Start longer runs asynchronously and read the dataset after SUCCEEDED, or use a succeeded-event webhook.

Use with AI agents and the API

Apify MCP server (Claude, ChatGPT, Cursor, VS Code)

Add this Actor to an MCP client that supports remote servers:

https://mcp.apify.com?tools=lentic_clockss/propertyguru-sg-scraper

Sign in with Apify using OAuth when prompted, or send Authorization: Bearer <YOUR_APIFY_TOKEN>. The tool starts a run and returns run and dataset IDs; the agent can then read rows with get-dataset-items.

Clients without remote support can use npx @apify/actors-mcp-server --tools lentic_clockss/propertyguru-sg-scraper with the APIFY_TOKEN environment variable.

Example prompt: "Collect up to 5 Singapore condo listings for sale in Orchard. Return prices, floor areas and listing URLs."

Apify API

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("lentic_clockss/propertyguru-sg-scraper").call(
run_input={"location": "orchard", "propertyType": "condo", "maxItems": 5}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('lentic_clockss/propertyguru-sg-scraper').call({
location: 'orchard', propertyType: 'condo', maxItems: 5
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

For asynchronous HTTP calls, send the input JSON to POST https://api.apify.com/v2/acts/lentic_clockss~propertyguru-sg-scraper/runs with Authorization: Bearer <YOUR_APIFY_TOKEN>. After completion, read GET https://api.apify.com/v2/datasets/<datasetId>/items?format=json.

Integrations

Use the Actor's Integrations tab to connect results to Google Sheets, Make, Zapier, n8n, Slack, Airtable or a webhook. Use Apify Schedules for regular runs.

FAQ

Public availability does not by itself grant permission for every use. Follow the site's terms and applicable data protection law. Processing personal data, including agent contacts, needs a lawful basis. Obtain legal advice if unsure.

Why did my run end as ABORTED?

The automatic-continuation message described above indicates a temporary pause. It is not the same as a manual abort. Check the status message before starting another run.

How many results can I get?

Request 1–500 rows per input with maxItems. Available inventory, your charge limit and the Free plan's 200-row total cap can reduce delivery. The requested count is not guaranteed.

Why are some fields empty?

Listings do not all provide the same details. Detail retrieval may also fail. Emails and agent websites are not collected; inspect leadAbsences for available reasons.

How do I collect HDB listings or rooms?

For HDB, set market: "SG" and propertyType: "hdb". For rooms, use propertyType: "room" and channel: "RENT" in Singapore or Malaysia.

How do I collect CommercialGuru offices?

Set market: "CG" and propertyType: "office". Choose BUY or RENT, and start with maxItems: 5.

Can I turn off detail collection?

Set scrapeDetails: false for mainly search-card information. Basic listing details may still be fetched when needed to produce a usable row. Do not expect agent phone numbers from search cards alone.

Why did a run return no rows?

The search may have no matching listings, or collection may have failed. Check the final status, RUN_SUMMARY and any ERROR_SUMMARY; try one known search URL before broadening the request.

Limitations

  • DDproperty, Rumah123 and Batdongsan are not supported.
  • Categories vary by market. all means supported primary categories, not every possible listing type.
  • This Actor collects current listings, not historical sales or transaction prices.
  • Emails, agent websites and social links are not supplied. Addresses and coordinates can be incomplete.
  • maxPages is not a strict cap in current Actor runs; use the row and cost limits instead.
  • Some searches return fewer rows than requested. Detail collection can take longer and still leave fields empty.

More real estate and property data scrapers from the same publisher:

Browse all of our scrapers at apify.com/lentic_clockss.

Support

Found a problem or need another field? Open an issue in the Issues tab of this Actor's page and include the run ID and the input you used.