PropertyGuru Scraper [Only $0.85/1K💰] | SG/MY/TH | PSF | MRT avatar

PropertyGuru Scraper [Only $0.85/1K💰] | SG/MY/TH | PSF | MRT

Pricing

from $0.83 / 1,000 results

Go to Apify Store
PropertyGuru Scraper [Only $0.85/1K💰] | SG/MY/TH | PSF | MRT

PropertyGuru Scraper [Only $0.85/1K💰] | SG/MY/TH | PSF | MRT

Scrape property listings from PropertyGuru Group portals — propertyguru.com.sg, propertyguru.com.my and ddproperty.com — with price, PSF, beds/baths, floor and land area, tenure, MRT proximity, agent details and photos. No browser — reads the sites' own JSON. $0.00085 per listing.

Pricing

from $0.83 / 1,000 results

Rating

0.0

(0)

Developer

Ahmed Jasarevic

Ahmed Jasarevic

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

6 days ago

Last modified

Categories

Share

Propertyguru Scraper

Scrape property listings from PropertyGuru Group's Southeast Asia portals — propertyguru.com.sg (Singapore), propertyguru.com.my (Malaysia) and ddproperty.com (Thailand) — with price, PSF, beds/baths, floor and land area, tenure, MRT proximity, agent details, photos, description and coordinates. Sale and rent listings from all three markets merge into one dataset, at $0.00085 per listing — and it works against Cloudflare-protected portals without a browser, reading the JSON each site already embeds in its own pages.

Built for SE Asia proptech teams, buyer agents, mortgage brokers, expat relocation services and price-trend researchers.

Main Use Cases

  • Singapore property data — build a clean database of SG sale and rental listings with price, PSF, tenure and MRT proximity
  • Thailand real estate data — Thai listings via ddproperty, with Thai titles and prices returned as correct Unicode
  • Malaysia property listings — KL-area condos, landed homes and new launches with agent and agency data
  • Property price monitoring — scheduled runs track price changes, new listings and delistings per district or project
  • Agent lead generation — collect agent name, agency, CEA licence number and profile URL for outreach
  • HDB resale and condo research — filter by property type (CONDO, HDB, LANDED, APARTMENT, COMMERCIAL) and district

How It Works — No Browser, Reads the Sites' Own JSON

PropertyGuru portals are Next.js SSR sites: every page embeds its data as a JSON blob in a <script id="__NEXT_DATA__"> tag. The actor fetches the page HTML over plain HTTP and parses that embedded JSON directly — no browser, no DOM scraping, no JavaScript execution, roughly ~10x cheaper than a Playwright actor. A pasted listing URL on the Singapore or Malaysia portal goes one step further and is read from the portal's own JSON listing endpoint — a few KB instead of the ~58 KB detail page, about 9x less residential proxy traffic per row — with the HTML page kept as an automatic fallback.

The one thing that makes it work: Cloudflare blocks requests that look like plain Node. The actor impersonates a real browser's TLS and HTTP/2 fingerprint at the transport layer (impit). The measured evidence, from an A/B test against a live MY listing page on the same residential proxy pool:

TransportRequests passed
Node / Crawlee default TLS signature1 of 6
Browser fingerprint impersonation6 of 6

Every failure under the default signature was a Cloudflare managed challenge (__cf_chl) — a response to how the request looks on the wire, not a puzzle to solve. No JavaScript was ever executed in either arm.

Both search pages and single-listing detail pages are supported. The actor reads the result pages — one request per ~20 listings — so a run of any size stays cheap and fast; paste individual listing URLs to read that specific listing. Singapore and Malaysia URLs are fetched from the portal's own JSON listing endpoint (a few KB per row), while Thailand and any lookup that fails fall back to the listing's HTML page. Either way you get the detail-only fields (coordinates on every portal, land area, description, full gallery). Blocks are handled by rotating residential IPs (up to 12 attempts per request, paced across a ~7-minute window). Each portal draws from a small pool of exit IPs (three by default) and each individual IP is spaced 1s apart by default (requestDelayMs, raise it to 2000 for the more conservative pacing), so a run goes several times faster than a single IP would allow without any one IP being hit harder — the same per-IP politeness, just more IPs.

Build a Southeast Asia Property Database Without the PropertyGuru API

