# DDProperty Scraper (`shahidirfan/ddproperty-scraper`) Actor

Scrape property listings from DD websites with precision. Extracts prices, locations, descriptions & more. Residential proxy compulsory for reliable data collection. Perfect for real estate analytics, market research & investment tracking. High-speed, accurate property data extraction.

- **URL**: https://apify.com/shahidirfan/ddproperty-scraper.md
- **Developed by:** [Shahid Irfan](https://apify.com/shahidirfan) (community)
- **Categories:** Real estate, Automation, Developer tools
- **Stats:** 16 total users, 1 monthly users, 87.1% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.99 / 1,000 results

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

### What does DDProperty Scraper do?

DDProperty Scraper collects structured property listings for sale and rent from DDProperty, Thailand's leading real estate portal. Paste a DDProperty search page URL, choose sale or rent mode, set a result target, and the Actor returns clean property records with prices, rooms, floor and land area, address, district, region, project and developer names, nearby MRT stations, agent details, verification flags, photo galleries, and posting dates. Export the results as JSON, CSV, Excel, or XML, or feed them into dashboards, alerts, and CRM tools for market research, property monitoring, and lead generation.

DDProperty publishes thousands of active listings across Bangkok and the rest of Thailand but does not offer a bulk export for structured property data. This Actor fills that gap by collecting public listing data from search results and pagination, so you can build your own property datasets without manual copy-paste.

### Why use DDProperty Scraper?

- **Structured Thai property dataset** - Collect dozens of fields per listing including price, price per area, bedrooms, bathrooms, floor area, land area, property type, address, district, region, project, and developer without manual copy-paste.
- **Duplicate-safe collection** - Unique listings only, even when result pages overlap, so exported data stays clean for analysis.
- **Sale and rent coverage** - Run the same Actor for for-sale or for-rent inventory by changing one input field.
- **Automation-ready output** - Download results as JSON, CSV, Excel, or XML, or connect them to Google Sheets, webhooks, Make, or Zapier.
- **Market and lead research** - Compare pricing and property specs by district and region, track listing freshness, and build outreach lists from agent and project metadata.
- **Schedule for monitoring** - Use Apify schedules to refresh listing data hourly, daily, or weekly and watch how prices and inventory change over time.

### What data can you extract from DDProperty?

| Field | Description |
|-------|-------------|
| `price` | Numeric asking price |
| `priceText` | Formatted asking price text |
| `currency` | Currency code such as THB |
| `bedrooms` | Number of bedrooms |
| `bathrooms` | Number of bathrooms |
| `floorAreaSqm` | Floor area in square meters |
| `landAreaSqm` | Land area in square meters |
| `propertyType` | Property type such as Condo, House, or Townhouse |
| `address` | Full listing address |
| `district` | District name when available |
| `region` | Region or province name |
| `projectName` | Project or development name |
| `developerName` | Developer name when available |
| `agentName` | Listing agent name |
| `imageUrl` | Main listing image URL |
| `photoGallery` | Full gallery of listing photo URLs |
| `mrtNames` | Nearby MRT station names |
| `recencyText` | How recently the listing was posted |
| `postedOnUnix` | Posting date as a Unix timestamp |
| `listingType` | Sale or rent label |
| `isVerified` | Listing verification flag |
| `url` | Direct link to the listing |

### How to use DDProperty Scraper

1. Open the Actor on Apify Store.
2. Keep the default sale search URL or paste your own DDProperty search page URL.
3. Choose `sale` or `rent` for the listing type.
4. Set the number of results you want and the maximum page depth.
5. Run the Actor and review the dataset preview.
6. Download the results or connect them to your workflow.

The Actor stops automatically once it reaches your result target or the end of the available listings for the search. If you request 500 results but only 300 exist, you get 300 with a clear message.

### Input Parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `startUrl` | String | No | Default sale search URL | DDProperty search page URL to start from |
| `listingType` | String | No | `sale` | Listing mode: `sale` or `rent` |
| `isCommercial` | Boolean | No | `false` | Set `true` for commercial property searches |
| `results_wanted` | Integer | No | `20` | Maximum number of listings to save |
| `max_pages` | Integer | No | `5` | Safety cap on the number of result pages to visit |
| `proxyConfiguration` | Object | No | Thailand residential proxy preset | Optional Apify Proxy settings; Thailand (`TH`) residential routing is recommended for DDProperty |

### Output Data

Each record in the dataset contains a subset of these fields, with empty values removed automatically:

| Field | Type | Description |
|-------|------|-------------|
| `id` | String | Listing ID |
| `externalId` | String | External listing ID |
| `title` | String | Listing title |
| `url` | String | Direct listing URL |
| `listingType` | String | Sale or rent label |
| `propertyType` | String | Property type such as Condo or House |
| `statusCode` | String | Listing status code |
| `price` | Number | Numeric asking price |
| `priceText` | String | Formatted asking price |
| `pricePerArea` | String | Price per area text |
| `currency` | String | Currency code |
| `bedrooms` | Number | Bedroom count |
| `bathrooms` | Number | Bathroom count |
| `floorAreaSqm` | Number | Floor area in square meters |
| `landAreaSqm` | Number | Land area in square meters |
| `address` | String | Full listing address |
| `district` | String | District name |
| `region` | String | Region or province |
| `projectName` | String | Project or development name |
| `developerName` | String | Developer name when available |
| `agentName` | String | Listing agent name |
| `agentId` | Number | Agent ID |
| `agentVerified` | Boolean | Agent verification flag |
| `imageUrl` | String | Main listing image URL |
| `photoGallery` | Array | Full-resolution listing photo URLs |
| `availabilityText` | String | Availability label |
| `listedByText` | String | Listing source label |
| `badgeText` | String | Listing badge text |
| `viewedLabel` | String | Viewer activity label |
| `mrtNames` | Array | Nearby MRT station names |
| `featureTexts` | Array | Feature summary text values |
| `isVerified` | Boolean | Listing verification flag |
| `isOfficialListing` | Boolean | Official listing flag |
| `isDeveloperListing` | Boolean | Developer listing flag |
| `isDeveloperUnitListing` | Boolean | Developer unit listing flag |
| `isPrioritized` | Boolean | Prioritized listing flag |
| `isPhoneOtpEnabled` | Boolean | Phone verification flag |
| `accountTypeCode` | String | Listing account type |
| `recencyText` | String | Recency label |
| `postedOnText` | String | Display posting date |
| `postedOnUnix` | Number | Posting date as Unix timestamp |
| `sourceUrl` | String | Search page URL used for collection |
| `page` | Number | Search result page number |
| `scrapedAt` | String | ISO timestamp when the record was collected |

### Usage Examples

#### Basic Sale Listings

Collect the default sale search results with the built-in presets:

```json
{
  "startUrl": "https://www.ddproperty.com/en/property-for-sale?listingType=sale&isCommercial=false",
  "listingType": "sale",
  "isCommercial": false,
  "results_wanted": 20,
  "max_pages": 3
}
```

#### Rent Listings

Switch to rental inventory by changing the search URL and listing type:

```json
{
  "startUrl": "https://www.ddproperty.com/en/property-for-rent?listingType=rent&isCommercial=false",
  "listingType": "rent",
  "isCommercial": false,
  "results_wanted": 30,
  "max_pages": 4
}
```

#### Larger Collection with Proxies

Collect 200 sale listings with residential proxies for smoother large-scale runs:

```json
{
  "startUrl": "https://www.ddproperty.com/en/property-for-sale?listingType=sale&isCommercial=false",
  "listingType": "sale",
  "isCommercial": false,
  "results_wanted": 200,
  "max_pages": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "TH"
  }
}
```

#### Commercial Search

Collect commercial property listings with a commercial search URL:

```json
{
  "startUrl": "https://www.ddproperty.com/en/property-for-sale?listingType=sale&isCommercial=true",
  "listingType": "sale",
  "isCommercial": true,
  "results_wanted": 20,
  "max_pages": 5
}
```

### Sample Output

```json
{
  "id": "60125081",
  "externalId": "60125081",
  "title": "3 Bedroom Condo for sale at Example Residence",
  "url": "https://www.ddproperty.com/en/property/project/example-residence-bangkok-for-sale-60125081#3856",
  "listingType": "For Sale",
  "propertyType": "Condo",
  "price": 8500000,
  "priceText": "฿8,500,000",
  "pricePerArea": "฿94,444 / sqm",
  "currency": "THB",
  "bedrooms": 3,
  "bathrooms": 2,
  "floorAreaSqm": 95,
  "address": "Bang Na, Bang Na, Bangkok",
  "district": "Bang Na",
  "region": "Bangkok",
  "projectName": "Example Residence",
  "developerName": "Example Developer",
  "agentName": "Example Agent",
  "agentVerified": true,
  "availabilityText": "Available now",
  "listedByText": "Listed by agent",
  "badgeText": "Verified",
  "viewedLabel": "Viewed 120 times",
  "mrtNames": ["Bang Na"],
  "featureTexts": ["3 Beds", "2 Baths", "95 sqm"],
  "imageUrl": "https://th1-cdn.pgimgs.com/project-listing-project/60248606/PLPHO.134568456.V550/example.jpg",
  "photoGallery": [
    "https://th1-cdn.pgimgs.com/project-listing-project/60248606/PLPHO.134568456.V800/example.jpg",
    "https://th1-cdn.pgimgs.com/project-listing-project/60248606/PLPHO.134568457.V800/example-2.jpg"
  ],
  "isVerified": true,
  "isOfficialListing": false,
  "isDeveloperListing": false,
  "isPrioritized": true,
  "accountTypeCode": "agent",
  "recencyText": "2 days ago",
  "postedOnText": "2 days ago",
  "postedOnUnix": 1772755200,
  "sourceUrl": "https://www.ddproperty.com/en/property-for-sale?listingType=sale&isCommercial=false",
  "page": 1,
  "scrapedAt": "2026-08-09T12:00:00.000Z"
}
```

### Tips for Best Results

- **Start small** - Use `results_wanted: 20` for quick validation runs, then raise the limit for larger jobs.
- **Use stable search URLs** - Keep the listing type in the URL aligned with the `listingType` input field.
- **Increase page depth gradually** - Raise `max_pages` only as needed, because each page adds more listings to collect.
- **Use Thailand residential proxies for larger runs** - Enable Apify Proxy with the RESIDENTIAL group and set the proxy country to Thailand (`TH`) inside `proxyConfiguration` to improve continuity.
- **Expect source-dependent fields** - Not every listing publishes every field. Empty values are removed automatically so the dataset stays clean.
- **Report page changes** - Public websites change over time. If a run stops unexpectedly, use the Issues tab on the Actor page.

### Integrations

- **Google Sheets** - Send property data to spreadsheets for team review.
- **Airtable** - Build searchable property databases.
- **Slack** - Get notified when new collection runs complete.
- **Webhooks** - Trigger downstream workflows after each run.
- **Make** - Automate reporting and data processing flows.
- **Zapier** - Connect property data to hundreds of apps.

#### Export Formats

- **JSON** - For applications, APIs, and data pipelines.
- **CSV** - For spreadsheet analysis.
- **Excel** - For business reporting.
- **XML** - For system integrations.

### Frequently Asked Questions

#### Can I scrape both sale and rental listings?

Yes. Set `listingType` to `sale` for for-sale properties or `rent` for rental listings, and provide a matching DDProperty search URL.

#### How many listings can I collect?

Set `results_wanted` to your target number and increase `max_pages` for deeper pagination. The Actor collects up to your target or until it reaches the total available listings for the search.

#### Why are some fields empty?

Some listings do not publish every data point. Empty values are removed automatically so the exported dataset remains clean and analysis-ready.

#### Should I use a proxy?

An Apify Residential Proxy in Thailand (`TH`) is recommended because it matches DDProperty's market and was the most reliable tested route. If a run fails, select the residential proxy option and choose Thailand (`TH`) in `proxyConfiguration`.

#### Can I export the data to CSV or Excel?

Yes. Apify datasets support export to JSON, CSV, Excel, XML, and HTML. Download results directly from the Apify Console or using the API.

#### What happens if a page fails to load?

The Actor retries failed pages automatically and uses alternative request patterns before reporting an error. If no data can be collected at all, the run stops with a clear error message instead of returning fake success records.

#### Is it legal to scrape DDProperty?

Scraping public web data can be legal, but you are responsible for complying with applicable laws, DDProperty's terms of service, and privacy rules. Use data responsibly and respect rate limits.

### Related Actors

- [Housing.com Property Scraper](https://apify.com/shahidirfan/housing-com-property-scraper) - Collect Indian property listings for market research and investment analysis.
- [iProperty Scraper](https://apify.com/shahidirfan/iproperty-scraper) - Extract Malaysian property listings, prices, locations, and details.
- [Domain.com.au Property Scraper](https://apify.com/shahidirfan/domain-com-au-property-scraper) - Collect Australian sale and rental property listings with prices, locations, and agent details.
- [Zameen.com Scraper](https://apify.com/shahidirfan/zameen-com-scraper) - Extract Pakistan property listings for homes, plots, and commercial properties.

### Support

For issues, feature requests, or custom Actor work, use the Issues tab on the Actor page or contact the developer through Apify.

### Legal Notice

This Actor is intended for legitimate collection of publicly available DDProperty property information. Users are responsible for complying with applicable laws, DDProperty's terms of service, and privacy rules. Use data responsibly and respect rate limits.

# Actor input Schema

## `startUrl` (type: `string`):

DDProperty search URL. If empty, a default sale search URL is used.

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

Search listing type.

## `isCommercial` (type: `boolean`):

Set true for commercial search pages.

## `results_wanted` (type: `integer`):

Maximum number of listings to save.

## `max_pages` (type: `integer`):

Safety cap on number of pages to visit.

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

Optional proxy configuration. For the most reliable DDProperty runs, use an Apify Residential Proxy in Thailand (TH).

## Actor input object example

```json
{
  "startUrl": "https://www.ddproperty.com/en/property-for-sale?listingType=sale&isCommercial=false",
  "listingType": "sale",
  "isCommercial": false,
  "results_wanted": 20,
  "max_pages": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "TH"
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# 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 = {
    "startUrl": "https://www.ddproperty.com/en/property-for-sale?listingType=sale&isCommercial=false",
    "listingType": "sale",
    "isCommercial": false,
    "results_wanted": 20,
    "max_pages": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("shahidirfan/ddproperty-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 = {
    "startUrl": "https://www.ddproperty.com/en/property-for-sale?listingType=sale&isCommercial=false",
    "listingType": "sale",
    "isCommercial": False,
    "results_wanted": 20,
    "max_pages": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("shahidirfan/ddproperty-scraper").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 '{
  "startUrl": "https://www.ddproperty.com/en/property-for-sale?listingType=sale&isCommercial=false",
  "listingType": "sale",
  "isCommercial": false,
  "results_wanted": 20,
  "max_pages": 5
}' |
apify call shahidirfan/ddproperty-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,shahidirfan/ddproperty-scraper"
        }
    }
}

```

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/5XIgTonXuw522xSwm/builds/QfYP58mojYlDqopog/openapi.json
