PropertyGuru Scraper - Singapore & Malaysia Listings
Pricing
from $2.50 / 1,000 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
Maintained by CommunityActor stats
1
Bookmarked
9
Total users
2
Monthly active users
6 hours ago
Last modified
Categories
Security
Limited permissionsShare
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:
scrapeDetailsis 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".
| Field | Description | Example |
|---|---|---|
id | Listing identifier | 12345678 |
url | Listing link | https://www.propertyguru.com.sg/listing/12345678 |
market | Site market | SG, MY, CG |
currency | Listing currency | SGD, MYR |
channel | Sale or rental | BUY, RENT |
category | Search category, when known | condo |
propertyType | Property type | hdb |
title | Listing headline | Example Residence |
projectName | Development name | Example Residence |
price | Numeric asking price | 1500000 |
priceFormatted | Price with currency | S$1,500,000 |
pricePsf | Price per square foot, when available | 1500 |
bedrooms | Bedroom count | 3 |
bathrooms | Bathroom count | 2 |
floorAreaSqft | Floor area in square feet | 1000 |
address | Address object; parts may be empty | {"street":"123 Example Street","country":"SG"} |
geo | Coordinates, when present | {"lat":1.3,"lng":103.8} |
district | District value provided by the listing | D09 |
tenure | Property tenure | Freehold |
builtYear | Year built | 2020 |
agentName | Agent name | Jane Doe |
person | Agent name and available role | {"name":"Jane Doe","role":null} |
org | Agency name and identifier | {"name":"Example Agency","id":null} |
phones | Available agent phone numbers | [{"value":"+1 555 0100","type":"mobile"}] |
images | Up to 30 photo URLs | [] |
leadSource | Search or detail information | detail |
leadAbsences | Reasons for missing contact fields | {"emails":"本站无"} |
scrapedAt | Collection timestamp | 2026-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
- Open PropertyGuru Scraper in Apify Console. A free Apify account is enough to try it.
- Fill
startUrlsorlocation. Clear the sample URL if you want a location search. - Set
maxItemsto5for a small first run. - Click Start and wait for the run to finish.
- 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
| Field | What to enter | Default |
|---|---|---|
startUrls | Search or listing URLs, as strings or objects with url | Sample URL in form |
location | Area or city when no URLs are supplied | Empty |
market | SG, MY, CG, or all | SG |
markets | Multiple markets; also includes the single market selection | Empty |
channel | BUY or RENT | BUY |
propertyType | One type, or all, residential, commercial, landed | all |
propertyTypes | Multiple types, replacing propertyType | Empty |
districtCode | District filter for a generated search, such as D09 | Empty |
minPrice | Minimum price in the market currency | Empty |
maxPrice | Maximum price, at least minPrice | Empty |
bedrooms | Bedroom count, 0–20 | Empty |
maxItems | Row limit per input, 1–500 | 70; form sample 3 |
maxPages | Not a strict page limit in current Actor runs; use maxItems | 1 |
scrapeDetails | Add available detail-page information | true |
requestDelayMillis | Requested navigation pause; not guaranteed between all requests | 2000 |
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,limitandmax_resultsare aliases ofmaxItems.- 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_REPORTin 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 plan | Price per row | Price 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-syncandrun-sync-get-dataset-itemswait 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 ApifyClientclient = 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
Is it legal to scrape PropertyGuru?
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.
allmeans 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.
maxPagesis 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.
Related scrapers
More real estate and property data scrapers from the same publisher:
- Zumper Scraper
- Booli Scraper
- Craigslist Scraper
- OpenSooq Scraper
- Apartments.com Rental Scraper
- Dot Property Scraper
- FINN.no Scraper
- Immobiliare.it Scraper
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.