There is no documented PropertyGuru listing API. The route widely documented in the wild (/api/v10/web/search/listings) belongs to 99.co, a competitor of PropertyGuru — it does not exist on these domains, and the published mobile-app endpoints are third-party reverse-engineering that existing scrapers only reach after launching a browser to clear Cloudflare. What does work is exactly what PropertyGuru serves its own pages: the SSR __NEXT_DATA__ blob, and — for Singapore and Malaysia listing URLs — the portals' own JSON listing endpoint (/api/consumer/agent-profile/listing-by-id), read over plain HTTP with TLS impersonation and no browser at all. That is the cheapest way to get structured property data for Singapore, Malaysia and Thailand — while SG-only competitors on the Store cover just one market.

Coordinates: detail pages publish lat/lng for all three portals; the search surface exposes coordinates only for Singapore (map-search). Paste individual listing URLs to get detail-page coordinates everywhere. Thai text: ddproperty sends an incorrect charset in Content-Type; the actor pins UTF-8 decoding so Thai titles, prices and agent names come back correct (before the fix, prices read as mojibake like a++ 3,950,000).

Input

FieldTypeRequiredDefaultNotes
countriesarrayNo["th"]Portals to scrape: Thailand (ddproperty.com), Singapore (propertyguru.com.sg), Malaysia (propertyguru.com.my) — combine several in one run, results merge
startUrlsarrayNo[]Exact URLs to scrape (result pages or single listings, any of the three portals, mixed freely). Overrides countries and all filters below
listingTypeenumNosalesale or rent
freetextstringNo""Location / district / MRT / project search text, e.g. Orchard, Mont Kiara
propertyTypeenumNo""CONDO, HDB, LANDED, APARTMENT, COMMERCIAL
minPrice / maxPriceintegerNo0Price range in local currency (SGD / MYR / THB); 0 = no bound
bedroomsintegerNo-1Exact bedroom count (0 = studio, -1 = any)
useMapSearchbooleanNofalseSingapore only: return lat/lng for every listing via the map-search surface
maxItemsintegerNo50Max listings for the whole run (split evenly across selected portals); the run fetches as many pages as needed to reach it
requestDelayMsintegerNo1000Gap between requests from the same exit IP; each portal uses a small pool of IPs, so lower is faster but blocks sooner
maxBlockRetriesintegerNo12Retries for a blocked request on a freshly rotated IP
blockRetryBudgetSecsintegerNo420Total seconds one blocked page may wait between retries
proxyobjectNoRESIDENTIALEvery portal sits behind Cloudflare; each selected portal gets a geo-matched exit IP automatically

A pasted URL wins over the Portals dropdown — a .com.sg link scrapes Singapore even if Thailand is selected, and the run logs which portals went unused so the override is never silent. maxItems is a total for the run, split evenly between selected portals.

Output — Property Listing Records for Market Research

One dataset item per listing. Search-surface rows include:

FieldDescription
id, title, urlListing identity and direct detail URL
price, priceMin, priceMax, pricePretty, currency, priceQualifierPrice in local currency; range bounds for new-build projects; "Price on Ask" qualifier when no figure exists
pricePsfPrice per square foot, when published
floorArea, floorAreaValue, landArea, landAreaValueAreas as published and as bare numbers (land on detail pages; key for Thai listings)
bedrooms, bathrooms, tenure, buildYearRoom counts, freehold/leasehold code (F, L99), completion year
propertyType, propertyTypeCode, projectIdCondo/HDB/Landed/Apartment/Commercial + portal code + project grouping
fullAddress, shortAddress, districtCode, districtText, regionText, areaText, nearestMrtLocation tiers; Thai-only subdistrict; nearest MRT/BTS with distance (Singapore)
description, features, photoCount, imagesListing text, amenity tags, photo count and URLs
agentName, agentId, agentLicense, agentProfileUrl, agentVerifiedAgent identity, CEA registration, profile link
agencyName, agencyIdAgency identity
latitude, longitudeCoordinates on detail pages for every portal; SG map-search on the search surface
postedOn, updatedOn, recencyTextFirst-posted vs last-changed dates (an edited listing is not "new")
statusCode, isProjectListing, isPremiumProjectListing, projectListingSubType, isVerified, isOfficialListing, isDeveloperListingListing provenance flags. isProjectListing comes from the page; Singapore and Malaysia detail rows carry the endpoint's own isPremiumProjectListing and projectListingSubType instead
sourcePageUrlThe page the row came from

Example Input

{
"countries": ["sg", "my"],
"listingType": "sale",
"propertyType": "CONDO",
"freetext": "Mont Kiara",
"minPrice": 500000,
"maxItems": 200
}

Or paste URLs straight from the browser (single listing or a filtered result page, any portal):

