# Propertyfinder UAE $0.8💰 Powerful Filters + Deep Search (`abotapi/propertyfinder-ae-scraper`) Actor

From $0.8/1K. Extract property listings from propertyfinder.ae at scale. Get comprehensive data including prices, property details, images, agent contacts, broker info, RERA numbers, coordinates, amenities, and more. Perfect for UAE real estate analytics, market research, and investment analysis.

- **URL**: https://apify.com/abotapi/propertyfinder-ae-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** Real estate, Developer tools, Automation
- **Stats:** 7 total users, 0 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.80 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## PropertyFinder AE Scraper

Extract property listings from **propertyfinder.ae** at scale. Get comprehensive data including prices, property details, images, agent contacts, broker info, RERA numbers, coordinates, amenities, and more. Perfect for UAE real estate analytics, market research, and investment analysis.

### What does PropertyFinder AE Scraper do?

This Apify Actor scrapes property listings from propertyfinder.ae — the largest real estate portal in the UAE. It extracts full listing data from search result pages with built-in anti-detection and automatic pagination.

#### Key Features

| Feature | Description |
|---------|-------------|
| **All Listing Types** | For Sale and For Rent properties across all UAE emirates |
| **Property Type Filters** | Apartments, Villas, Townhouses, Penthouses, Land, and more |
| **Price & Bedroom Filters** | Narrow results by price range (AED) and bedrooms |
| **Location Filters** | Filter by city, community, subcommunity |
| **Exact Coordinates** | Lat/lng for every listing |
| **Multiple Dataset Views** | Listings Overview, Agent & Broker Info |
| **Checkpoint/Resume** | Automatic state saving for long scraping runs, plus `resumeFromRunId` to continue from a previous run as a delta |
| **Incremental mode** | Schedule this actor daily/weekly on the same search and get only NEW / UPDATED / REAPPEARED listings — the actor remembers the previous run itself |
| **URL Mode** | Paste any search URL directly |

### What data can you extract?

The scraper extracts 40+ fields per listing:

<table>
<tr><td>

**Property Details**

- Listing ID & URL
- Title & full description
- Property type (Apartment, Villa, Townhouse, etc.)
- Bedrooms & bathrooms
- Size in sqft
- Furnished status
- Completion status (completed / off-plan)
- Amenities list

</td><td>

**Pricing**

- Price (AED numeric value)
- Price per sqft
- Price period (sale / yearly / monthly)
- Price hidden flag

</td></tr>
<tr><td>

**Location**

- Full location path
- City, community, subcommunity, building
- Latitude & longitude (GPS)

</td><td>

**Agent & Broker**

- Agent name, email, phone, WhatsApp
- SuperAgent flag
- Broker name & phone
- RERA permit number
- Reference number

</td></tr>
<tr><td>

**Media**

- Property images (medium quality URLs)
- Image count
- Video tour URL
- 360-degree view flag

</td><td>

**Dates & Metadata**

- Listed date
- Last refreshed date
- Verified / Premium / Featured / Exclusive flags
- Listing level (premium, featured, standard)

</td></tr>
</table>

### Quick Start

Search for apartments for sale in Dubai:

```json
{
  "category": "buy",
  "locations": ["dubai"],
  "propertyTypes": ["apartments"],
  "maxListings": 50
}
```

### How to Use

#### Step 1: Basic search by location

```json
{
  "category": "buy",
  "locations": ["dubai"],
  "maxListings": 100,
  "maxPages": 5
}
```

#### Step 2: Filter by property type and price

```json
{
  "category": "rent",
  "locations": ["dubai"],
  "propertyTypes": ["apartments"],
  "minPrice": 50000,
  "maxPrice": 150000,
  "minBedrooms": 1,
  "maxBedrooms": 2,
  "furnishing": "furnished",
  "maxListings": 200
}
```

#### Step 3: Scrape specific URLs

```json
{
  "urls": [
    "https://www.propertyfinder.ae/en/buy/dubai/apartments-for-sale-downtown-dubai.html",
    "https://www.propertyfinder.ae/en/rent/abu-dhabi/villas-for-rent.html"
  ],
  "maxListings": 500,
  "maxPages": 20
}
```

#### Step 4: Large-scale scrape across multiple locations

Leave `maxPages` empty to walk every result page for each location/type combination:

