# PropertyGuru Singapore Property Listings (`data_dino/propertyguru-sg-scraper`) Actor

💰 $1.00 per 1000 results❗ Find structured PropertyGuru Singapore property listings by area, listing type, price, bedrooms, property type, and build year. Each record returns price, price per square foot, address, district, tenure, floor area etc — ready for property research, market analysis

- **URL**: https://apify.com/data\_dino/propertyguru-sg-scraper.md
- **Developed by:** [Data Dino](https://apify.com/data_dino) (community)
- **Categories:** Real estate, Automation, SEO tools
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## PropertyGuru Singapore listings

Collect decision-ready Singapore property listings from PropertyGuru in one Apify run. Choose an area and practical listing filters, then receive structured records with prices, addresses, property details, tenure, nearby MRT access, listing status, agents, and source-linked URLs — ready for export to JSON, CSV, or Excel.

### Why use this actor?

- **Area-focused search** — match listings to a named area such as Geylang, Orchard, or Tampines instead of downloading unrelated results.
- **Practical property filters** — narrow by listing type (sale or rent), property type, price band, bedroom count, and build year.
- **Structured listing records** — every item follows the same flat, query-friendly shape for analysis, comparison, and downstream exports.
- **Traceable sources** — each record keeps its PropertyGuru listing URL and source provenance.
- **Resilient collection** — stealth browser extraction with automatic retries and a configurable delay between pages to keep runs stable.

### Input

All fields are optional; defaults collect up to five Geylang condominium sale listings.

| Field | Type | Default | Description |
|---|---|---:|---|
| `area` | string | `Geylang` | Area text to match in listing titles, addresses, districts, regions, or nearby MRT names. |
| `limit` | integer | `5` | Maximum number of matching listings to return (1–100). |
| `listingType` | enum | `sale` | `sale` or `rent`. |
| `propertyTypes` | string array | `["CONDO"]` | PropertyGuru property type codes to include, such as `CONDO` or `HDB`. |
| `minPrice` | integer | *(empty)* | Optional minimum listing price in SGD. |
| `maxPrice` | integer | `2200000` | Optional maximum listing price in SGD. |
| `bedrooms` | string array | `["3", "4", "5"]` | Bedroom counts to include. |
| `minBuildYear` | integer | `2010` | Optional earliest build year to include. |
| `maxBuildYear` | integer | *(empty)* | Optional latest build year to include. |
| `maxPages` | integer | `40` | Maximum PropertyGuru result pages to inspect (1–100). |
| `delay` | number | `5` | Seconds to wait between result pages (0–120). |

#### Example input

```json
{
  "area": "Geylang",
  "limit": 5,
  "listingType": "sale",
  "propertyTypes": ["CONDO"],
  "maxPrice": 2200000,
  "bedrooms": ["3", "4", "5"],
  "minBuildYear": 2010,
  "maxPages": 40,
  "delay": 5
}
```

### Output

The actor pushes one dataset item per matching listing. Each item includes the listing ID, title, full address, district code and name, region, property type, build year, tenure, bedrooms, bathrooms, floor area, SGD price, price per square foot, nearby MRT, verification and developer flags, listing status, posting date, agent, agency, listing URL, and the source page number. Missing source values are returned as `null`.

A representative result:

```json
{
  "listing_id": 25362532,
  "title": "Mori",
  "full_address": "223 Guillemard Road",
  "district_code": "D14",
  "district_name": "Eunos / Geylang / Paya Lebar",
  "region": "Balestier / Geylang (D12-14)",
  "unit_type": "Condominium",
  "build_year_text": "Built: 2025",
  "build_year": 2025,
  "tenure_code": "F",
  "tenure": "F",
  "bedrooms": 3,
  "bathrooms": 2,
  "floor_area_sqft": 883,
  "price_sgd": 1750000,
  "price_pretty": "S$ 1,750,000",
  "price_psf_text": "S$ 1,981.88 psf",
  "price_psf": 1981.88,
  "nearest_mrt": "8 min (630 m) from EW9 Aljunied MRT Station",
  "is_verified": false,
  "is_new_project": false,
  "is_developer_listing": false,
  "listing_status": "ACT",
  "posted_on": "20 Aug 2026",
  "agent_name": null,
  "agency_name": null,
  "listing_url": "https://www.propertyguru.com.sg/listing/for-sale-mori-25362532",
  "page_scraped": 1,
  "source": "propertyguru.com.sg"
}
```

### Practical limitations

- Results reflect the public PropertyGuru page at run time and may change as listings are added or removed.
- Area matching is text-based across the listing's title, address, district, region, and nearby MRT fields.
- PropertyGuru may challenge automated requests; automatic retries and a page delay help, but no result is guaranteed.
- A run that cannot retrieve or match any listing is reported as failed rather than returning invented records.
- Use collected information in accordance with PropertyGuru's terms and applicable privacy and data-use requirements.

# Actor input Schema

## `area` (type: `string`):

Area text to match in listing titles, addresses, districts, regions, or nearby MRT names.

## `limit` (type: `integer`):

Maximum number of matching listings to return.

## `listingType` (type: `string`):

Whether to collect properties offered for sale or rent.

## `propertyTypes` (type: `array`):

PropertyGuru property type codes to include, such as CONDO or HDB.

## `minPrice` (type: `integer`):

Optional minimum listing price in Singapore dollars.

## `maxPrice` (type: `integer`):

Optional maximum listing price in Singapore dollars.

## `bedrooms` (type: `array`):

Bedroom counts to include.

## `minBuildYear` (type: `integer`):

Optional earliest build year to include.

## `maxBuildYear` (type: `integer`):

Optional latest build year to include.

## `maxPages` (type: `integer`):

Maximum PropertyGuru result pages to inspect before stopping.

## `delay` (type: `number`):

Delay between result pages. A modest delay helps reduce request rate and blocking.

## Actor input object example

```json
{
  "area": "Geylang",
  "limit": 5,
  "listingType": "sale",
  "propertyTypes": [
    "CONDO"
  ],
  "maxPrice": 2200000,
  "bedrooms": [
    "3",
    "4",
    "5"
  ],
  "minBuildYear": 2010,
  "maxPages": 40,
  "delay": 5
}
```

# Actor output Schema

## `dataset` (type: `string`):

Structured PropertyGuru listing records collected during the run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "area": "Geylang",
    "limit": 5,
    "listingType": "sale",
    "propertyTypes": [
        "CONDO"
    ],
    "maxPrice": 2200000,
    "bedrooms": [
        "3",
        "4",
        "5"
    ],
    "minBuildYear": 2010,
    "maxPages": 40,
    "delay": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("data_dino/propertyguru-sg-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "area": "Geylang",
    "limit": 5,
    "listingType": "sale",
    "propertyTypes": ["CONDO"],
    "maxPrice": 2200000,
    "bedrooms": [
        "3",
        "4",
        "5",
    ],
    "minBuildYear": 2010,
    "maxPages": 40,
    "delay": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("data_dino/propertyguru-sg-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "area": "Geylang",
  "limit": 5,
  "listingType": "sale",
  "propertyTypes": [
    "CONDO"
  ],
  "maxPrice": 2200000,
  "bedrooms": [
    "3",
    "4",
    "5"
  ],
  "minBuildYear": 2010,
  "maxPages": 40,
  "delay": 5
}' |
apify call data_dino/propertyguru-sg-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,data_dino/propertyguru-sg-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/oOAvXyNXwRM2irYjM/builds/1xUfq9ep1BeGVC5Tx/openapi.json
