# PropertyGuru Singapore Listings & Agent Leads Scraper (`automation-lab/propertyguru-singapore-listings-agent-leads-scraper`) Actor

Scrape PropertyGuru Singapore sale and rental listings with SGD prices, PSF, property facts, locations, images, floor plans, and public agent/agency details. Search by keyword or URL and monitor recently posted inventory.

- **URL**: https://apify.com/automation-lab/propertyguru-singapore-listings-agent-leads-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Real estate, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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 & Agent Leads Scraper

Collect sale and rental listings from **PropertyGuru Singapore** as structured JSON, CSV, or Excel.

The Actor searches public `propertyguru.com.sg` result pages or enriches individual listing URLs.
It returns asking prices, PSF, property facts, dates, Singapore location fields, images, floor plans, and public professional agent and agency details.

Use it for daily inventory monitoring, valuation inputs, property research, and brokerage lead workflows.
V1 is intentionally Singapore-only.

### What this Actor does

- Searches PropertyGuru Singapore sale listings.
- Searches PropertyGuru Singapore rental listings.
- Accepts complete PropertyGuru search URLs with your existing filters.
- Accepts individual listing detail URLs.
- Generates searches from keywords, projects, addresses, neighborhoods, or MRT names.
- Paginates result pages up to a configurable safety limit.
- Optionally opens each detail page for richer records.
- Deduplicates listings by PropertyGuru listing ID.
- Filters by price, bedrooms, district, property type, and latest posted date.
- Saves one typed property record per accepted listing.
- Detects anti-bot and upstream payload changes instead of returning misleading empty success.

### Who is it for

#### Property agents and brokerages

Refresh competing inventory, asking prices, and public professional contact details for prospecting or territory analysis.

#### PropTech and AVM teams

Feed current asking-price, PSF, size, tenure, location, and property attributes into market models.

#### Investors and acquisition teams

Monitor new sale or rental inventory in selected projects and districts.

#### Market researchers

Create repeatable snapshots of Singapore inventory without manually copying listing pages.

#### Data and automation teams

Schedule runs, send dataset items to a webhook, or connect the Actor to an ETL or CRM workflow.

### Why use this scraper

PropertyGuru serves normal datacenter requests a Cloudflare challenge.
This Actor uses lightweight HTTP with a browser-like TLS fingerprint and a coherent Singapore proxy session.
It parses PropertyGuru's server-rendered structured state rather than running a full browser for every page.

That design provides:

- lower compute and memory than browser-heavy extraction;
- complete typed records instead of raw HTML;
- optional detail enrichment when card-level data is enough;
- explicit challenge and payload-shape errors;
- conservative sequential traffic and bounded retries;
- an incremental `since` mode for scheduled monitoring.

### Data extracted

| Field group | Example fields |
| --- | --- |
| Identity | `listingId`, `url`, `listingType`, `status` |
| Marketing | `title`, `headline`, `description` |
| Pricing | `currency`, `price`, `priceText`, `pricePerSqft` |
| Unit facts | `bedrooms`, `bathrooms`, `floorAreaSqft`, `landAreaSqft` |
| Property | `propertyType`, `propertyTypeCode`, `propertyName`, `tenure`, `developer` |
| Flags | `isNewProject`, `isVerified` |
| Dates | `firstPostedAt`, `lastPostedAt`, `updatedAt`, `availableAt` |
| Location | `address`, `streetName`, `districtCode`, `district`, `region`, `postcode` |
| Coordinates | `latitude`, `longitude` |
| Transport | `mrt` station context when present |
| Media | `imageUrls`, `floorPlanUrls` |
| Agent | public `id`, `name`, `jobTitle`, `ceaLicense`, `profileUrl`, `mobile`, `phone` |
| Agency | `id`, `name`, `ceaLicense` |
| Provenance | `sourceUrl`, `scrapedAt` |

Some fields are optional because publishers can mask addresses, omit floor plans, or leave attributes blank.
The Actor does not invent missing values.

### Getting started

1. Open the Actor input page.
2. Keep the prefilled Tampines search or enter `keywords`.
3. Choose `sale`, `rent`, or `both`.
4. Set `maxItems` to a small number for the first run.
5. Leave **Enrich listing details** enabled for descriptions, coordinates, media, and agent contacts.
6. Leave the default Singapore residential proxy configuration enabled.
7. Start the Actor.
8. Open the default dataset to export JSON, CSV, Excel, XML, or RSS.