{
"startUrls": [{ "url": "https://www.ddproperty.com/en/property/single-house-in-sriwilai-for-sale-10800011" }],
"maxItems": 10
}

Example Output — Listing Record (trimmed)

{
"id": 500249916,
"title": "The Tapestry",
"url": "https://www.propertyguru.com.sg/listing/for-sale-the-tapestry-50024991",
"country": "sg",
"portal": "propertyguru.com.sg",
"listingType": "sale",
"price": 860000,
"pricePretty": "S$ 860,000",
"currency": "SGD",
"pricePsf": "S$ 1,814.35 psf",
"floorArea": "474 sqft",
"bedrooms": 1,
"bathrooms": 1,
"tenure": "L99",
"buildYear": 2021,
"propertyType": "Condominium",
"fullAddress": "61 Tampines Street 86, Pasir Ris / Tampines",
"districtText": "Pasir Ris / Tampines",
"regionText": "Changi / Pasir Ris (D17-18)",
"nearestMrt": null,
"description": "High Floor Spacious 1 Bedder Plus Study with a Dual Pool View !",
"features": ["Pool", "Gym", "Security", "Aircon", "Balcony"],
"photoCount": 24,
"agentName": "Alton Nah",
"agentLicense": "R074064A",
"agencyName": "PROPNEX REALTY PTE. LTD.",
"latitude": null,
"longitude": null,
"postedOn": "26 Sep 2026",
"recencyText": "Listed on Sep 26, 2026 (3h ago)",
"isOfficialListing": true,
"sourcePageUrl": "https://www.propertyguru.com.sg/property-for-sale?isCommercial=false&listingType=sale&locale=en"
}

Detail-page rows (from pasted single-listing URLs) additionally carry landArea, latitude/longitude for every portal, the full image gallery, and both postedOn and updatedOn. On Singapore and Malaysia these rows are built from the portal's JSON listing endpoint; Thailand — and any Singapore/Malaysia lookup that fails — is built from the HTML page.

SE Asia Property Listings at $0.00085 Per Listing