```json
{
  "category": "buy",
  "locations": ["dubai", "abu-dhabi", "sharjah"],
  "propertyTypes": ["apartments", "villas", "townhouses"],
  "sort": "nd",
  "maxListings": 0
}
```

#### Step 5: Resume a previous run

Pick up where a previous run stopped (or continue collecting only new listings since then) by passing its run ID — already-collected listings are skipped:

```json
{
  "category": "buy",
  "locations": ["dubai"],
  "maxListings": 0,
  "resumeFromRunId": "<previous run ID>"
}
```

#### Step 6: Recurring monitoring with Incremental mode

Schedule this actor to run daily/weekly against the same search and get only what changed since last time — no run ID to paste, no manual dedup:

```json
{
  "category": "buy",
  "locations": ["dubai"],
  "propertyTypes": ["apartments"],
  "maxListings": 0,
  "incrementalMode": true,
  "emitExpired": true
}
```

- The **first** run returns everything as `changeType: "NEW"`.
- **Later** runs return only `NEW`, `UPDATED`, and `REAPPEARED` listings by default. Turn on **Emit unchanged** to also get every unchanged listing back (billed), or **Emit expired** to also get listings that disappeared since the last run (only produced once a run scans every search URL to its natural end — never when Max listings capped it, or Resume was used).
- State is kept per search+filter combination automatically; set **State key** to name or deliberately share a monitoring campaign.
- This is distinct from `resumeFromRunId` above: Resume continues *one* interrupted run; Incremental mode tracks *the same recurring search* across many separate runs.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape — the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each record — not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `urls` | array | `[]` | PropertyFinder search URLs (overrides category/location/type) |
| `category` | string | `buy` | `buy` or `rent` |
| `locations` | array | `[]` | Location slugs (empty = all UAE) |
| `propertyTypes` | array | `["properties"]` | Property type filters (see table below) |
| `maxListings` | integer | `100` | Max listings to scrape (0 = unlimited) |
| `maxPages` | integer | - | Max pages per search URL. Leave empty to walk every result page (~25 listings/page) |
| `sort` | string | `nd` | Sort order (see table below) |
| `minPrice` | integer | - | Minimum price in AED |
| `maxPrice` | integer | - | Maximum price in AED |
| `minBedrooms` | integer | - | Minimum bedrooms |
| `maxBedrooms` | integer | - | Maximum bedrooms |
| `furnishing` | string | `any` | `any`, `furnished`, `unfurnished`, `partly-furnished` |
| `completionStatus` | string | `any` | `any`, `completed`, `off_plan` |
| `proxy` | object | - | Proxy configuration (optional) |
| `resumeFromRunId` | string | - | Run ID (or dataset ID) of a previous run of this Actor. Listings already collected there are skipped, so this run returns only the delta. |
| `incrementalMode` | boolean | `false` | Turn on for recurring/scheduled monitoring — only NEW/UPDATED/REAPPEARED listings are returned on later runs. |
| `stateKey` | string | - | Name an incremental monitoring campaign, or leave empty to derive one automatically from the search/filters. |
| `emitUnchanged` | boolean | `false` | Also return (and bill for) listings unchanged since the last incremental run. |
| `emitExpired` | boolean | `false` | Also return (and bill for) listings no longer found since the last incremental run (only on a complete, non-resumed scan). |

### Locations

Any location slug from propertyfinder.ae:

| Location | Slug | Location | Slug |
|----------|------|----------|------|
| Dubai | `dubai` | Sharjah | `sharjah` |
| Abu Dhabi | `abu-dhabi` | Ajman | `ajman` |
| Ras Al Khaimah | `ras-al-khaimah` | Fujairah | `fujairah` |
| Downtown Dubai | `dubai/downtown-dubai` | Dubai Marina | `dubai/dubai-marina` |
| JVC | `dubai/jumeirah-village-circle` | Al Reem Island | `abu-dhabi/al-reem-island` |

### Property Types

| Type | Slug | Type | Slug |
|------|------|------|------|
| All Properties | `properties` | Hotel Apartments | `hotel-apartments` |
| Apartments | `apartments` | Compounds | `compounds` |
| Studio Apartments | `studio-apartments` | Land | `land` |
| Villas | `villas` | Whole Buildings | `whole-buildings` |
| Townhouses | `townhouses` | Bulk Sale Units | `bulk-sale-units` |
| Penthouses | `penthouses` | Full Floors | `full-floors` |
| Duplexes | `duplexes` | Half Floors | `half-floors` |

### Sort Options

