propertyguru-mcp

propertyguru-mcp

Unofficial MCP server that exposes PropertyGuru Singapore & Malaysia property listing search as MCP tools, returning detailed listing data without an API key.

Category
Visit Server

README

propertyguru-mcp

Python 3.10+ License: MIT MCP Tests

Unofficial MCP (Model Context Protocol) server that exposes PropertyGuru Singapore & Malaysia listing search as MCP tools. No API key. No subscription. One HTTP request per query.


⚠️ Disclaimer

This project is not affiliated with, endorsed by, or connected to PropertyGuru Group in any way. It is an unofficial, community-maintained tool built for personal research and educational purposes.

  • PropertyGuru® and the PropertyGuru logo are trademarks of PropertyGuru Group.
  • This tool scrapes publicly available HTML that PropertyGuru renders server-side. Use of this tool may violate PropertyGuru's Terms of Service. Use at your own risk.
  • No warranty. The authors are not responsible for any consequences of using this tool.
  • If you are PropertyGuru and want this taken down, please open an issue and I will respond promptly.

What data does it provide?

Each search_listings call returns up to 25 listings (one page) with the complete 48-field listingData as rendered by PropertyGuru itself. Highlights:

Category Fields
Price price.value, price.pretty ("S$ 3,499,999"), price.type.text (Negotiable / Offers Welcome)
Area area.localeStringValue ("1,873 sqft"), floorArea
PSF pricePerArea.localeStringValue ("S$ 1,868.66 psf")
Layout bedrooms, bathrooms, property.subTypeText (Condominium / HDB / Apartment / Landed / Commercial)
Tenure / Age Freehold vs 99-year Leasehold; "Built: 2010"
Address fullAddress ("29 Angullia Park"), shortAddress ("Orchard / River Valley, D09-10")
Public transit mrt.nearbyText ("7 min (570 m) from NS22 Orchard MRT Station")
Photos mediaCarousel.previewMedia.images.items[] (15-30 hi-res URLs per listing), floorPlans.items[]
Agent agent.name, agent.license (e.g. R057754I), agent.profileUrl, agent.description, agency.name
Status isVerified, isOfficialListing, isDeveloperListing, isPrioritized
Posted postedOn.text, postedOn.unix
Highlights highlights.items (project selling points)
URL Direct link to the listing detail page

No field pruning. Server returns the raw listingData structure — the example below is the exact JSON a caller receives.


Demo

Real output of search_listings(region="sg", listing_type="rent", freetext="Orchard", bedrooms_min=3, price_min=3000000, price_max=5000000):

{
  "count": 25,
  "listings": [
    {
      "id": 25472440,
      "price": { "value": 3499999, "pretty": "S$ 3,499,999", "type": { "text": "Negotiable" } },
      "pricePerArea": { "localeStringValue": "S$ 1,868.66 psf" },
      "area": { "localeStringValue": "1,873 sqft" },
      "bedrooms": 3, "bathrooms": 3,
      "localizedTitle": "Orchard Scotts",
      "fullAddress": "251 Orchard Road",
      "shortAddress": "Orchard / River Valley (D09-10)",
      "mrt": { "nearbyText": "10 min (840 m) from NS21 Newton MRT Station" },
      "mediaItems": [{ "icon": "images", "text": "18", "mediaType": "images" }],
      "agent": { "name": "Edwin Phua", "license": "R057754I" },
      "agency": { "name": "HUTTONS ASIA PTE. LTD." },
      "url": "https://www.propertyguru.com.sg/listing/for-sale-orchard-scotts-25472440",
      "postedOn": { "text": "11 Aug 2026", "unix": 1786419975 }
    },
    ...
  ]
}

How it works

PropertyGuru is a Next.js SSR site. When you visit a listing-search URL, the server embeds the complete result set as JSON at a well-known DOM id:

<script id="__NEXT_DATA__" type="application/json">{
  "props": { "pageProps": { "pageData": { "data": {
    "listingsData": [ { "listingData": { ... }, ... }, ... ]
  } } } }
}</script>

This MCP server:

  1. Builds a filter URL using the same minPrice/maxPrice/bedrooms[]/freetext param spelling PropertyGuru's own frontend uses.
  2. Fetches the HTML page with a plain browser User-Agent.
  3. Parses __NEXT_DATA__ (regex → json.loads).
  4. Returns the raw listingData array as JSON to the caller.

Why no third-party API key: because we're not using PropertyGuru's paid partner APIs — we're reading the same HTML your browser would receive.


Tools

search_listings

The primary tool. Returns a page of full listings.

Param Type Required Default Description
region sg | my sg Singapore or Malaysia
listing_type sale | rent sale
freetext string Free text: "Orchard", "Mont Kiara", "Tampines", "Orchard Scotts" (specific condo)
property_type string CONDO, HDB, LANDED, APARTMENT, COMMERCIAL
bedrooms_min int When bedrooms_min == bedrooms_max, treated as exact match
bedrooms_max int Studio = 0
price_min int Local currency (SGD or MYR)
price_max int
sort enum price_asc, price_desc, date, psf
limit int ≤ 40 25 Single page cap