The actor bills $0.00085 per listing (Apify's apify-default-dataset-item) plus the standard $0.00005 actor start. Listings read from a pasted single-listing ("detail") URL additionally carry a detail-listing event — charged once per row. Scraping by detail URL costs one request and one result per listing, whereas a search result page returns 20-30 listings from a single request, so runs that feed search, MRT or district URLs stay at the flat per-result rate and only pasted listing URLs pay the surcharge. The actor uses 256 MB memory, fetches only as many result pages as maxItems needs, and de-duplicates by listing ID so overlapping result pages never duplicate rows. Proxy cost (RESIDENTIAL, geo-matched) is billed separately by Apify by data transfer; free accounts get a preview, paid plans run to your caps.

Integrations & Automation

  • API — run and fetch via the Apify REST API, or call it from AI agents through the Apify MCP server
  • Scheduling — daily/weekly runs for price-change tracking per district or project
  • Webhooks — push new listings or price drops to your app, Sheets or Slack
  • Export — JSON, CSV, Excel, HTML

Recommended schedule: daily for price monitoring and new-listing alerts; weekly for full-market database refreshes and research datasets.

This actor is the only one in the set covering all three portals (SG + MY + TH) in a single run with a no-browser transport, at $0.00085/listing.

FAQ

Why use this actor instead of the official PropertyGuru API?

There is no documented public PropertyGuru listing API. The /api/v10/web/search/listings route often cited in tutorials belongs to 99.co, a PropertyGuru competitor, and does not exist on these domains. This actor reads the same JSON PropertyGuru renders server-side to its own pages — the __NEXT_DATA__ blob on search and Thai listing pages, and the portals' own listing endpoint for Singapore and Malaysia listing URLs.

What are alternatives to this actor for Southeast Asia property data?

SG-focused Store actors: shahidirfan/propertyguru-scraper, abotapi/propertyguru-sg-scraper, lentic_clockss/propertyguru-sg-scraper. Off-Store, 99.co operates its own competing portal in Singapore. Ours is the only no-browser actor covering SG, MY and TH.

Why is my run returning an empty dataset?

Nearly always Cloudflare blocking — the actor logs the exact cause. The default RESIDENTIAL proxy with geo-matched country is essential (datacenter IPs get challenge pages, not listings). Check proxy is on, then wait and re-run: exhausted residential IPs turn over in minutes, and blockRetryBudgetSecs (default 420s) rides that out automatically.

Why not just use a browser?

A JS challenge is a reaction to how a request looks on the wire, so a browser-accurate TLS/HTTP2 fingerprint satisfies it without executing anything — the A/B above measured 1/6 vs 6/6. A browser also changes the cost profile by ~an order of magnitude (hundreds of MB RAM and seconds per page vs a few KB and a couple of seconds), which defeats the reason to use this actor at all.

Why are coordinates null in my run?

Coordinates are published on detail pages for all three portals; on the search surface only Singapore returns them, and only when you enable map-search. A plain search run returning null lat/lng is by design, not missing data — paste individual listing URLs to get detail-page rows with coordinates, land area and the full gallery.

Why is a price missing on some listings?

New-build projects are advertised as a range ("RM 1,300,000 - RM 1,500,000") or as "Price on Ask". The range lands in priceMin/priceMax; "Price on Ask" leaves price as null (never a misleading 0) with priceQualifier recording the case. tenure holds only the freehold/leasehold code (F, L99), not a full lease-length statement.

Can I scrape by district or MRT station?

Yes — freetext accepts areas, districts, MRT/BTS stations and project names (e.g. Orchard, Tampines, Mont Kiara); nearestMrt comes back for Singapore listings. For complex filters, the most reliable path is building the URL in your browser and pasting it into startUrls.

For AI Agents & LLM Apps

  • Purpose: given portals, filters or direct URLs, returns one structured row per property listing (price, PSF, rooms, tenure, location tiers, MRT, agent, photos, coordinates on detail pages) from PropertyGuru's SG/MY/TH portals.
  • Minimal working input:
{ "countries": ["sg"], "listingType": "sale", "maxItems": 50 }
  • Variant inputs — direct URL: { "startUrls": [{ "url": "https://www.propertyguru.com.sg/listing/..." }] }; rent: { "countries": ["my"], "listingType": "rent", "freetext": "Mont Kiara", "maxItems": 100 }.
  • Output fields: id, title, url, country, portal, listingType, price, priceMin, priceMax, pricePretty, priceQualifier, currency, pricePsf, floorArea, floorAreaValue, landArea, landAreaValue, bedrooms, bathrooms, tenure, buildYear, propertyType, propertyTypeCode, projectId, fullAddress, shortAddress, districtCode, districtText, regionText, areaText, nearestMrt, description, features, photoCount, images, agentName, agentId, agentLicense, agentProfileUrl, agentAvatar, agentVerified, agencyName, agencyId, latitude, longitude, postedOn, postedUnix, updatedOn, updatedUnix, recencyText, statusCode, isProjectListing, isVerified, isOfficialListing, isDeveloperListing, isPreLaunched, sourcePageUrl.
  • Behaviors an agent should know: all three portals sit behind Cloudflare — keep the default RESIDENTIAL proxy with geo-matched countries; datacenter IPs yield empty runs. startUrls overrides countries and every filter. maxItems is split evenly between selected portals. Rows from pasted listing URLs carry land area and lat/lng for every portal; plain search rows return null coordinates except SG map-search. tenure is a code (F, L99), not a full statement; agentLicense is null for Thailand. price is null (with priceQualifier: "Price on Ask") when no figure exists — do not retry such listings seeking a price. postedOn is first-posted; updatedOn records edits and must not be treated as a new listing. Thai text is already UTF-8 correct. A run that returns nothing while pages load is Cloudflare — wait and retry, widening blockRetryBudgetSecs first.
  • Billing: pay-per-result — $0.00085 per listing + standard $0.00005 actor start; listings read from pasted single-listing URLs add a detail-listing event per row; residential proxy traffic billed separately by Apify.

This actor is an independent tool and is not affiliated with, endorsed by, or sponsored by PropertyGuru Group, PropertyGuru Pte Ltd, DDproperty, or any of their affiliates. It reads only publicly available data that PropertyGuru's portals render server-side to anonymous visitors — it does not log in, bypass paywalls, solve CAPTCHAs, or access private or personal data beyond what the portals publish on listing pages (agent names and agency details are published by the portals themselves). Users are responsible for their own compliance with each portal's Terms of Service, robots.txt and applicable law; the actor is intended for legitimate market research, price monitoring and competitive analysis. Scraping publicly available data may nevertheless violate PropertyGuru's Terms of Service — use responsibly and at low request rates.

SEO Keywords

propertyguru scraper, singapore property data, malaysia property listings, thailand real estate data, ddproperty scraper, sg property for sale, hdb resale data, condo price psf, propertyguru api alternative, southeast asia property, rental market data, property listing database, mrt station property, freehold leasehold data, bangkok property listings, kuala lumpur property, singapore condo rental, property price monitoring, agent lead generation, property market research