{
  "openapi": "3.0.1",
  "info": {
    "title": "iProperty MY Scraper - Properties, Prices, Agents & Photos",
    "description": "Scrape property listings from iProperty.com.my for sale or rent: price, PSF, bedrooms, bathrooms, floor area, tenure, property type, full address, agent (name, license, agency, contact numbers) and photo gallery. Search and URL modes, filters, 6 sort orders, and optional detail enrichment.",
    "version": "1.0",
    "x-build-id": "seevhawpRUMs3nnve"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~iproperty-com-my-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-iproperty-com-my-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/abotapi~iproperty-com-my-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-iproperty-com-my-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/abotapi~iproperty-com-my-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-iproperty-com-my-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",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "How to start the scrape. 'search' builds a search from the channel, location and filters below. 'url' walks the iProperty.com.my search or listing URLs you paste (search filters below are ignored in URL mode).",
            "default": "search"
          },
          "channel": {
            "title": "Channel",
            "enum": [
              "sale",
              "rent"
            ],
            "type": "string",
            "description": "Search properties for sale or for rent.",
            "default": "sale"
          },
          "isCommercial": {
            "title": "Commercial properties",
            "type": "boolean",
            "description": "Search the commercial property routes (offices, shops, retail, industrial) for the chosen channel instead of residential listings.",
            "default": false
          },
          "location": {
            "title": "Location",
            "type": "string",
            "description": "Optional location to narrow the search: a state, city, district or neighbourhood name (e.g. 'Kuala Lumpur', 'Selangor', 'Petaling Jaya', 'Mont Kiara'). Hyphens work too ('petaling-jaya'). You can also paste an iProperty.com.my location slug straight from your browser's address bar (e.g. 'in-kuala-lumpur-58jok'). Leave empty to search the whole country."
          },
          "propertyType": {
            "title": "Property type",
            "enum": [
              "",
              "bungalow",
              "condo",
              "semi_detached",
              "terrace",
              "land"
            ],
            "type": "string",
            "description": "Optional property type filter. Leave empty for all types.",
            "default": ""
          },
          "priceMin": {
            "title": "Minimum price (MYR)",
            "minimum": 0,
            "type": "integer",
            "description": "Only return listings priced at or above this amount."
          },
          "priceMax": {
            "title": "Maximum price (MYR)",
            "minimum": 0,
            "type": "integer",
            "description": "Only return listings priced at or below this amount."
          },
          "bedrooms": {
            "title": "Minimum bedrooms",
            "minimum": 0,
            "type": "integer",
            "description": "Only return listings with at least this many bedrooms."
          },
          "sortBy": {
            "title": "Sort by",
            "enum": [
              "relevance",
              "date_desc",
              "date_asc",
              "price_desc",
              "price_asc",
              "size_desc"
            ],
            "type": "string",
            "description": "Order the results are returned in.",
            "default": "relevance"
          },
          "urls": {
            "title": "iProperty.com.my URLs",
            "type": "array",
            "description": "Paste iProperty.com.my search, category or listing URLs (country-wide, location, ?page=N, filtered/sorted, keyword, property-type category, listing detail, new-project detail). Pasted filters and page numbers are applied; they win over the search fields. Agent profile pages are not supported and are skipped with a warning. Leave untouched in URL mode to scrape one example of each of the 13 supported shapes (raise Max items to reach all of them: the default cap of 20 is spent on the first search URLs).",
            "default": [
              "https://www.iproperty.com.my/property-for-sale",
              "https://www.iproperty.com.my/property-for-rent",
              "https://www.iproperty.com.my/property-for-sale/in-kuala-lumpur-58jok",
              "https://www.iproperty.com.my/property-for-sale?page=2",
              "https://www.iproperty.com.my/property-for-sale/in-kuala-lumpur-58jok?page=2",
              "https://www.iproperty.com.my/property-for-sale?sort=price&order=desc&propertyTypeGroup=N&minPrice=500000&maxPrice=900000&bedroom=3",
              "https://www.iproperty.com.my/property-for-sale?keyword=Mont%20Kiara",
              "https://www.iproperty.com.my/terrace-for-sale",
              "https://www.iproperty.com.my/apartment-condo-service-residence-for-sale",
              "https://www.iproperty.com.my/commercial-property-for-sale",
              "https://www.iproperty.com.my/property/bangsar/khaya-residences/sale-501740698/",
              "https://www.iproperty.com.my/property/sale-501740698/",
              "https://www.iproperty.com.my/new-property/property/johor-bahru/residensi-maxim-pelangi-the-address-johor-bahru/sale-501752866/"
            ],
            "items": {
              "type": "string"
            }
          },
          "fetchDetails": {
            "title": "Fetch full details",
            "type": "boolean",
            "description": "Visit each listing page to add the full property description and map coordinates (latitude / longitude). Slower and adds a small per-item charge; leave off for fast basic listings.",
            "default": false
          },
          "maxItems": {
            "title": "Max items",
            "minimum": 0,
            "type": "integer",
            "description": "The single cap on this run: stop after collecting this many listings (across all searches/URLs). Set 0 for unlimited.",
            "default": 20
          },
          "maxPages": {
            "title": "Max pages per search",
            "minimum": 0,
            "type": "integer",
            "description": "Optional safety bound on how many result pages to include per search. Defaults to unlimited (leave empty or set 0) and does NOT cap the run; it defers to Max items, which is the single cap. The run stops at Max items, not here."
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Use an Apify Residential proxy for reliable results.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ],
              "apifyProxyCountry": "MY"
            }
          },
          "maxResidentialMB": {
            "title": "Residential traffic budget (MB)",
            "minimum": 0,
            "type": "integer",
            "description": "When using a Residential proxy group, cap residential traffic at this many MB. The run keeps returning results as long as the site still serves them, and will not silently drop to zero. 0 = unlimited.",
            "default": 0
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run",
            "type": "string",
            "description": "Paste a previous run ID or dataset ID to continue a large crawl without returning or charging for listings already collected there. Use this after an interrupted run. For recurring monitoring of the same search, use Incremental mode below instead."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn this on for daily or recurring monitoring. The first run returns all matching listings as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED listings. A listing counts as UPDATED when any output field changes except the ignored ones (by default scrapedAt, searchMetadata, the relative ago-text in recency, recencyText and postedOn, thumbnail and image links; see Ignore fields below); changedFields names what moved. Turn on \"Emit unchanged\" or \"Emit expired\" only when you also want those listings returned (and billed). State is kept separately for each search/URL and detail-mode setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional, incremental mode only)",
            "type": "string",
            "description": "Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the search/URL and detail settings — different searches then never mix state with each other."
          },
          "emitUnchanged": {
            "title": "Emit unchanged listings (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return listings that have not changed since the last run, marked UNCHANGED. This returns — and bills — extra rows you already have, so leave it off unless you specifically want the full snapshot every run.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired listings (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return listings that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search — not when Max items capped it or when Resume was used. This returns — and bills — extra synthetic rows, so leave it off unless you need expiry tracking.",
            "default": false
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "Incremental mode only. Field names (or nested paths such as postedOn.unix) that must NOT make a listing count as UPDATED. They stay in the output. Already ignored by default: scrapedAt, searchMetadata, the relative \"(… ago)\" part of recency and recencyText, postedOn.text, thumbnail and images (image CDN links). Everything else is compared, so a change to price, bedrooms, bathrooms, floor area, title, tenure, agent, description, coordinates or image count marks the listing UPDATED and lists it in changedFields.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write/digest. Leave empty to skip; never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com)."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on items written to each connector per run. Does not affect the dataset.",
            "default": 50
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}