| Code | Description |
|------|-------------|
| `nd` | Newest first |
| `mr` | Featured / recommended |
| `pa` | Price: low to high |
| `pd` | Price: high to low |
| `ba` | Bedrooms: least first |
| `bd` | Bedrooms: most first |

# Actor input Schema

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

How to find properties to scrape

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

Location slugs (Search mode only). Example: 'dubai', 'abu-dhabi', 'dubai/downtown-dubai'. Leave empty for all UAE.

## `urls` (type: `array`):

PropertyFinder search page URLs to scrape (URL mode only). Supports pagination — the scraper will follow pages from where the URL starts.

## `category` (type: `string`):

Buy or Rent (Search mode only)

## `propertyTypes` (type: `array`):

Property types (Search mode only): properties, apartments, studio-apartments, villas, townhouses, penthouses, hotel-apartments, compounds, land, duplexes, whole-buildings, bulk-sale-units, bungalows, full-floors, half-floors.

## `sort` (type: `string`):

Sort order for results (Search mode only)

## `maxListings` (type: `integer`):

Maximum number of listings to scrape. Set 0 for unlimited.

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

Maximum pages to paginate per search URL (~25 listings/page). Leave empty to walk every result page.

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

Minimum price filter. Leave empty for no minimum.

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

Maximum price filter. Leave empty for no maximum.

## `minBedrooms` (type: `integer`):

Minimum bedrooms filter.

## `maxBedrooms` (type: `integer`):

Maximum bedrooms filter.

## `furnishing` (type: `string`):

Furnishing filter

## `completionStatus` (type: `string`):

Property completion status. 'off\_plan' includes both off-plan and off-plan primary.

## `proxy` (type: `object`):

Proxy settings. Datacenter proxies usually work. Use residential if you get blocked.

## `resumeFromRunId` (type: `string`):

Run ID (or dataset ID) of a previous run of this Actor. Listings already collected there are skipped, so this run returns only the delta. Leave empty for a normal run. For recurring daily/weekly monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns all matching listings as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED listings. Turn on "Emit unchanged" or "Emit expired" only when you also want those listings returned (and billed). State is kept separately for each search/URL and filter setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from run ID above.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the search/URL and filter settings — different searches then never mix state with each other.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return listings that have not changed since the last run, marked UNCHANGED. This returns — and bills — extra rows you already have, so leave it off unless you specifically want the full snapshot every run.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return listings that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned every search URL — not when Max listings capped it, or when Resume was used. This returns — and bills — extra synthetic rows, so leave it off unless you need expiry tracking.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON — the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "locations": [
    "dubai"
  ],
  "urls": [
    "https://www.propertyfinder.ae/en/buy/dubai/apartments-for-sale.html"
  ],
  "category": "buy",
  "propertyTypes": [
    "properties"
  ],
  "sort": "nd",
  "maxListings": 100,
  "furnishing": "any",
  "completionStatus": "any",
  "proxy": {
    "useApifyProxy": false
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxNotifyListings": 50
}
```

# Actor output Schema

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

Individual property listing records with 40+ fields including price, location hierarchy, agent/broker contacts, RERA numbers, amenities, and GPS coordinates.

## `output` (type: `string`):

Scraping run summary with total listings, pages fetched, duration, and rate.

# 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 = {
    "mode": "search",
    "locations": [
        "dubai"
    ],
    "urls": [
        "https://www.propertyfinder.ae/en/buy/dubai/apartments-for-sale.html"
    ],
    "propertyTypes": [
        "properties"
    ],
    "proxy": {
        "useApifyProxy": false
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/propertyfinder-ae-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 = {
    "mode": "search",
    "locations": ["dubai"],
    "urls": ["https://www.propertyfinder.ae/en/buy/dubai/apartments-for-sale.html"],
    "propertyTypes": ["properties"],
    "proxy": { "useApifyProxy": False },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/propertyfinder-ae-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 '{
  "mode": "search",
  "locations": [
    "dubai"
  ],
  "urls": [
    "https://www.propertyfinder.ae/en/buy/dubai/apartments-for-sale.html"
  ],
  "propertyTypes": [
    "properties"
  ],
  "proxy": {
    "useApifyProxy": false
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false
}' |
apify call abotapi/propertyfinder-ae-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/propertyfinder-ae-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/d1zAcGEH2KYEj0BZ4/builds/KkkoVVkATNPZuIY6E/openapi.json
