# Centaline HK Property Listings Scraper (`ardent_fork/centaline-hk-property`) Actor

Rent and buy listings from Centaline Property, Hong Kong's largest estate agency: price, rent, size, unit price, district, estate, bedrooms, MTR distance, coordinates.

- **URL**: https://apify.com/ardent\_fork/centaline-hk-property.md
- **Developed by:** [KF P](https://apify.com/ardent_fork) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Centaline HK Property Listings Scraper

Scrapes residential listings from [Centaline Property](https://hk.centanet.com/findproperty/en/list/rent), Hong Kong's largest estate agency (~10k rentals, ~33k sale listings). Public pages only, no login.

No login, no API key, no proxy needed. Pay-per-event: **one `listing` event per listing saved**; list requests that return nothing cost nothing.

### Output (one record per listing)

| field | example |
|---|---|
| `refNo`, `id` | `GAJ917` |
| `mode` | `rent` or `buy` |
| `url` | detail page |
| `title`, `estate`, `phase`, `building`, `address` | `Grand Mayfair・Phase 1A…・Tower 5` |
| `region`, `district`, `area` | `New Territories West`, `Yuen Long District`, `Kam Tin` |
| `buildingType`, `unitType`, `isHouse`, `bedrooms`, `buildingAge`, `direction` | `Apartment`, `Simplex`, `2`, `1`, `South West` |
| `sizeSqft` | saleable area, `384` |
| `price`, `rent` | HKD asking price / monthly rent (either may be null) |
| `unitPriceSqft`, `unitRentSqft`, `monthlyPayment`, `yieldPct` | derived numbers from the site |
| `hasKey`, `exclusive`, `petFriendly`, `foreclosure`, `hosFlat`, `tags` | flags and feature tags |
| `mtr` | `[{ name: "Kam Sheung Road", walkMinutes: 7 }]` |
| `lat`, `lng`, `publishDate`, `updateDate`, `thumbnail` | |

### Input

Example: rentals in Taikoo Shing between HK$15k and HK$30k a month —

```json
{ "mode": "rent", "locations": ["Taikoo Shing"], "minPrice": 15000, "maxPrice": 30000, "maxItems": 200 }
```

- `mode` — `rent` (default) or `buy`.
- `language` — `en` (default), `zh-hk` or `zh-cn`; controls every text field.
- `locations` — optional list of districts / estates / buildings / MTR stations, in any language (`["Taikoo Shing", "沙田"]`). Entries are OR-ed, but must all be the same kind (all districts, or all estates, or all phases / buildings / MTR stations) — the API AND-s different kinds and returns nothing, so the actor refuses such input. Each name is resolved through the site's own autocomplete (exact English/Chinese label match preferred, else the first district, then estate, building, MTR hit); raw site tokens like `HMA034` (district), `3-OVDUURFSRJ` (estate), `2-…` (phase), `1-…` (building) or `mtr-58` are used as-is. An unknown name fails the run rather than silently scraping all of Hong Kong.
- `minPrice` / `maxPrice` — HKD; monthly rent in `rent` mode, sale price in `buy` mode.
- `maxItems` (default 100), `startPage` (default 1), `maxPages` per URL (default 200).
- `proxyConfiguration` — optional; the site is served without bot challenges, datacenter proxies are enough for big runs.

### Pricing

Pay-per-event: one `listing` event is charged per listing pushed to the dataset. Nothing else is charged. If a run's budget (`maxTotalChargeUsd`) is exhausted before `maxItems`, the actor stops cleanly with the listings it could pay for and reports it in the status message.

### How it works

The list page is server-rendered only for the first 24 results; the site's SPA then paginates through `POST hk-api.centanet.com/centanetapi/api/Post/Search` (offset/size). The actor calls that endpoint directly, in the site's own ranking order, and de-duplicates by listing id (the ranking is not perfectly stable between calls). `src/parse.js` also contains a parser for the `window.__NUXT__` SSR payload, evaluated in an empty, time-limited VM sandbox, used by the fixture tests and kept as a fallback.

### Local development

```
npm install
npm test          # parser tests against fixtures/
apify run -i '{"mode":"rent","maxItems":30}'
```

Refresh fixtures with a browser user-agent: `curl -A "Mozilla/5.0 …" https://hk.centanet.com/findproperty/en/list/rent > fixtures/rent-page1.html`.

### Limitations

- One run filters by one kind of location (districts, or estates, or buildings/phases/MTR stations); size, bedroom and school-net filters are not exposed yet.
- Transaction history and the detail-page fields (floor plan, agent) are client-side rendered and not scraped in v1.
- Field names on the site can change; if a run fails with "Listing array not found", the `__NUXT__` layout moved.

# Actor input Schema

## `mode` (type: `string`):

Scrape properties for rent or for sale.

## `language` (type: `string`):

Language of text fields (names, districts, tags).

## `locations` (type: `array`):

Districts, estates, phases, buildings or MTR stations to restrict the search to, in any language (e.g. "Taikoo Shing", "太古城", "Sha Tin"). All entries must be the same kind (e.g. several districts, or several estates) and are combined with OR; the site AND-s different kinds and returns nothing. Raw site tokens are accepted as-is: HMA034 (district), 3-… (estate), 2-… (phase), 1-… (building), mtr-58 (MTR station). Leave empty for all of Hong Kong. An unknown name fails the run.

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

Minimum monthly rent (rent mode) or sale price (buy mode), in HKD.

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

Maximum monthly rent (rent mode) or sale price (buy mode), in HKD.

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

Stop after this many unique listings (across all list URLs).

## `startPage` (type: `integer`):

First results page to fetch (24 listings per page).

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

Safety cap on pages fetched per list URL.

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

Proxy settings. The API answers without proxies; use Apify datacenter proxies for large runs.

## Actor input object example

```json
{
  "mode": "rent",
  "language": "en",
  "locations": [
    "Taikoo Shing"
  ],
  "minPrice": 15000,
  "maxPrice": 30000,
  "maxItems": 200,
  "startPage": 1,
  "maxPages": 200,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

Dataset items, one per Centaline property listing (rent or buy). Fields are described in the README.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("ardent_fork/centaline-hk-property").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("ardent_fork/centaline-hk-property").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call ardent_fork/centaline-hk-property --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ardent_fork/centaline-hk-property"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/XxamhVHEiGZdDgaFS/builds/UMWpZZliszAM23eEh/openapi.json