get_listing_count

Cheap probe returning only the count for a search (use to size a query before fetching).


Installation

# Clone and install
git clone https://github.com/kkukoo/propertyguru-mcp.git
cd propertyguru-mcp

# Option A: uv (recommended)
uv venv && uv pip install -e .

# Option B: plain pip
python -m venv .venv && ./.venv/bin/pip install -e .

# Run tests
python -m pytest tests/ -v

After install, the MCP server is available three ways (all equivalent):

# 1. Console script
.venv/bin/propertyguru-mcp

# 2. Module invocation
.venv/bin/python -m propertyguru_mcp

# 3. Direct path (no install needed if you prefer running from source)
python src/propertyguru_mcp/server.py

The server talks MCP over stdio (the default transport for MCP clients). It does not listen on any network port.


Hooking up to your MCP client

Below are working config snippets. Replace /path/to/propertyguru-mcp and the python interpreter with whatever you used in the install step.

Hermes Agent — ~/.hermes/config.yaml

mcp_servers:
  propertyguru:
    command: /path/to/propertyguru-mcp/.venv/bin/propertyguru-mcp
    args: []
    timeout: 60
    connect_timeout: 30

Reload via hermes gateway restart (from a shell outside Hermes) or /restart from inside the gateway chat.

Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "propertyguru": {
      "command": "/path/to/propertyguru-mcp/.venv/bin/propertyguru-mcp",
      "args": []
    }
  }
}

Restart Claude Desktop after editing.

Cursor — ~/.cursor/mcp.json

{
  "mcpServers": {
    "propertyguru": {
      "command": "/path/to/propertyguru-mcp/.venv/bin/propertyguru-mcp",
      "args": []
    }
  }
}

Cline (VS Code extension)

In Cline Settings → MCP, add:

{
  "propertyguru": {
    "command": "/path/to/propertyguru-mcp/.venv/bin/propertyguru-mcp",
    "args": []
  }
}

Continue.dev

Edit ~/.continue/config.json:

{
  "experimental": {
    "modelContextProtocolServers": [{
      "name": "propertyguru",
      "transport": {
        "type": "stdio",
        "command": "/path/to/propertyguru-mcp/.venv/bin/propertyguru-mcp",
        "args": []
      }
    }]
  }
}

Any OpenAI Agents SDK-compatible client

The standard MCP stdio pattern works:

from agents.mcp import MCPServerStdio

async with MCPServerStdio(
    name="propertyguru",
    params={
        "command": "/path/to/propertyguru-mcp/.venv/bin/propertyguru-mcp",
        "args": [],
    },
) as server:
    tools = await server.list_tools()

Known limitations

  • Single-page responses (25 listings). PropertyGuru's &page=N query-string is unreliable from non-browser User-Agents (Cloudflare blocks intermittently). Path-style /{region}/property-for-sale/2 works but is untested in the server. If you need > 25 listings, run multiple freetexts / districts and merge client-side.
  • Cloudflare. If PropertyGuru starts challenging this server's User-Agent or your IP, you'll get HTTP 403 errors. Workarounds: slow down request rate; route via a residential proxy; switch to a browser-based toolset (e.g. Hermes browser_exec).
  • Field drift. PropertyGuru can reshape __NEXT_DATA__ any time. When it does, search_propertyguru will raise and you'll need to re-trace the path (look at the live page's __NEXT_DATA__ in browser DevTools).
  • Singapore + Malaysia only. PropertyGuru has other regional sites (propertyguru.co.id, .co.th) — PRs welcome.
  • No autocomplete endpoint. There's a separate RapidAPI endpoint that does location autocomplete; if you want that here, it's a clean addition (file an issue or open a PR).
  • No detail endpoint. To get full listing descriptions / floor plans, you need one extra fetch per listing — not implemented yet.

Roadmap

  • [ ] Stable multi-page support (handle Cloudflare + path-style /{n} pagination)
  • [ ] autocomplete_locations(query) — return objectId / district / MRT proximity
  • [ ] get_listing_detail(listing_url) — full description, all photos, floor plans
  • [ ] Built-in rate limiter (configurable requests/min) to stay polite to PropertyGuru
  • [ ] Optional thin server-side projection (e.g. fields=summary) to save caller tokens
  • [ ] Indonesia / Thailand region support

Contributing

See CONTRIBUTING.md. PRs welcome — especially for:

  • New regions (Indonesia/Thailand)
  • New endpoints (autocomplete, detail, project pages)
  • Tests for additional URL parameter combinations
  • Better Cloudflare resilience
  • Example usage for other MCP clients (Windsurf, Codex, OpenClaw, etc.)

License

MIT — see LICENSE.


Acknowledgements

Built with modelcontextprotocol/python-sdk. Inspired by the wider community's shared frustration that real-estate data is artificially locked down by a handful of aggregators.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured