28Hse Scraper – Hong Kong Property Listings, FSBO & Details avatar

28Hse Scraper – Hong Kong Property Listings, FSBO & Details

Pricing

from $2.00 / 1,000 property listings

Go to Apify Store
28Hse Scraper – Hong Kong Property Listings, FSBO & Details

28Hse Scraper – Hong Kong Property Listings, FSBO & Details

Scrape 28Hse, a Hong Kong property portal, without an API or login: sale and rental listings plus full property details — price, saleable area, unit price, layout, district and estate, with agent vs owner (FSBO) marker. Unique owner asking-price data for HK property valuation. Export JSON/CSV/Excel.

Pricing

from $2.00 / 1,000 property listings

Rating

0.0

(0)

Developer

Chad

Chad

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

28Hse Scraper – Hong Kong Property Listings & FSBO Details (No API)

Scrape 28Hse.com (Hong Kong's property portal): property listings and full single-property detail, via public HTML endpoints (SSR + JSON-LD) — no login, no token. Structured output, and FSBO (owner-listed) detection is this Actor's core feature — a data dimension agency-only sites don't expose, useful for valuation models, proptech, or agency research teams looking to fill out asking-price data.

Complements the same author's centaline-scraper (Centaline transaction records): centaline covers completed transactions, this Actor covers active listing detail and FSBO filtering.

Output fields

Property listings (listing mode)

FieldTypeDescription
property_idstringProperty ID
titlestring | nullTitle
deal_typestring | nullbuy or rent
property_typestring | nullProperty type, e.g. apartment
pricenumber | nullPrice (HKD). The raw text "售 $830 萬元" is converted to 8300000
saleable_areanumber | nullSaleable area (sqft)
gross_areanumber | nullGross floor area (sqft). Listing cards don't show gross area, so this field is always null in listing mode — only detail mode populates it
unit_pricenumber | nullUnit price per saleable sqft (HKD)
districtstring | nullDistrict, e.g. "Tsuen Wan"
estatestring | nullEstate name
roomsnumber | nullRoom count. Open-plan units (no separate rooms) honestly return null instead of a guess
bathroomsnumber | nullBathroom count
is_ownerbooleanFSBO (owner-listed) detection. The page marking "業主盤" / "業主自讓" (owner listing) = true; agent listing or no marking = false
agent_namestring | nullAgency name; for FSBO listings, the owner contact name shown on the page
posted_atstring | nullPosted time (ISO 8601). The raw value is relative ("36 seconds ago", "N days ago"), converted to an absolute timestamp
listing_urlstring | nullFull listing URL
source_modestringAlways listing
scraped_atstringScrape time (ISO 8601)

Property detail (detail mode, all fields above + the following)

FieldTypeDescription
addressstring | nullFull address
floor_size_sqftnumber | nullSaleable area (sqft), same source as saleable_area
num_roomsnumber | nullThe raw room-count field from the listing page's own JSON-LD. Note: this is the site's own JSON-LD structured value, and in testing it doesn't always match the "N 房" (N rooms) shown on the page (the rooms field above) — see Notes below. Both fields are kept, each honestly reporting its own source
descriptionstring | nullFull listing/estate description
agent_addressstring | nullAgency (or owner contact) address
agent_urlstring | nullAgency (or owner) page link
date_publishedstring | nullPosted time (ISO 8601, with timezone)
date_modifiedstring | nullLast-updated time (ISO 8601, with timezone)
image_countnumber | nullTotal number of listing images (including floor/unit plans)

Modes

ModeInputOutputBillingStatus
📋 listingdealType + propertyType (or listingUrls)Property listingssearch-listing $0.002/itemv1.0
🏠 detailpropertyIds or propertyUrlsFull single-property fieldsproduct-detail $0.008/itemv1.0
📈 transactionsestateUrls (estate transaction records)Transaction recordsreview-item $0.003/itemNot yet available in v1.1 — selecting this mode returns an error

All charges happen only after data is successfully pushed to the dataset. The run's end-of-run log prints total_items / charged / skipped so you can reconcile.

Input fields

FieldTypeDefaultDescription
modeenumlistinglisting / detail / transactions (not yet available, see table above) (required)
dealTypeenumbuybuy or rent. Used by listing mode; also needed in detail mode when using propertyIds (instead of propertyUrls)
propertyTypeenumapartmentProperty type. Only "Apartment" has been fully tested; other types use the same URL pattern but haven't each been individually verified
listingUrlsarrayListing mode only, directly specify listing page URLs (overrides dealType/propertyType), multiple allowed, each paginated and counted independently
propertyIdsarrayDetail mode, property IDs (numeric only), needs dealType/propertyType to build the URL
propertyUrlsarrayDetail mode, full property URLs, safest since deal/type info is already in the URL
bulkInputtextareaBulk paste, one item per line, merged into the matching field based on the current mode
ownerOnlybooleanfalseListing mode only: only keep FSBO listings, filtering out agent listings. FSBO listings are usually rarer within a single category — if 5 consecutive pages return no matches, the run stops early (see Notes below)
maxItemsinteger50Listing mode: max items per listing source; detail mode: max properties to scrape. Maximum 500
dateFromstringListing mode only, filters by listing posted time. Format 3d, 12h, 2w (relative) or MM/DD/YY (absolute date). When set, paging also stops early, which keeps scheduled monitoring cheaper. Not applicable to detail mode
proxyConfigurationproxyApify datacenter proxyOn by default; without a proxy your run shares egress IPs with other runs and gets rate-limited. Turn off only for your own proxy or local testing

Input examples

1. Property listings: apartments for sale

{
"mode": "listing",
"dealType": "buy",
"propertyType": "apartment",
"maxItems": 50
}

2. Property detail: a single property

{
"mode": "detail",
"propertyUrls": ["https://www.28hse.com/buy/apartment/property-3948689"]
}

3. FSBO only, rentals

{
"mode": "listing",
"dealType": "rent",
"propertyType": "apartment",
"ownerOnly": true,
"maxItems": 100
}

4. Bulk-scrape multiple property IDs

{
"mode": "detail",
"dealType": "buy",
"propertyType": "apartment",
"bulkInput": "3948689\n3924956\n3990751"
}

5. Scheduled monitoring: only listings posted in the last 3 days

{
"mode": "listing",
"dealType": "buy",
"propertyType": "apartment",
"dateFrom": "3d",
"maxItems": 200
}

Notes

  • Only scrapes public content — no account or token required, uses public HTML endpoints (SSR + JSON-LD), no browser, fast and low-cost
  • Price parsing: the raw text "售 $830 萬元" ("萬" = 10,000) is automatically converted to a number (× 10,000 = 8,300,000); rental prices usually have no "萬" unit and are taken as-is
  • FSBO (is_owner) detection: only returns true when the page explicitly marks a listing as "業主盤" / "業主自讓" (owner-listed). A title that merely mentions "業主" (owner) in passing (e.g. "friend of the owner, price negotiable") is not mistaken for FSBO — that's still an agent listing, and is_owner correctly returns false
  • ownerOnly cost-protection mechanism: FSBO listings are usually much rarer than agent listings within a single category (e.g. "buy · apartment"). To avoid the crawler paging forever burning cost in a category with no FSBO listings at all, this Actor follows the rule "stop after 5 consecutive requests with no matching data" — with ownerOnly enabled, if 5 consecutive pages have no FSBO listings, the run stops immediately, even if the category theoretically still has more (agent-only) listings left. If FSBO listings happen to be clustered on later pages, some may be missed as a result; narrower filters (splitting runs by dealType/propertyType) increase FSBO density and reduce this risk
  • Why rooms and num_rooms are two separate fields: rooms (shared by listing and detail mode) comes from the "N 房" (N rooms) text shown on the page (reliable, matches what's displayed); num_rooms (detail mode only) is the raw room-count field from the site's own JSON-LD structured data. In testing, the two can disagree for the same property (e.g. a listing page displays "3 房" but its JSON-LD numberOfRooms is 1) — this is a discrepancy in 28Hse's own data source, not a parsing error by this Actor. Both fields are kept as-is, each honestly reporting its own source, with no field overriding the other
  • Open-plan units (no separate room partitions) honestly return null for rooms rather than guessing 0 or 1
  • gross_area (gross floor area) is only populated in detail mode — listing cards only show saleable area, not gross area
  • Paging stops automatically after 5 consecutive pages with no new data, to avoid burning cost for nothing; if dateFrom is set, paging also stops as soon as an entire page of listings is older than dateFrom (further reduces cost, listing mode only)
  • Estate transaction records (transactions mode) are not yet available, planned for v1.1. Selecting this mode currently returns an error message immediately and consumes no charge
  • 28Hse currently shows no anti-bot challenge (no CAPTCHA/JS challenge) against the datacenter proxy this Actor uses; if the site tightens defenses in the future, the fallback plan is to switch to a residential proxy — not over-engineered in advance

FAQ

Q: Why are district/estate/price null for some listings?

A: A small number of listing cards have an incomplete layout (e.g. carparks, non-residential listings, or the listing itself is missing data). This Actor honestly returns null rather than substituting a guessed value.

Q: ownerOnly returns no FSBO listings at all — is that normal?

A: Yes. FSBO listings are naturally rarer than agent listings; if 5 consecutive pages have no matches, the run stops early (see Notes above) — this is a deliberate cost-protection mechanism, not a bug. Try a different dealType/propertyType combination, or check the 28Hse site directly to confirm whether that category currently has any active FSBO listings.

Q: What's the difference between propertyIds and propertyUrls?

A: propertyUrls (full URLs) already carry deal type and property type info, making them the safest choice; propertyIds (numeric IDs only) require dealType/propertyType to build the correct URL. The two can also be mixed.

Q: Why is gross_area (gross floor area) always null in listing mode?

A: 28Hse's listing cards only show saleable area, not gross floor area; gross floor area only appears on the property detail page, so only detail mode output has a value. If you need gross floor area, use detail mode for the relevant properties.

Q: When will estate transaction records (Land Registry data) be available?

A: Planned for v1.1. 28Hse's transaction records go through an AJAX endpoint, and the full set of request parameters hasn't been confirmed yet — this will be added once confirmed, at which point mode will simply gain another available option, with no need to switch to a different Actor.

Disclaimer

This tool is intended for academic research and lawful business analysis only. Users must comply with 28Hse's terms of service and applicable laws. Do not use this tool to infringe on others' privacy, spread false information, or engage in any other unlawful activity. The author is not responsible for any misuse.


28Hse scraper, Hong Kong property, HK real estate data, FSBO listings, property listings, HK property prices