A small enriched search:

```json
{
  "keywords": ["Tampines"],
  "searchType": "sale",
  "scrapeDetails": true,
  "maxItems": 10
}
````

### Input parameters

| Parameter | Type | Default | Purpose |
| --- | --- | --- | --- |
| `startUrls` | array | prefilled search | Sale/rent search URLs or listing detail URLs on `propertyguru.com.sg` |
| `searchType` | string | `sale` | Generated keyword mode: `sale`, `rent`, or `both` |
| `keywords` | string array | `[]` | Locations, projects, addresses, MRT names, or free-text terms |
| `districts` | string array | `[]` | Post-filter by district code or name, such as `D09` |
| `propertyTypes` | string array | `[]` | Post-filter by type name/code, such as `Condominium` or `CONDO` |
| `minPrice` | integer | unset | Minimum accepted asking price in SGD |
| `maxPrice` | integer | unset | Maximum accepted asking price in SGD |
| `minBedrooms` | integer | unset | Minimum accepted bedrooms |
| `since` | ISO date/time | unset | Keep listings posted at or after this timestamp |
| `scrapeDetails` | boolean | `true` | Fetch enriched listing detail pages |
| `maxItems` | integer | `100` | Maximum accepted, deduplicated records |
| `maxPages` | integer | `10` | Maximum pages per search |
| `requestDelayMs` | integer | `500` | Delay between HTTP requests |
| `maxRequestRetries` | integer | `2` | Retry limit for transient failures |
| `proxyConfiguration` | object | SG residential | Apify proxy settings |

#### URL behavior

Only HTTPS URLs on `propertyguru.com.sg` are accepted.
Supported paths are:

- `/property-for-sale`
- `/property-for-rent`
- `/listing/for-sale-...-<listing ID>`
- `/listing/for-rent-...-<listing ID>`

All Actor filters also apply to records discovered from explicit URLs.
Unsupported countries and sister domains fail validation.

### Incremental monitoring

Use `since` with a scheduled run to collect recently posted inventory:

```json
{
  "keywords": ["Orchard", "River Valley"],
  "searchType": "rent",
  "since": "2026-07-01T00:00:00+08:00",
  "scrapeDetails": true,
  "maxItems": 100
}
```

The filter uses each listing's latest posted timestamp.
Set the value from your workflow state or scheduling window.
The Actor does not keep a hidden cross-run global dataset, so each run remains isolated and predictable.

### Output example

The following abbreviated record reflects current live extraction behavior:

```json
{
  "listingId": "500156685",
  "url": "https://www.propertyguru.com.sg/listing/for-sale-citylife-tampines-500156685",
  "listingType": "SALE",
  "status": "ACT",
  "title": "CityLife @ Tampines",
  "currency": "SGD",
  "price": 2108888,
  "pricePerSqft": 1675.05,
  "bedrooms": 3,
  "bathrooms": 3,
  "floorAreaSqft": 1259,
  "propertyType": "Executive Condominium",
  "propertyTypeCode": "EXCON",
  "districtCode": "D18",
  "district": "Pasir Ris / Tampines",
  "latitude": 1.36083,
  "longitude": 103.94371,
  "imageUrls": ["https://sg1-cdn.pgimgs.com/listing/...jpg"],
  "agent": {
    "name": "Example agent",
    "ceaLicense": "R000000A",
    "mobile": "+65..."
  },
  "agency": {
    "name": "Example agency",
    "ceaLicense": "L0000000A"
  },
  "sourceUrl": "https://www.propertyguru.com.sg/property-for-sale?freetext=Tampines&page=1",
  "scrapedAt": "2026-07-25T03:11:53.688Z"
}
```

The example redacts professional contact identity while preserving the output shape.
Real dataset rows contain public source values when PropertyGuru exposes them.

### Pricing

This Actor uses pay-per-event pricing:

- **$0.005 start fee** per run;
- **$0.0010432 per saved listing** on the Free tier;
- **$0.00090714 per saved listing** on Bronze;
- lower tier prices apply on Silver and above.

You are charged for accepted records saved to the dataset, not challenge pages, duplicates, rejected records, or failed detail parses.
Platform compute and proxy use follow your Apify plan.

Illustrative Actor event charges on the Free tier:

| Saved listings | Event charge |
| ---: | ---: |
| 10 | about 0.0154 USD |
| 100 | about 0.1093 USD |
| 1,000 | about 1.0482 USD |

Actual totals shown by Apify can also include platform usage according to your plan.

### Performance and cost tips

- Set `scrapeDetails: false` for a fast listing-card feed.
- Enable details when you need descriptions, precise coordinates, media, or contact fields.
- Start with `maxItems: 10` before scaling a new search.
- Use narrow PropertyGuru search URLs to avoid filtering many irrelevant cards.
- Use `since` for frequent scheduled refreshes.
- Keep the Singapore residential proxy enabled; ordinary datacenter access is challenged.
- Avoid setting retry counts above the default unless logs show transient failures.

### Failure behavior and limitations

PropertyGuru can change its anti-bot controls or server-rendered payload.
The Actor treats a Cloudflare challenge, missing `__NEXT_DATA__`, or missing listing payload as an error.
It does not silently report those conditions as zero results.

A valid search with a recognized empty `listingsData` array succeeds with zero items.
An invalid URL, malformed date, inconsistent price range, or unsupported domain fails before scraping.

Other limitations:

- Singapore `propertyguru.com.sg` only;
- no Malaysia, Thailand, or Vietnam claims;
- no login-only or private data;
- no guarantee that publishers expose exact addresses or contact numbers;
- result ordering follows PropertyGuru;
- media URLs can expire or change after extraction;
- upstream listing availability can change between search and detail requests.

### Automation workflows

#### Daily inventory alert

Schedule a keyword search with `since`, then send dataset items to Slack, email, or a webhook.

#### Agent CRM enrichment

Run specific listing URLs, map `agent.ceaLicense` as a stable professional identifier, and deduplicate before CRM insertion.

#### Asking-price dataset

Run district searches periodically and store `price`, `pricePerSqft`, areas, tenure, and timestamps in a warehouse.

#### Competing-agent monitor

Group records by agency or public CEA license to observe active public inventory in a chosen project.

#### AVM feature feed

Use price, size, beds/baths, district, property type, coordinates, and posted dates as current listing-side model features.

### API with cURL

Replace `YOUR_APIFY_TOKEN` with your token:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~propertyguru-singapore-listings-agent-leads-scraper/runs?token=YOUR_APIFY_TOKEN&waitForFinish=120" \
  -H "Content-Type: application/json" \
  -d '{"keywords":["Tampines"],"searchType":"sale","maxItems":10}'
```

