hk_property_transactions
Registered HK property sales with price and $/sqft
Download a file
CSV and Parquet. Filtered exports.
See pricingQuery with SQL
DBeaver, DuckDB, MotherDuck, or HTTPS. Sub-second latency.
Open connection detailsConnect to AI
MCP for Claude Desktop, Cursor, ChatGPT, Goose. 1-line install.
See setupRegistered Hong Kong residential property transactions as recorded by Centaline (Centadata). One row per Land Registry memorial: registration date, consideration (price), saleable and gross floor areas, and price per square foot on both bases. The core fact table for property analytics.
Evaluate it in full below: the evidence and a working sample are open to everyone. Buy or subscribe to unlock the complete dataset — your account is created automatically at checkout.
The evidence
Rows over time
monthSchema & column quality (78 columns)
Scroll table sideways to see more columns →
| Column | Type | Description | Populated | Distinct |
|---|---|---|---|---|
| transaction_id | String | Land Registry memorial number — unique identifier for the registered transaction | — | — |
| unit_code | Nullable(String) | Centaline unit code — links to hk_property_units | — | — |
| building_code | Nullable(String) | Centaline building code — links to hk_property_buildings | — | — |
| phase_code | Nullable(String) | Centaline phase code — the development phase the building belongs to; links to hk_property_phases. Taken from the building's own record, because the sale records carry it inconsistently; null when unknown | — | — |
| estate_code | Nullable(String) | Centaline estate code — the large multi-phase development the building belongs to; links to hk_property_estates. Taken from the building's own record; null for standalone single-phase developments or buildings not yet matched | — | — |
| tx_date | Date | Registration date in the Hong Kong calendar (YYYY-MM-DD) | — | — |
| price_hkd | Nullable(Float64) | Consideration (transacted price) in Hong Kong dollars | — | — |
| saleable_area_sqft | Nullable(Float64) | Saleable area in square feet (實用面積) — as this sale reported it, else from the unit's other records or imputed from the building's ratio (see saleable_area_source); null where unknown | — | — |
| saleable_area_source | Nullable(String) | Provenance of saleable_area_sqft — 'transaction' (THIS sale reported it), 'unit_dimension' (filled from a frozen Centaline unit master or another sale of the same unit), 'imputed' (per-building ratio imputation); null when unknown | — | — |
| saleable_area_is_imputed | Bool | True when saleable_area_sqft was imputed from the building's mean gross/saleable ratio (mirrors saleable_area_source = 'imputed') | — | — |
| gross_area_sqft | Nullable(Float64) | Gross area in square feet (建築面積) — as this sale reported it, else from the unit's other records or imputed from the building's ratio (see gross_area_source); null where unknown | — | — |
| gross_area_source | Nullable(String) | Provenance of gross_area_sqft — 'transaction', 'unit_dimension' or 'imputed' (see saleable_area_source); null when unknown | — | — |
| gross_area_is_imputed | Bool | True when gross_area_sqft was imputed from the building's mean gross/saleable ratio (mirrors gross_area_source = 'imputed') | — | — |
| price_per_saleable_sqft | Nullable(Float64) | Price divided by the TRANSACTION-REPORTED saleable area (HK$/sqft) — never computed from filled/imputed areas; null when the sale reported no saleable area | — | — |
| price_per_gross_sqft | Nullable(Float64) | Price divided by the TRANSACTION-REPORTED gross area (HK$/sqft) — never computed from filled/imputed areas; null when the sale reported no gross area | — | — |
| block | Nullable(String) | Block/tower label (English) — this sale's own label, else the unit's, else the building's own designator; null whenever the label says nothing beyond the building's own name (each tower is its own building, so this is almost always null) | — | — |
| floor | Nullable(String) | Floor designation (e.g. 30/F) — this sale's own label, else the unit's; the oldest records carry none | — | — |
| flat | Nullable(String) | Flat/unit designation (e.g. FLAT C) — this sale's own label, else the unit's; the oldest records carry none | — | — |
| flat_letter | Nullable(String) | Bare flat token, normalised across eras (FLAT A / A室 → A, FLAT 1 / 1室 → 1); unrecognised forms pass through; null when the raw flat label is blank. The clean structured companion to `flat` | — | — |
| floor_number | Nullable(Int64) | Absolute floor parsed from the floor label (this sale's own label, else the unit dimension's): 27樓/27/F/二十七樓 → 27, G/F and 地下 → 0, basements negative, ranges (14-15樓) → the lower bound; null where only a band or a special named floor (see named_floor) was reported | — | — |
| floor_band | Nullable(String) | Coarse floor band ('high'/'middle'/'low') when no floor number could be resolved for the unit (this sale's label or the unit dimension's) — mutually exclusive with floor_number; null otherwise | — | — |
| named_floor | Nullable(String) | Canonical token for a special floor that carries no integer floor (M/F, P/H, Podium, B/M, Roof) — mutually exclusive with floor_number. Compose a display label as coalesce(named_floor, floor_number || '/F'); null for ordinary numbered floors and non-floor labels | — | — |
| unit_grid_x | Nullable(Int64) | Building-grid column position of the unit (0-based flat-column ordinal); native Centaline grid where available, else a derived rank — see unit_grid_source | — | — |
| unit_grid_y | Nullable(Int64) | Building-grid floor position of the unit (0-based, dense, basement-aware) — the per-building floor rank; pairs with unit_grid_x for a per-building flat-grid heatmap | — | — |
| unit_grid_source | Nullable(String) | 'native' (Centaline's own grid, stable) or 'derived' (ranked from parsed floors/flat labels; may shift as new floors transact); reflects EITHER coordinate being populated — null only when both unit_grid_x and unit_grid_y are null | — | — |
| prev_price_hkd | Nullable(Float64) | Consideration of the unit's previous registered sale (HK$); null when there was no prior sale or its price wasn't recorded | — | — |
| prev_tx_date | Nullable(Date) | Registration date of the unit's previous sale; null for first-hand/never-resold units. Present back to 1995 from the deep-history feed | — | — |
| gain_percent | Nullable(Float64) | Percentage change against the previous sale price, to one decimal where it can be re-derived from the recorded prices (otherwise Centaline's whole-number figure); null when there is no prior sale or its price is unknown | — | — |
| held_days | Nullable(Int64) | Days between the previous sale and this sale (holding period); null when there was no prior sale | — | — |
| ins_date | Nullable(Date) | Instrument/agreement date — when the deal was actually struck, on or before the registration date (tx_date). The true transaction date for timing analysis; kept alongside tx_date, never substituted for it | — | — |
| centa_phase_id | Nullable(Int64) | Centaline numeric phase id — a stable integer join key for the phase, independent of the alphanumeric phase_code; taken from the building's own record | — | — |
| centa_estate_id | Nullable(Int64) | Centaline numeric estate id — a stable integer join key for the estate, independent of estate_code; null for standalone single-phase developments | — | — |
| centa_bldg_id | Nullable(Int64) | Centaline numeric building id — stable integer alternate key to building_code; legacy-rich feeds only | — | — |
| centa_unit_id | Nullable(Int64) | Centaline numeric unit id — stable integer alternate key to unit_code; legacy-rich feeds only | — | — |
| usage_code | Nullable(String) | Property usage code (RE=private residential, RH=Home Ownership Scheme, RP=Private Sector Participation Scheme, RG/RR/RS/…); legacy-rich feeds only | — | — |
| usage_label_en | Nullable(String) | English label for usage_code — the human-readable HK housing-scheme name behind the code (e.g. RE→'PRIVATE RESIDENTIAL', RH→'HOME OWNERSHIP SCHEME', RP→'TENANTS PURCHASE SCHEME'). Null when usage_code is blank (pre-2018 / non-legacy-rich feeds) or unmapped | — | — |
| usage_label_zh | Nullable(String) | Traditional-Chinese label for usage_code — the HK housing-scheme name in Traditional Chinese (e.g. 私人住宅, 居者有其屋計劃, 租者置其屋計劃). Null when usage_code is blank (pre-2018 / non-legacy-rich feeds) or unmapped | — | — |
| is_residential | Nullable(Bool) | Residential classifier, tri-state: true (residential/HOS/subsidised usage, or a residential unit type on the live feed), false (known non-residential: carpark/commercial/industrial), null (deep history without usage codes — unknown, NOT non-residential) | — | — |
| unit_usage_code | Nullable(String) | Per-unit usage code (may differ from the estate-level usage_code, e.g. a carpark in a residential estate); legacy-rich feeds only | — | — |
| unit_usage_label_en | Nullable(String) | English label for unit_usage_code (same housing-scheme dictionary as usage_label_en). Null for the unit-only carpark codes (CP/SP/CM), which carry no scheme label in the source, or when the code is blank (pre-2018 / non-legacy-rich feeds) | — | — |
| unit_usage_label_zh | Nullable(String) | Traditional-Chinese label for unit_usage_code — the HK housing-scheme name in Traditional Chinese, same dictionary as usage_label_zh. Null for the unit-only carpark codes (CP/SP/CM) or when the code is blank (pre-2018 / non-legacy-rich feeds) | — | — |
| estate_type | Nullable(String) | Estate type classification from the modern centanet feed (e.g. Single, Normal); null on the legacy feeds | — | — |
| unit_type | Nullable(String) | Unit type classification from the modern centanet feed (e.g. AP); null on the legacy feeds | — | — |
| first_or_second_hand | Nullable(String) | Whether the sale is first-hand (developer/primary) or second-hand (resale); modern centanet feed only | — | — |
| bedroom_count | Nullable(Int64) | Number of bedrooms, where the modern centanet feed records it | — | — |
| direction | Nullable(String) | Aspect / compass orientation of the unit (e.g. 北, 東北), where recorded; modern centanet feed only | — | — |
| unit_remark | Nullable(String) | Unit-composition remark: bundled extras sold with the flat, as Centaline tokens — R#=roof/rooftop, P#=car park, G#=garden, C#, D# (combinable, e.g. R#P#). Null when none. ~2% of rows; explains price/$-psf outliers | — | — |
| has_rooftop | Nullable(Bool) | True when the unit_remark carries R# (a roof/rooftop is bundled in the sale); derived flag, null when unit_remark is null | — | — |
| has_car_park | Nullable(Bool) | True when the unit_remark carries P# (a car-park space is bundled in the sale); derived flag, null when unit_remark is null | — | — |
| has_garden | Nullable(Bool) | True when the unit_remark carries G# (a garden is bundled in the sale); derived flag, null when unit_remark is null | — | — |
| unit_price_saleable | Nullable(Float64) | Source-reported price per saleable square foot (HK$/sqft) — Centaline's own figure, complementary to the derived price_per_saleable_sqft | — | — |
| unit_price_gross | Nullable(Float64) | Source-reported price per gross square foot (HK$/sqft) — Centaline's own figure | — | — |
| unit_price_rvd | Nullable(Float64) | Rating-and-Valuation-Department unit price (HK$ per rateable-area unit); legacy-rich feeds only | — | — |
| rvd_area_sqm | Nullable(Float64) | Rating-and-Valuation-Department net area in square metres (note: sqm, not sqft); legacy-rich feeds only | — | — |
| building_age_years | Nullable(Int64) | Age of the building in years at the time of the transaction; legacy feeds carry it directly, the modern feed derives it from the building's completion year | — | — |
| gain_abs_hkd | Nullable(Float64) | Absolute capital gain vs the previous sale, in Hong Kong dollars; null when there was no prior sale; legacy-rich feeds only | — | — |
| gain_annualised_pct | Nullable(Float64) | Annualised percentage gain vs the previous sale; null when there was no prior sale; legacy-rich feeds only | — | — |
| prev_ins_date | Nullable(Date) | Instrument/agreement date of the unit's previous sale; null for first-hand/never-resold units | — | — |
| prev_memorial | Nullable(String) | Land Registry memorial number of the unit's previous sale (links back to that transaction_id); legacy-rich feeds only | — | — |
| prev_gross_area | Nullable(Float64) | Gross area (sqft) recorded at the unit's previous sale; legacy-rich feeds only | — | — |
| prev_unit_price | Nullable(Float64) | Price per gross square foot recorded at the unit's previous sale (HK$/sqft); legacy-rich feeds only | — | — |
| premium_status | Nullable(String) | Land-premium (補地價) status for subsidised-housing units: 未補 (premium not paid) / 已補 (premium paid); null for private-sector sales and where unknown | — | — |
| prn | Nullable(String) | Land Registry property reference number; legacy-rich feeds only | — | — |
| scp_id | Nullable(String) | Centaline internal scope id (fine geographic grouping); legacy-rich feeds only | — | — |
| clu_ccode | Nullable(String) | Centaline cluster code (geographic clustering); legacy-rich feeds only | — | — |
| district_code | Nullable(String) | Single-letter Centaline browse-area code (A–V) as the sale record gives it: U (Tseung Kwan O) and V (Lai King / Lai Wan) are Centaline sub-areas of Q (Sai Kung) and S (Kwai Tsing). Joins hk_property_buildings.sub_district_code; for the official district use hk_property_buildings.district_code via building_code. Null on the oldest records | — | — |
| hma_id | Nullable(String) | Centaline neighbourhood (HMA) identifier, e.g. HMA035; modern centanet feed only | — | — |
| scp_mkt | Nullable(String) | Macro market region: KL=Kowloon, NW=New Territories West, NE=New Territories East, HK=Hong Kong Island; modern centanet feed only | — | — |
| district_name_fine | Nullable(String) | Fine district name in Chinese (e.g. 屯門北); modern centanet feed only | — | — |
| hk_grid_x | Nullable(Float64) | Hong Kong 1980 Grid easting (HK80 metric coordinate); legacy-rich feeds only | — | — |
| hk_grid_y | Nullable(Float64) | Hong Kong 1980 Grid northing (HK80 metric coordinate); legacy-rich feeds only | — | — |
| street_view_lat | Nullable(Float64) | Street-view camera latitude (WGS84) for the unit, where captured; legacy-rich feeds only | — | — |
| street_view_long | Nullable(Float64) | Street-view camera longitude (WGS84) for the unit, where captured; legacy-rich feeds only | — | — |
| address_en | Nullable(String) | English address of the unit (full location string where available, else street), from the legacy-rich feeds | — | — |
| address_zh | Nullable(String) | Chinese address of the unit; sourced from the modern feed's address, the legacy Chinese street, or the deep-history dump's unit address | — | — |
| old_transaction_id | Nullable(String) | Centaline's prior internal transaction identifier (pre-migration id); modern centanet feed only | — | — |
| updated_at | DateTime64(3) | Timestamp when the record was last loaded | — | — |
| id | String | Stable unique identifier for this row — the last column of every export. Use it to deduplicate, to key an incremental load, or to reference one specific row. It is additive: the entity and join keys you already use (transaction_id, building_code) are unchanged. | — | — |
The most recent registered sales, full schema: price, floor areas, $/sqft on both bases, the unit's block/floor/flat and the building, phase and estate it belongs to.
Choose your access
A Pass gives you freshness within a rolling window. The Full Archive gives you the full history we hold for the dataset, frozen at purchase. They solve different problems, and they work together.
One-off purchase
Full Archive
The full history we hold, frozen at purchase. Yours to keep.
Full details →- What you get
- The full history we hold, to your purchase date
- History depth
- Jul 1995 – present, in full
- Updates
- None. Frozen at purchase
- Delivery
- Gzipped CSV, opens in Excel; link valid 7 days
- API access
- Not included
Pass subscription
Hong Kong Property — Property Pass
Continuously updated, with API access.
View full package →- Access window
- Full history (no window)
- Updates
- Continuous, within hours of the source
- Delivery
- API, SQL and downloads
- Exports
- 1,000,000 rows/month included
Included Datasets
Get notified when this dataset is updated.
Questions about this data?
Our data experts are ready to help clarify any aspects of this dataset.
Contact Our Team