Centaline API: Ask Claude to Compare Hong Kong Property Prices via Apify MCP
In one line: There’s no public Centaline API, but you can get a natural-language version of one by wiring Apify’s official MCP server into Claude: ask “how does Taikoo Shing’s current asking price compare with its recent deals?” and Claude calls
centaline-scraperitself, reads the dataset back, and computes the medians. We ran it for real on October 12, 2026 — 33 transactions at a median price per square foot of $17,512 against 40 listings at $17,373, for about $0.17 total.
Why ask Claude instead of opening Centaline’s site yourself
Checking how far an estate’s current asking prices have drifted from what actually sold takes two open tabs: one for listings, one for transaction history, then copying unit prices by hand and averaging them yourself. Fine once. Annoying if you check a handful of estates every week.
Searching “centaline api” usually means you’re looking for a programmatic way to pull Centaline’s public data, because there isn’t an official one. centaline-scraper does that: it turns the listings and transaction records already shown publicly on Centaline (and 28Hse) into fixed JSON fields. Add Apify’s official MCP server on top, and Claude can treat that actor as its own tool — you ask in plain English, and it decides which mode to run and what estate name to fill in.
If you want the full field and mode reference first, see the Hong Kong property data hub; this piece is about what actually happens once you wire it into Claude.
What you need
- An Apify account (no monthly fee, pay per item, free credits to start)
- Claude Code, or Claude Desktop / claude.ai (any MCP-capable client works)
- About 5 minutes
Step 1 — Connect Apify’s official MCP server (hosted)
The older approach ran a local stdio server with npx (see our Bahamut forum-monitoring guide for that pattern). Apify now also hosts the server directly at mcp.apify.com, so there’s nothing to install.
For Claude Code, one command:
claude mcp add --transport http apify \
"https://mcp.apify.com/?tools=claude_code_reviewer/centaline-scraper-en,claude_code_reviewer/midland-scraper-en" \
--header "Authorization: Bearer $APIFY_TOKEN"
$APIFY_TOKEN is the token from Apify Console → Settings → API & Integrations. This is the documented syntax for adding a remote HTTP MCP server to Claude Code.
The ?tools= part matters: it restricts Claude to exactly these two actors. Leave it off and Apify’s MCP server exposes broader, dynamic tools like search-actors and call-actor by default, which let Claude find and run any actor in the Store — convenient, but you lose control over which one it picks and what it spends. With the filter in place, Claude only sees centaline-scraper-en, midland-scraper-en, plus the generic get-dataset-items / get-actor-run tools it needs to read results back.
For Claude Desktop or claude.ai: add a custom connector under Settings, point it at https://mcp.apify.com, and sign in to your Apify account via OAuth when prompted — no token to paste.
Step 2 — Just ask
Once it’s connected, paste a prompt like this (swap in any estate name):
You have Apify's centaline-scraper and get-dataset-items tools available. Compare
Taikoo Shing's current asking prices against its recent transactions:
1. Run centaline-scraper in transactions mode, keywords "Taikoo Shing", dealType
buy, maxItems 40.
2. Run it again in search mode, source centanet, keywords "Taikoo Shing",
dealType buy, maxItems 40.
3. After both runs finish, read the datasets with get-dataset-items. Only
request the fields you actually need, not every column.
4. Some transaction records are parking spaces (building is a parking
designation, area and unit price are null) — filter those out before
computing anything using net_unit_price.
5. Compute: median transaction price per square foot (saleable area), median
asking price per square foot, and both split by 2-bedroom vs. 3-bedroom.
6. Present the result as a small table, noting the transaction date range and
sample size.
7. Add a short caveat section: how small the sample is, how far it covers, and
what conclusions it can't support. Don't forecast where prices are headed.
Claude calls the tool, reads the dataset, and does the arithmetic. You can keep asking follow-ups afterward — “which 3-bedroom deal closed at the lowest price?” works fine in the same thread.
What we actually got: Taikoo Shing, 33 deals vs. 40 asking prices
Here’s one real run from October 12, 2026 (same MCP connection, same input as above):
| Transactions | Asking prices (listings) | |
|---|---|---|
| Sample | 33 residential deals (7 parking-space records excluded) | 40 current listings |
| Date range | August 3 – October 6, 2026 | October 12, 2026 snapshot |
| Median price/sq ft (saleable) | $17,512 | $17,373 |
| Range | $14,493 – $22,237 | $14,716 – $24,630 |
| 2-bedroom median | $17,032 (19 deals) | $17,081 (20 listings) |
| 3-bedroom median | $19,786.5 (14 deals) | $18,358 (20 listings) |
Overall, the asking-price median sat about 0.8% below the recent transaction median. Two-bedroom units were roughly flat (asking price about 0.3% higher). Three-bedroom units were the exception: asking prices ran about 7% below recent deals — none of the 3-bedroom listings in this sample were priced above what a 3-bedroom unit had actually sold for recently.
This is not a market-trend finding. The honest caveats:
- The 40 listings are only the site’s default-sorted first page, not every unit for sale.
- 33 transactions over about two months is a small sample — 14 of them for 3-bedroom units alone, so the median moves easily if one or two deals are unusual.
- It’s one estate.
- A lower asking-price median than the transaction median could mean asking prices really are soft, or it could just mean the listed units differ in floor, aspect or condition from the units that actually sold — this sample can’t tell the two apart.
So treat a result like this as “a quick gut-check before you go view a unit,” not a buy or sell signal. For how one estate’s price can diverge from the citywide picture over time, see Hong Kong’s CCL index gap.
Three things the agent will trip on if your prompt doesn’t cover them
Running this for real surfaced three specific failure points — skip any of them in your prompt and Claude is likely to go wrong.
1. Transaction records include parking spaces. 7 of the 40 transaction rows we pulled were parking-space deals, with area and every price-per-square-foot field null. Without an explicit instruction to filter those out, the median gets skewed, or the calculation errors out on the nulls. That’s what step 4 in the prompt above is for.
2. Midland can’t be searched by estate name. midland-scraper only accepts region-level filters — regions (Hong Kong Island / Kowloon / New Territories), bedrooms, bathrooms, schoolNet. An estate name or keyword sent to Midland’s own API is silently ignored, not rejected — it just behaves as if that parameter wasn’t there. To get Midland data for one estate, have Claude pull the whole region first, then filter the output’s own estate field itself. If you specifically need to search by estate name, centaline-scraper is the one that supports it directly. See the three-agency comparison in our listing-verification guide for what each actor can and can’t do.
3. The tool call returns a summary, not the data. After Claude calls the actor, what comes back is a run ID, status, a one-line summary, a dataset ID, and a prompt to call get-dataset-items to read the actual rows. The real records only arrive once Claude makes that second call, and it can request specific fields instead of pulling everything. That keeps dozens of rows with twenty-odd columns each out of the conversation at once — but it also means that if your prompt doesn’t say so explicitly, the agent can answer from the summary alone and hand you confident-sounding numbers with no data behind them. Step 3 in the prompt above exists specifically to prevent that.
What it actually costs
The MCP layer itself is free; you pay the actor’s normal pay-per-event price:
| Item | Count | Price | Subtotal |
|---|---|---|---|
Transaction records (search-listing event) | 40 | $0.002 | $0.08 |
Current listings (search-listing event) | 40 | $0.002 | $0.08 |
| Run-start fee (charged automatically by Apify) | 2 | $0.005 | $0.01 |
| Total | about $0.17 |
The two tool calls took 11 and 12 seconds respectively, start to finish (the actor itself ran for about 5.5 and 6.6 seconds inside that). That’s a real, paid run; it’s free if you’re still inside the actor’s free-usage credits. If you wanted to check ten estates every week, extrapolating from the same per-item prices (not a separate measurement) comes out to roughly $1.70 a week.
Beyond one question: turning this into weekly tracking
A single question only gets you a snapshot. If you’re watching a handful of estates over time, schedule the same input on Apify — weekly, using dateFrom in transactions mode so each run only pulls newly added deals — and let the results accumulate into one dataset. Then ask Claude to read the whole series back with get-dataset-items and answer something like “has the gap between asking price and recent deals narrowed over the last three months?” — which a single snapshot can’t tell you.
Three ways to start
From least effort to most freedom
FAQ
Does Centaline have an official API? No. Centaline has not published a public API. centaline-scraper is a third-party Apify actor that reads the listing and transaction data Centaline (and 28Hse) already display publicly and turns it into fixed, snake_case JSON fields. Wiring it into Claude through Apify’s official MCP server effectively gives you a natural-language front end to it.
How much does one MCP question about an estate cost? In our test, 40 transaction records plus 40 current listings (80 items total) cost $0.002 each under the search-listing event, plus two run-start fees at $0.005 each that Apify’s platform charges automatically. Total: about $0.17. The MCP layer itself adds nothing on top of what you’d pay running the actor manually in the Apify Console. Each tool call took about 11 to 12 seconds end to end.
Why did Claude say some transactions had no price per square foot? Because transactions mode also returns car-parking-space deals. In our 40-record pull, 7 had building set to a parking designation, with area and price-per-square-foot fields all null. We told Claude to filter out rows where net_unit_price is null before computing a median — otherwise parking prices get mixed into a residential median.
Can I ask about a specific estate using Midland’s midland-scraper instead? Not by name. Midland’s own API only accepts region-level filters (Hong Kong Island, Kowloon, New Territories) — an estate name or keyword is silently ignored. You can have Claude pull a whole region first and then filter the output’s own estate field down to the one you want. If you need to search by estate name directly, use centaline-scraper.
Can this result tell me whether prices are trending up or down? No. This was a single snapshot taken on October 12, 2026: one estate, 33 transactions over roughly two months, and the site’s default-sorted first 40 listings — not every listing on the market. It tells you how today’s asking prices compare with recent deals for that one estate; it says nothing about a rising or falling market, and it isn’t investment advice.
Further reading
- Is That Hong Kong Listing Actually For Sale?: the same
centaline-scraper,28hse-scraperandmidland-scrapercomparison, used here to cross-check a single agent’s claims instead of asking Claude. - Hong Kong’s CCL Index Is Up 12% — Yet One Estate Still Sold at a Loss: why even a correct snapshot like this one can’t be read as “the market.”
- Monitor Bahamut in English with Claude Code + Apify MCP: the same MCP-agent pattern applied to a Chinese-language gaming forum instead of property data.
Chad runs 30+ published Apify actors, including the centaline-scraper and midland-scraper used here. The Taikoo Shing figures above come from a real run through Apify’s official MCP server on October 12, 2026; cost and timing are from that same run. Only the “ten estates a week” extrapolation is a price-list calculation, not a measurement.