# Nhatot Scraper - Vietnam Real Estate Listings (`hgservices/nhatot-scraper`) Actor

Extract real estate listings from Nhatot.com, Vietnam's busiest property market. Scrape apartments, houses, land, offices, and rooms for sale or rent by keyword, region, and price. Get legal status, furnishing, size, price/m², images, seller info, GPS coordinates. Export to JSON, CSV, or Excel.

- **URL**: https://apify.com/hgservices/nhatot-scraper.md
- **Developed by:** [Harish Garg](https://apify.com/hgservices) (community)
- **Categories:** Real estate, Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 ad listing scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Nhatot Scraper — Vietnam Real Estate Listings

**Scrape property listings from [Nhatot.com](https://www.nhatot.com)**, Chotot's real-estate vertical and **Vietnam's busiest property marketplace**. This Actor extracts **apartments, houses, land, offices and rooms — for sale or for rent** — with the structured real-estate attributes buyers actually filter on: **legal document, property status, furnishing, size, and price per m²**. It is **fast and low-cost to run**.

Run it on the [Apify platform](https://apify.com) to get API access, scheduling, integrations, automatic proxy rotation, and run monitoring out of the box. Export every result to **JSON, CSV, Excel, or HTML**.

### What does Nhatot Scraper do?

It collects real-estate ads from Nhatot and returns one clean, structured record per listing. For each property you get the title, full description, price, images, GPS coordinates, seller info, and — when enrichment is on (the default) — the **labeled property attributes** that make real-estate data useful: legal paperwork, handover status, furnishing level, and the price per square metre.

### Why use Nhatot Scraper?

- **Market research & pricing** — track asking prices and price/m² by district, project, or property type.
- **Lead generation** — build lists of for-sale or for-rent listings with seller names and public profiles.
- **Investment analysis** — compare inventory and legal status across provinces and subcategories.
- **Property portals & aggregators** — feed a downstream site or CRM with fresh Vietnam listings.
- **Trend monitoring** — schedule a daily run and watch new supply enter the market.

### How to use Nhatot Scraper

1. Open the Actor in Apify Console and go to the **Input** tab.
2. Choose a **Listing type** — *For sale*, *For rent*, or *Both*.
3. Pick the **Property subcategories** you want (apartments, houses, land, offices, rooms). All five are selected by default.
4. Optionally narrow the search with a **keyword**, a **region/province**, or a **price range** (VND).
5. Set **Max items per subcategory** (default 50) and leave **enrichment** on for the structured attributes.
6. Click **Start**. When the run finishes, open the **Output** tab and download the dataset in your preferred format.

#### Sale vs. rent (and Phòng trọ)

Nhatot separates *for sale* (Cần bán) from *for rent* (Cho thuê). One special case: **Phòng trọ (Rooms) exist only as rentals** — there are no for-sale rooms. If you select *For sale* together with only the Rooms subcategory, the Actor stops immediately with a clear error. When you scrape the default full set as *For sale*, Rooms is simply skipped with a warning. Choose *For rent* or *Both* to include rooms.

The rarer **wanted ads** (Cần mua / Cần thuê — posted by seekers, not sellers) are hidden behind the **Include wanted ads** toggle and are off by default.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `listingType` | select: `sale` / `rent` / `all` | `sale` | For sale, for rent, or both. |
| `includeWantedAds` | boolean | `false` | Also scrape wanted-to-buy / wanted-to-rent ads. |
| `subcategoryIds` | multi-select | all five | Apartments (1010), Houses (1020), Land (1040), Offices (1030), Rooms (1050). |
| `search` | string | — | Full-text keyword (project name, street, ward…). |
| `regionId` | select | Any | Limit to a single of the 63 provinces. |
| `priceFrom` / `priceTo` | integer (VND) | — | Price range. Total price for sale; monthly for rent. |
| `maxItems` | integer | `50` | Number of ads to fetch **per subcategory**. |
| `enrichDetails` | boolean | `true` | Add structured property attributes (legal document, status, furnishing, price/m²) to every ad. |

`maxItems` is a **per-subcategory** cap. With the default 50 and all five subcategories, a single run returns up to ~250 items. Increase it (or filter by region/price) for deeper backfills.

### Output

Each dataset item looks like this (trimmed):

```json
{
  "adId": 177585277,
  "listId": 133674683,
  "url": "https://www.chotot.com/133674683.htm",
  "title": "Bán căn hộ 2PN Vinhomes Grand Park",
  "price": 8500000000,
  "priceString": "8,5 tỷ",
  "propertyType": "Căn hộ/Chung cư",
  "listingType": "sale",
  "rooms": 2,
  "sizeM2": 98,
  "apartmentType": 1,
  "regionName": "Tp Hồ Chí Minh",
  "areaName": "Quận 7",
  "wardName": "Phường Tân Hưng",
  "latitude": 10.74506,
  "longitude": 106.69885,
  "images": ["https://cdn.chotot.com/....jpg"],
  "listedAt": "2026-08-02T03:49:45.000Z",
  "seller": { "id": 30397140, "name": "Seller", "liveAds": 5 },
  "legalDocument": "Sổ hồng riêng",
  "propertyStatus": "Đã bàn giao",
  "furnishing": "Nội thất đầy đủ",
  "pricePerM2": 86.73,
  "attributes": {
    "property_legal_document": "Sổ hồng riêng",
    "property_status": "Đã bàn giao",
    "furnishing_sell": "Nội thất đầy đủ",
    "price_m2": "86,73 triệu/m²",
    "rooms": "2 phòng",
    "size": "98 m²",
    "address": "..."
  }
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

#### Data fields

| Field | Description |
|---|---|
| `adId`, `listId` | Ad and listing identifiers. |
| `url` | Stable `chotot.com` short URL for the ad. |
| `title`, `description` | Ad headline and full body text. |
| `price`, `priceString` | Numeric price (VND) and the display string (e.g. `8,5 tỷ`). |
| `propertyType` | Apartment / house / land / office / room. |
| `listingType` | `sale`, `rent`, `wanted_buy`, or `wanted_rent`. |
| `rooms`, `sizeM2`, `apartmentType` | Bedrooms, area in m², apartment type code. |
| `regionName`, `areaName`, `wardName` | Province, district, ward. |
| `latitude`, `longitude` | GPS coordinates. |
| `images`, `numberOfImages` | Full-size photo URLs. |
| `listedAt`, `relativeDate` | ISO timestamp and the Vietnamese relative-time string. |
| `seller` | Seller id, name, avatar, and live-ad count. |
| `legalDocument`, `propertyStatus`, `furnishing` | Flattened key property attributes. |
| `pricePerM2` | Numeric price per m² (triệu VND/m²). |
| `attributes` | Full id → value map of labeled property attributes (when enriched). |

#### The structured attributes — the headline feature

Generic scrapers hand you a wall of description text. This Actor decodes Nhatot's **labeled real-estate attributes** into clean fields. The three most-asked ones — **legal document** (Giấy tờ pháp lý), **property status** (Tình trạng BĐS), and **furnishing** (Nội thất) — are promoted to top-level columns, and `pricePerM2` is parsed into a number you can sort and filter on. The complete set lives in the `attributes` map (toilets, block, apartment features, full address, and more).

### How much does it cost to scrape Nhatot?

This Actor is **pay-per-result**. You are charged per listing delivered, plus a small add-on per item that is enriched with structured attributes. A typical enriched item costs roughly **$2 per 1,000 items** — real-estate data with decoded legal/furnishing/price-per-m² attributes. Turn `enrichDetails` off to skip the enrichment charge if you only need the basic listing. New Apify accounts include monthly free usage to try it out.

Because the property vertical is relatively compact, even a full enriched sweep is inexpensive and completes quickly — ideal for a scheduled daily refresh.

### Tips & advanced options

- **Limit cost** — lower `maxItems`, deselect subcategories, or turn off `enrichDetails`.
- **Deeper backfills** — the Actor automatically splits dense subcategories by region, then district, then price band, so large result sets are collected reliably and completely. Filter by `regionId` or price to focus the crawl.
- **Daily monitoring** — schedule a run and dedupe downstream on `listId` to detect new supply.
- **Advanced input** — power users can pass extra district/ward geo-filters and a custom `proxyConfiguration` directly in the input JSON, even though they are not shown as form fields. A proxy is normally unnecessary.

### FAQ, disclaimers & support

**Is scraping Nhatot legal?** This Actor collects only publicly available listing data and does not bypass logins or access private information. You are responsible for using the output in line with Nhatot's Terms of Service and applicable laws (including personal-data rules). Do not use the data for spam or unlawful purposes.

**Why do the URLs point to chotot.com?** Public ad URLs on `chotot.com` redirect to the canonical Nhatot page for the same listing. The short `chotot.com` URL is stable and always resolves, so it is the one stored.

**Known limitations.** The Actor does not return property project/development data, historical price trends, revealed phone numbers, or agency profiles — these are out of scope.

**Feedback & issues.** Found a bug or need an extra field? Open a ticket on the **Issues** tab. Custom scraping solutions are available on request.

### Changelog

#### 0.1

- Initial release: sale/rent/wanted filtering, five property subcategories, region and price filters, structured attribute enrichment (legal document, status, furnishing, price/m²), and automatic backfill of large result sets.

# Actor input Schema

## `listingType` (type: `string`):

Scrape properties for sale, for rent, or both. Note: Phòng trọ (Rooms) exist only as rentals — selecting them with "For sale" fails with a clear error.

## `includeWantedAds` (type: `boolean`):

Also scrape "wanted to buy" (Cần mua) and "wanted to rent" (Cần thuê) ads. These are posted by seekers rather than sellers and are far less common. Off by default.

## `subcategoryIds` (type: `array`):

Which property subcategories to scrape. Defaults to all five.

## `search` (type: `string`):

Full-text keyword (project name, street, ward…). Combinable with every filter below. Leave empty to scrape whole subcategories.

## `regionId` (type: `string`):

Limit results to a single province. Leave as "(Any region)" to scrape nationwide.

## `priceFrom` (type: `integer`):

Lower price bound in Vietnamese đồng. Total price for sale; monthly price for rent. Leave empty for no minimum.

## `priceTo` (type: `integer`):

Upper price bound in Vietnamese đồng. Total price for sale; monthly price for rent. Leave empty for no maximum.

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

Number of ads to fetch for EACH selected subcategory. Total output is at most this number times the number of subcategories (e.g. 50 × 5 subcategories = up to 250 items).

## `enrichDetails` (type: `boolean`):

Add an `attributes` object plus flattened `legalDocument`, `propertyStatus`, `furnishing` and numeric `pricePerM2` fields to every ad. On by default — these attributes are the headline feature. Slightly slows the run and adds a per-item enrichment charge.

## Actor input object example

```json
{
  "listingType": "sale",
  "includeWantedAds": false,
  "subcategoryIds": [
    "1010",
    "1020",
    "1040",
    "1030",
    "1050"
  ],
  "search": "Vinhomes Grand Park",
  "regionId": "",
  "maxItems": 50,
  "enrichDetails": true
}
```

# 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 = {
    "listingType": "sale",
    "subcategoryIds": [
        "1010",
        "1020",
        "1040",
        "1030",
        "1050"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("hgservices/nhatot-scraper").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 = {
    "listingType": "sale",
    "subcategoryIds": [
        "1010",
        "1020",
        "1040",
        "1030",
        "1050",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("hgservices/nhatot-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "listingType": "sale",
  "subcategoryIds": [
    "1010",
    "1020",
    "1040",
    "1030",
    "1050"
  ]
}' |
apify call hgservices/nhatot-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=hgservices/nhatot-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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