PropertyGuru / DDProperty Scraper (SG · MY · TH)
Pricing
from $0.0007 / actor start
PropertyGuru / DDProperty Scraper (SG · MY · TH)
Scrapes property listings from PropertyGuru Singapore, PropertyGuru Malaysia and DDProperty Thailand — one actor, three SEA markets sharing one platform, 630,000+ listings. Filter by keyword, type, price, bedrooms and size; returns price, beds, baths, size, address, agent, photos and transit info.
Pricing
from $0.0007 / actor start
Rating
0.0
(0)
Developer
Ibnu Adzim
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Scrapes property listings from PropertyGuru Singapore, PropertyGuru Malaysia and DDProperty Thailand — Southeast Asia's largest property portal group, with over 630,000 listings across the three markets.
One actor, three markets. They run on the same platform, so results share an identical field shape and can be compared directly.
Public data only. No login, no cookies, no browser.
What you get
Two record types share one dataset, told apart by recordType.
PROPERTY — one row per listing
Search rows are already rich (48 fields): price with currency, bedrooms, bathrooms, floor area, full address, property type, agent and agency, photo carousel, listing features, posting date, and transit info (MRT/BTS proximity where the market has it).
Turn on Fetch full listing details for the complete description, full facility list, project data and agent contact — one extra request per listing.
SEARCH_SUMMARY — one row per market
Upstream's own match total, how deep the run paged, the filters you requested, and the platform's own echo of the filters it actually parsed.
Input
| Field | What it does |
|---|---|
| Markets | Thailand, Singapore, Malaysia — pick any combination |
| For sale / for rent | which side of the market |
| Keyword / location | district or project name: sukhumvit, orchard, mont kiara |
| Property type | Condo, Apartment, Bungalow, Semi-detached, Land |
| Min / max price | in each market's own currency (THB / SGD / MYR) |
| Bedrooms | minimum count |
| Minimum floor area | sqm in TH/MY, sqft in SG |
| Max listings per market | 0 = unlimited |
| Fetch full listing details | off by default — the search row is already detailed |
Example
{"markets": ["th", "sg", "my"],"listingType": "sale","propertyType": "CONDO","minPrice": 1000000,"bedrooms": 2,"maxItems": 500}
The thing this actor protects you from
Property-type codes are market-specific, and an unsupported one is silently
ignored. Ask for LAND in Thailand and you get 10,729 plots. Ask for LAND
in Singapore and you get all 57,647 listings — no error, no warning, just a
search that quietly wasn't filtered.
This actor checks the platform's own echo of what it parsed and tells you:
"filtersRequested": {"property_type_code": "LAND"},"propertyTypeApplied": false,"upstreamSearchParams": {"locale": "en", "listingType": "sale", "page": 1}
plus a warning in the log. When the filter does land, the echo proves it:
"upstreamSearchParams": {"propertyTypeGroup": "N", "propertyTypeCode": ["CONDO"],"minPrice": 1000000, "bedrooms": [2]}
| code | Thailand | Singapore | Malaysia |
|---|---|---|---|
| Condo / Apartment | ✅ | ✅ | ✅ |
| Bungalow / Semi-detached | ✅ | ✅ | ✅ |
| Land | ✅ | ✗ | ✗ |
| Terraced / HDB | ✗ | ✗ | ✗ |
Unsupported markets and impossible price ranges are refused before the first request rather than producing a healthy-looking wrong result.
Notes on reliability
- No bot challenge on search. All three hosts sit behind Cloudflare but serve data cold.
- Singapore requires a Referer header on paginated URLs (it answers 403 without one), as do Thai detail pages. The actor always sends the right one — you never see this.
- Runs unattended. No session, no token, nothing to refresh.
- Failures never vanish. A listing withdrawn mid-crawl degrades that one
row (
_detailError); every input maps to at least one output row. - Residential proxy by default on cloud runs.
Output envelope
Every record carries _input, _source and _scrapedAt. Upstream field names
pass through verbatim — no renaming. _source is S1-nextdata-search, or
S1-nextdata-search+S2-nextdata-detail once details are attached.
The market you searched is marketQueried (upstream's own fields are left
untouched).
See CRAWLING_METHOD.md for the full reverse-engineering trail — the shared-buildId proof, the Referer gate, and the per-market property-type matrix.