{
  "openapi": "3.0.1",
  "info": {
    "title": "PropertyGuru Scraper [Only $0.85/1K💰] | SG/MY/TH | PSF | MRT",
    "description": "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.",
    "version": "1.4",
    "x-build-id": "8logn97nsUTkV3RQT"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/ahmed_jasarevic~propertyguru-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-ahmed_jasarevic-propertyguru-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/ahmed_jasarevic~propertyguru-scraper/runs": {
      "post": {
        "operationId": "runs-sync-ahmed_jasarevic-propertyguru-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/ahmed_jasarevic~propertyguru-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-ahmed_jasarevic-propertyguru-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": {
          "countries": {
            "title": "Portals",
            "type": "array",
            "description": "Which PropertyGuru portals to scrape. Pick one or combine several in a single run - each is geo-matched to its own market and the results are merged into one dataset. Pasted URLs below override this entirely, because a URL already states which portal it is.",
            "items": {
              "type": "string",
              "enum": [
                "th",
                "sg",
                "my"
              ],
              "enumTitles": [
                "Thailand — ddproperty.com",
                "Singapore — propertyguru.com.sg",
                "Malaysia — propertyguru.com.my"
              ]
            },
            "default": [
              "th"
            ]
          },
          "startUrls": {
            "title": "Listing URLs",
            "type": "array",
            "description": "Optional: one or more PropertyGuru URLs to scrape exactly as they are - result pages or individual listing pages, from any of the three portals, mixed freely in one list. Open the site, filter as you like, and paste the address bar. This overrides the filter fields below, and is the fastest way to re-scrape a page you already know.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "listingType": {
            "title": "Listing Type",
            "enum": [
              "sale",
              "rent"
            ],
            "type": "string",
            "description": "Sale or rent listings.",
            "default": "sale"
          },
          "freetext": {
            "title": "Location / Free text",
            "type": "string",
            "description": "Optional search text: area, district, MRT station or project name (e.g. 'Orchard', 'Tampines', 'Mont Kiara'). Leave empty for all listings.",
            "default": ""
          },
          "propertyType": {
            "title": "Property Type",
            "enum": [
              "",
              "CONDO",
              "HDB",
              "LANDED",
              "APARTMENT",
              "COMMERCIAL"
            ],
            "type": "string",
            "description": "Optional property type filter (SG/MY).",
            "default": ""
          },
          "minPrice": {
            "title": "Min Price",
            "minimum": 0,
            "type": "integer",
            "description": "Minimum price in local currency (SGD / MYR / THB). 0 = no minimum.",
            "default": 0
          },
          "maxPrice": {
            "title": "Max Price",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum price in local currency. 0 = no maximum.",
            "default": 0
          },
          "bedrooms": {
            "title": "Bedrooms",
            "minimum": -1,
            "maximum": 10,
            "type": "integer",
            "description": "Exact number of bedrooms (0 = studio). -1 = any.",
            "default": -1
          },
          "useMapSearch": {
            "title": "Include coordinates (Singapore)",
            "type": "boolean",
            "description": "Singapore only: also return latitude/longitude for every listing by using the map-search surface. Coordinates on the other portals are only published on individual listing pages, so paste listing URLs to get them.",
            "default": false
          },
          "maxItems": {
            "title": "Max Listings",
            "minimum": 1,
            "type": "integer",
            "description": "Maximum number of listings for the whole run. When several portals are selected this total is split between them as evenly as possible, so every portal is represented rather than one filling the cap. The actor asks the search for exactly the pages needed to reach this number.",
            "default": 50
          },
          "maxBlockRetries": {
            "title": "Max retries per blocked request",
            "minimum": 0,
            "maximum": 60,
            "type": "integer",
            "description": "How many times a request that comes back blocked may be retried on a fresh IP. Each retry waits longer than the last, spread across a window long enough for the proxy pool to turn over rather than hammering the same exhausted addresses. 0 disables retrying.",
            "default": 12
          },
          "blockRetryBudgetSecs": {
            "title": "Block retry time budget (seconds)",
            "minimum": 0,
            "maximum": 3000,
            "type": "integer",
            "description": "Total seconds one blocked request may spend waiting between retries before it is abandoned. The default spreads attempts over ~7 minutes, which is the timescale on which exhausted residential IPs actually turn over. Raise it to ride out a longer block; the container is idle while waiting, so this is far cheaper than any browser-based approach.",
            "default": 420
          },
          "requestDelayMs": {
            "title": "Request delay (ms)",
            "minimum": 250,
            "maximum": 10000,
            "type": "integer",
            "description": "Minimum gap between requests to the same portal. Lower is faster but raises the Cloudflare block rate; 1000 is the current default and 2000 is the more conservative setting. Every run logs how many requests were blocked, so running the same input at two values shows whether the extra speed costs blocks.",
            "default": 1000
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Select proxies to be used by your crawler. Residential is strongly recommended: every PropertyGuru portal sits behind Cloudflare, which blocks datacenter IPs outright. Each portal selected above is given an exit IP in its own market automatically, unless you pin a country here.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          }
        }
      },
      "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}