To receive dataset items directly:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~propertyguru-singapore-listings-agent-leads-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startUrls":[{"url":"https://www.propertyguru.com.sg/property-for-sale?freetext=Tampines"}],"maxItems":5}'
```

### API with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/propertyguru-singapore-listings-agent-leads-scraper').call({
  keywords: ['Tampines'],
  searchType: 'sale',
  scrapeDetails: true,
  maxItems: 10,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### API with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor(
    'automation-lab/propertyguru-singapore-listings-agent-leads-scraper'
).call(run_input={
    'keywords': ['Tampines'],
    'searchType': 'sale',
    'scrapeDetails': True,
    'maxItems': 10,
})

items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use with Apify MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/propertyguru-singapore-listings-agent-leads-scraper"
```

#### Claude Desktop, Cursor, and VS Code

Use this same MCP server configuration in **Claude Desktop**, **Cursor**, or **VS Code**. Add it to the client’s MCP settings file or MCP server UI:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/propertyguru-singapore-listings-agent-leads-scraper"
    }
  }
}
```

Example prompts:

- “Find up to 10 current Tampines sale listings and show price, PSF, bedrooms, and agent CEA license.”
- “Extract this PropertyGuru Singapore listing URL and summarize its location, floor area, images, and public agency details.”
- “Collect rental listings posted since my last monitoring timestamp.”

### Legality and responsible use

PropertyGuru pages and listing information may be protected by copyright, database rights, contract terms, and privacy laws.
You are responsible for your inputs, purpose, retention, and downstream use.

Collect only public data you have a lawful reason to process.
Respect applicable terms, robots guidance, rate limits, PDPA obligations, direct-marketing rules, and professional-contact preferences.
Do not use public phone fields for spam, harassment, discrimination, or unlawful profiling.
Avoid republishing copyrighted descriptions or images without permission.

This Actor is an extraction tool, not legal advice.

### Troubleshooting

#### The run reports a Cloudflare challenge

Keep the default SG residential proxy enabled.
Do not switch to a generic datacenter group.
If failures are temporary, retry later with the default coherent session behavior rather than extreme concurrency.

#### A valid search returns zero records

Open the same public search URL and confirm it currently has results.
Check `districts`, `propertyTypes`, price, bedroom, and `since` filters.
A listing missing a field required by a filter is rejected rather than guessed.

#### A listing has no address or phone

The publisher or PropertyGuru may mask or omit it.
The Actor emits only values present in public server-rendered data.

#### A URL is rejected

Use the Singapore HTTPS host and one of the supported search/detail paths.
Sister-country domains are deliberately out of scope.

#### The run stops after an upstream change

Inspect the error and run log.
Missing structured payloads fail explicitly so you can distinguish a source change from a genuine empty result.

### FAQ

#### Can I scrape both sale and rental listings?

Yes. Set `searchType` to `both` for generated keyword searches, or provide both kinds of search URL.

#### Can I scrape a single listing?

Yes. Put the full public detail URL in `startUrls`.

#### Does it return agent phone numbers?

It returns public professional mobile/phone fields when PropertyGuru includes them in the listing payload.

#### Is a browser launched?

No. The Actor uses browser-fingerprinted HTTP and structured SSR data, reducing compute compared with a full browser.

#### Can I turn off enrichment?

Yes. Set `scrapeDetails` to `false` for card-level output.

#### Does `maxItems` count filtered or duplicate records?

It counts accepted, deduplicated dataset records.

#### Does it retain data between runs?

No hidden global dataset is used. Every run writes to its own default dataset.

#### Is PropertyGuru Malaysia supported?

No. This version is Singapore-only.

### Related Automation Lab Actors

For equivalent property workflows in other markets:

- [Realtor.com Scraper](https://apify.com/automation-lab/realtor-scraper) — United States listings.
- [Rightmove Scraper](https://apify.com/automation-lab/rightmove-scraper) — United Kingdom listings.
- [PropertyFinder Scraper](https://apify.com/automation-lab/propertyfinder-scraper) — Middle East property listings.
- [Redfin Scraper](https://apify.com/automation-lab/redfin-scraper) — United States sale-market research.

Choose this Actor when your target source is specifically PropertyGuru Singapore and you need Singapore district, CEA, MRT, and SGD-oriented fields.

### Support

If the target changes or a valid input fails, open an Actor issue with:

- the input with sensitive values removed;
- the run URL or run ID;
- whether card-only or detail enrichment was enabled;
- the expected listing or search behavior;
- the first relevant error from the log.

That evidence makes anti-bot and payload changes faster to diagnose.

# Actor input Schema

## `startUrls` (type: `array`):

Optional property-for-sale/property-for-rent search URLs or individual listing detail URLs on propertyguru.com.sg. Existing URL filters are preserved.

## `searchType` (type: `string`):

Listing market used for generated keyword searches.

## `keywords` (type: `array`):

Generate one PropertyGuru Singapore search per keyword, project, neighborhood, MRT station, or address. Leave empty when only startUrls should run.

## `districts` (type: `array`):

Keep records whose district code or name contains one of these values, for example D09 or Orchard.

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

Keep matching property types or codes, such as Condominium, HDB, CONDO, or LANDED.

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

Keep listings at or above this asking price.

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

Keep listings at or below this asking price.

## `minBedrooms` (type: `integer`):

Keep listings with at least this many bedrooms.

## `since` (type: `string`):

Only emit listings whose latest posted timestamp is at or after this ISO 8601 date/time. Useful for incremental monitoring.

## `scrapeDetails` (type: `boolean`):

Open every discovered listing to collect descriptions, precise location, images, and public agent/agency fields. Disable for a faster listing-card feed.

## `maxItems` (type: `integer`):

Maximum accepted, deduplicated records to save.

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

Safety limit for PropertyGuru result pagination.

## `requestDelayMs` (type: `integer`):

Conservative delay between search/detail requests. Increase if the target starts throttling.

## `maxRequestRetries` (type: `integer`):

Retries for transient network, throttling, and challenge responses. Parser and input errors are not retried.

## `proxyConfiguration` (type: `object`):

Singapore residential proxy is strongly recommended and used by default because PropertyGuru challenges ordinary datacenter requests.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.propertyguru.com.sg/property-for-sale?freetext=Tampines"
    }
  ],
  "searchType": "sale",
  "keywords": [],
  "districts": [],
  "propertyTypes": [],
  "since": "2026-07-01T00:00:00+08:00",
  "scrapeDetails": true,
  "maxItems": 10,
  "maxPages": 10,
  "requestDelayMs": 500,
  "maxRequestRetries": 2,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "SG"
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

Accepted, deduplicated PropertyGuru Singapore records shown in the overview view.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.propertyguru.com.sg/property-for-sale?freetext=Tampines"
        }
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/propertyguru-singapore-listings-agent-leads-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 = {
    "startUrls": [{ "url": "https://www.propertyguru.com.sg/property-for-sale?freetext=Tampines" }],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/propertyguru-singapore-listings-agent-leads-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.propertyguru.com.sg/property-for-sale?freetext=Tampines"
    }
  ],
  "maxItems": 10
}' |
apify call automation-lab/propertyguru-singapore-listings-agent-leads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=automation-lab/propertyguru-singapore-listings-agent-leads-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "PropertyGuru Singapore Listings & Agent Leads Scraper",
        "description": "Scrape PropertyGuru Singapore sale and rental listings with SGD prices, PSF, property facts, locations, images, floor plans, and public agent/agency details. Search by keyword or URL and monitor recently posted inventory.",
        "version": "0.1",
        "x-build-id": "SfXrpjOjfLWd7ivyc"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/automation-lab~propertyguru-singapore-listings-agent-leads-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-automation-lab-propertyguru-singapore-listings-agent-leads-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/automation-lab~propertyguru-singapore-listings-agent-leads-scraper/runs": {
            "post": {
                "operationId": "runs-sync-automation-lab-propertyguru-singapore-listings-agent-leads-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/automation-lab~propertyguru-singapore-listings-agent-leads-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-automation-lab-propertyguru-singapore-listings-agent-leads-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "startUrls": {
                        "title": "PropertyGuru Singapore URLs",
                        "type": "array",
                        "description": "Optional property-for-sale/property-for-rent search URLs or individual listing detail URLs on propertyguru.com.sg. Existing URL filters are preserved.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "searchType": {
                        "title": "Search type",
                        "enum": [
                            "sale",
                            "rent",
                            "both"
                        ],
                        "type": "string",
                        "description": "Listing market used for generated keyword searches.",
                        "default": "sale"
                    },
                    "keywords": {
                        "title": "Keywords or locations",
                        "type": "array",
                        "description": "Generate one PropertyGuru Singapore search per keyword, project, neighborhood, MRT station, or address. Leave empty when only startUrls should run.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "districts": {
                        "title": "District filters",
                        "type": "array",
                        "description": "Keep records whose district code or name contains one of these values, for example D09 or Orchard.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "propertyTypes": {
                        "title": "Property type filters",
                        "type": "array",
                        "description": "Keep matching property types or codes, such as Condominium, HDB, CONDO, or LANDED.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "minPrice": {
                        "title": "Minimum price (SGD)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Keep listings at or above this asking price."
                    },
                    "maxPrice": {
                        "title": "Maximum price (SGD)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Keep listings at or below this asking price."
                    },
                    "minBedrooms": {
                        "title": "Minimum bedrooms",
                        "minimum": 0,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Keep listings with at least this many bedrooms."
                    },
                    "since": {
                        "title": "Posted since",
                        "type": "string",
                        "description": "Only emit listings whose latest posted timestamp is at or after this ISO 8601 date/time. Useful for incremental monitoring."
                    },
                    "scrapeDetails": {
                        "title": "Enrich listing details",
                        "type": "boolean",
                        "description": "Open every discovered listing to collect descriptions, precise location, images, and public agent/agency fields. Disable for a faster listing-card feed.",
                        "default": true
                    },
                    "maxItems": {
                        "title": "Maximum listings",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Maximum accepted, deduplicated records to save.",
                        "default": 100
                    },
                    "maxPages": {
                        "title": "Maximum pages per search",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Safety limit for PropertyGuru result pagination.",
                        "default": 10
                    },
                    "requestDelayMs": {
                        "title": "Delay between requests (ms)",
                        "minimum": 0,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Conservative delay between search/detail requests. Increase if the target starts throttling.",
                        "default": 500
                    },
                    "maxRequestRetries": {
                        "title": "Request retries",
                        "minimum": 0,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Retries for transient network, throttling, and challenge responses. Parser and input errors are not retried.",
                        "default": 2
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Singapore residential proxy is strongly recommended and used by default because PropertyGuru challenges ordinary datacenter requests.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ],
                            "apifyProxyCountry": "SG"
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
