# Property Finder Scraper — AI Deal Score & Complete Coverage (`programmx/propertyfinder-deal-scraper`) Actor

Scrape Property Finder UAE listings with agent email, phone & WhatsApp, an AI Deal Score vs local comps, and a per-run coverage proof. CSV/JSON.

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

## Pricing

from $150.00 / 1,000 deal scores

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/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

## Property Finder Scraper — AI Deal Score & Complete Coverage

![How the Property Finder UAE scraper works: pick your scope, complete capture with a coverage receipt, optional AI deal score](https://raw.githubusercontent.com/PTechFusion/programmx-actor-assets/main/propertyfinder-how-it-works.png)

This Property Finder scraper extracts UAE property listings from [propertyfinder.ae](https://www.propertyfinder.ae) with agent contact details (email, phone, and WhatsApp) in every row, an **AI Deal Score** that benchmarks each listing against comparable properties in the same sub-community, and a per-run **coverage proof** that shows — with numbers you can check — that you received the full result set for your search, not just the first page-window.

### What you get in every row

- The full search-page listing record: price, bedrooms, bathrooms, area (sqft), property type, community, sub-community, tower, listing date, reference, furnishing, amenities, description, and more
- **Agent contact bundled in**: email, phone, and WhatsApp number, plus agent and broker names
- Direct listing URL and image link
- Optional **Deal Score** fields and an optional detail-page enrichment block

### What makes this Property Finder scraper different

#### AI Deal Score

Every scored listing is compared against comparable listings — same offering type (rent or sale), same property type, same bedroom count, similar size (±30%) — in the **same sub-community**, falling back to the same community only when the sub-community has too few comparables. The engine computes the median price per sqft of those comps and scores the listing 0–100 (50 = at market, higher = better value):

| Field | Meaning |
|---|---|
| `dealScore` | 0–100; one point per percent below the comps median |
| `dealScoreBand` | `great_deal` / `below_market` / `at_market` / `above_market` / `overpriced` |
| `dealScorePctVsMedian` | Percent above/below the median price per sqft |
| `dealScoreMedianPpsf` | The comps median itself, so you can verify the math |
| `dealScoreCompsCount` / `dealScoreBasis` | How many comparables, and at which level |
| `dealScoreNarrative` | A one-sentence plain-English summary, written by AI |

The numbers are computed deterministically from the listings data — the AI only phrases the result, it never calculates. Listings with too few comparables are marked with a reason instead of being given a fake score, and they are not charged.

#### Provable completeness

Property Finder silently caps any single search at about 1,250 results: past page 50 the site returns an empty page with HTTP 200, so a naive Property Finder crawler delivers a partial dataset without any error. This scraper partitions your search through Property Finder's own category tree (property type → emirate → community → sub-community → tower), walks each branch below the cap, de-duplicates listings across branches, and then writes a `coverage_proof` row **into your dataset**: the sum of branch counts, the site's own total, the difference, per-field fill rates, and a `reconciled: true/false` verdict. Unlike crawlers that stop at the window, an incomplete walk here says so, in the data.

#### Agent contacts, included

Email, phone, and WhatsApp are part of the base row — no separate tier, no add-on price.

#### How this compares to other Property Finder scrapers

The Apify store has a dozen Property Finder scrapers, and most of them do the same three things: read the search pages, return what fits in the window, and sell agent contacts as a second actor. The differences that actually change what you can do with the data:

| | Typical Property Finder scraper | This actor |
|---|---|---|
| **Result ceiling** | Stops at the site's silent ~1,250-row window and reports success | Partitions the category tree to walk past the window, and **proves the result set reconciles** |
| **Did I get everything?** | No way to tell from the output | A `coverage_proof` row per run: branch totals vs the site's own count, per-field fill rates, `reconciled: true/false` |
| **Agent email / phone / WhatsApp** | Usually a separate agent-scraper actor, billed again | In every listing row, at no extra event |
| **Valuation signal** | Raw price only | Optional Deal Score vs same-sub-community comparables, with the median and comp count in the row so you can check the math |
| **Delistings** | Not tracked, or asserted without evidence | Monitor mode reports removals **only when the coverage proof reconciles**, so a failed walk can't masquerade as a wave of delistings |

We are not going to quote other developers' star ratings at you — they move, and you can read them yourself on the store. Run this actor against any of them on the same search and compare the row counts against the `coverage_proof`; that is the comparison that matters.

### Monitor mode

Turn on `monitorMode` to re-check listings found by previous runs of this actor or task: price changes, unchanged listings, and removals are reported as `monitor` rows (removals are only asserted when the coverage proof reconciles, so an incomplete walk can never masquerade as a wave of delistings). New listings in the same scope are delivered as normal listing rows.

### Detail-page enrichment (optional)

Off by default. When enabled, each returned listing's detail page is also fetched and a `detail` block is added: regulatory details and licenses, zone name, availability date, project information, grouped amenities, and Property Finder's price-comparison and price-trend widgets. A detail page is a separate page load per listing rather than a row read off a search page, so it is charged separately at **$0.005 per enriched listing** ($5 per 1,000) on top of the listing row.

### Example output

```json
{
  "listingId": "122898013",
  "title": "2-months Free| Lifestyle Amenities| Ideal Location",
  "price": 280000,
  "pricePeriod": "yearly",
  "propertyType": "Apartment",
  "bedrooms": 3,
  "areaSqft": 2271,
  "community": "Sheikh Zayed Road",
  "subCommunity": "City Towers",
  "agentName": "Diana Ilinca",
  "agentEmail": "diana.ilinca@bhomes.com",
  "agentPhone": "+97144090911",
  "agentWhatsapp": "+97145560345",
  "dealScore": 64,
  "dealScoreBand": "below_market",
  "dealScoreNarrative": "This 3-bedroom apartment in City Towers is priced about 14% below the median for comparable listings.",
  "url": "https://www.propertyfinder.ae/en/plp/rent/..."
}
```

### Input

Pick a scope with the dropdowns (rent/sale, emirate, property type) or paste propertyfinder.ae search URLs. Set `maxResults` — the hard cap on unique listings returned, and the only listing rows you are billed for. Toggle `dealScore`, `detailEnrichment`, and `monitorMode` as needed.

#### Input example

Copy this into the **JSON** tab of the input editor — a Dubai apartment rental sweep with Deal Scores on:

```json
{
  "offeringType": "rent",
  "emirate": "dubai",
  "propertyType": "apartment",
  "maxResults": 1000,
  "dealScore": true,
  "detailEnrichment": false,
  "monitorMode": false
}
```

Or drive it from search URLs you built on the site, and re-check known listings weekly:

```json
{
  "searchUrls": [
    "https://www.propertyfinder.ae/en/buy/dubai/villas-for-sale.html",
    "https://www.propertyfinder.ae/en/rent/abu-dhabi/apartments-for-rent.html"
  ],
  "maxResults": 2000,
  "dealScore": false,
  "monitorMode": true
}
```

Pasted URLs must be `propertyfinder.ae` **rent or buy** paths (`/en/rent/…` or `/en/buy/…`). The path is the filter: query-string parameters like `min_price` or a bedroom count are stripped with a warning, because Property Finder ignores them anyway — and billing you for a wider result set than you thought you asked for would be dishonest.

### Pricing: $1.50 per 1,000 listings

Billing is pay-per-event, and every event has a published price — nothing here is quoted as a multiple of something else:

| Event | Price | Per 1,000 | When it fires |
|---|---|---|---|
| **Listing row** | **$0.0015** | **$1.50** | Once per unique listing delivered |
| **Deal Score** | $0.015 | $15.00 | Only when `dealScore` is on, and only for listings that had enough comparables to score |
| **Detail enrichment** | $0.005 | $5.00 | Only when `detailEnrichment` is on, once per enriched listing |
| **Monitor check** | $0.005 | $5.00 | Only in `monitorMode`, once per previously-seen listing re-checked |
| Actor start | $0.00005 | — | Once per run |

**Never billed:** duplicate listings removed during the walk, listings that could not be scored for lack of comparables, the `coverage_proof` row itself, pages fetched while partitioning the category tree, and anything above your `maxResults` cap.

#### Worked examples

**A one-off market pull — 1,000 Dubai apartment listings, no extras:**

| Line | Count | Rate | Cost |
|---|---|---|---|
| Listing rows | 1,000 | $0.0015 | $1.50 |
| Actor start | 1 | $0.00005 | $0.00 |
| **Total** | | | **$1.50** |

**The same pull, with Deal Scores on the 100 listings you shortlist:**

| Line | Count | Rate | Cost |
|---|---|---|---|
| Listing rows | 1,000 | $0.0015 | $1.50 |
| Deal Scores | 100 | $0.015 | $1.50 |
| **Total** | | | **$3.00** |

**A weekly monitor run over those 1,000 known listings, finding 40 new ones:**

| Line | Count | Rate | Cost |
|---|---|---|---|
| Monitor checks on known listings | 1,000 | $0.005 | $5.00 |
| New listing rows | 40 | $0.0015 | $0.06 |
| **Total per week** | | | **$5.06** |

`maxResults` is a hard cap on unique listing rows, so the listing-row line of your bill can never exceed `maxResults × $0.0015` no matter how large the search turns out to be.

### Integrations

Export the dataset as **CSV, Excel, JSON, or XML** from the Apify console or API, sync it to **Google Sheets** or **Airtable**, push leads into **HubSpot** or any CRM, and automate runs with **Zapier, Make, or n8n** through [Apify integrations](https://docs.apify.com/platform/integrations). The dataset is also available over a simple HTTP API for your own stack.

### FAQ

**How do I get Property Finder agent contacts — email, phone, and WhatsApp?**
Run the scraper on your search scope; every listing row includes `agentEmail`, `agentPhone`, and `agentWhatsapp` when the listing publishes them, plus agent and broker names. The coverage proof's per-field fill counts tell you exactly how many rows carried each contact field.

**Can I export UAE property listings to CSV or Excel?**
Yes — every run produces an Apify dataset you can download as CSV, Excel, JSON, or XML, or pull straight into Google Sheets.

**How is the AI Deal Score calculated?**
Deterministically: the median price per sqft of comparable listings (same type, bedrooms, similar size) in the same sub-community, and the listing's percentage above or below that median. The AI writes the one-sentence summary; it never does the math. The median and comp count are in the row so you can check it.

**Do I really get every listing in my search, and how would I know?**
Every run ends with a `coverage_proof` row reconciling the sum of walked branches against Property Finder's own total count. If the run was capped by `maxResults` or a branch failed, the proof says `reconciled: false` and names the gap — unlike crawlers that stop at Property Finder's silent ~1,250-row window and report nothing.

**Can I monitor Property Finder listings for price changes and removals?**
Yes — enable `monitorMode` on a saved task and schedule it. Known listings are re-checked (price changes and removals reported), and new listings arrive as normal rows.

**How much does it cost to scrape 1,000 Property Finder listings?**
**$1.50** — 1,000 listing rows at $0.0015 each, agent email, phone and WhatsApp included. Deal Score ($0.015), detail enrichment ($0.005) and monitor checks ($0.005) are separate opt-in events, so a run with everything switched off costs exactly the listing rows. See [Pricing](#pricing-150-per-1000-listings) for worked examples.

**Is it legal to scrape Property Finder?**
The scraper collects publicly visible listing data only. You are responsible for using the data in compliance with applicable laws and the source site's terms; nothing here is legal advice.

### Works together with

| Actor | What it gives you |
|---|---|
| **[Instantly Lead Pusher](https://apify.com/programmx/instantly-lead-pusher)** | Push the agent contacts in these rows straight into an Instantly.ai campaign — no CSV export. Attach it on the **Integrations** tab and every scheduled run feeds your sequence. `dealScoreBand`, `community` and `price` arrive as `{{merge_tags}}`, so the email can open with the listing itself. |
| **[eBay Business Leads Scraper](https://apify.com/programmx/ebay-business-leads)** | Verified B2B contacts for eBay business sellers across the UK and EU, from the DSA/GPSR trader disclosure. |
| **[German Estate Agent Leads](https://apify.com/programmx/immoscout24-agent-leads)** | Verified contact records for German estate agencies, built from legally mandated Impressum data. |

***

Built by [ProgrammX](https://programmx.com) · hello@programmx.com

# Actor input Schema

## `offeringType` (type: `string`):

Which side of the market to scrape. Rent and sale are separate result trees on Property Finder, so one run covers one of them.

## `emirate` (type: `string`):

Where to search. "All emirates" walks the full UAE tree — expect a long run unless Max results caps it first.

## `propertyType` (type: `string`):

Restrict to one property type, or take everything under the chosen emirate.

## `searchUrls` (type: `array`):

Paste propertyfinder.ae search-result URLs to scrape exactly those scopes instead of the pickers above. Note: Property Finder ignores query-string filters like min\_price — only the URL path decides the result set, so query parameters are stripped with a warning.

## `maxResults` (type: `integer`):

Hard cap on unique listings returned — and the only rows you are billed for. Billing is per listing row, never per page fetched. Duplicates across overlapping search branches are removed before billing.

## `dealScore` (type: `boolean`):

Score every returned listing against comparable listings in the same sub-community (median price per sqft): a 0–100 score, a market band, the comp count, and a one-sentence AI narrative. Charged per scored row as a separate event — listings with too few comparables are marked, not charged.

## `detailEnrichment` (type: `boolean`):

Also fetch each listing's detail page for extra fields (amenities, descriptions, and other fields not present in search results). Costs roughly 17× a search row to produce, and is charged as its own event — leave off unless you need those fields.

## `monitorMode` (type: `boolean`):

Re-check listings seen by previous runs of this actor/task: price changes, removals, and unchanged listings are reported and charged per check. New listings found in the same scope still bill as normal listing rows.

## `maxConcurrency` (type: `integer`):

Parallel page fetches. Higher is faster but heavier on the source; 4 is a good citizen.

## `requestDelayMs` (type: `integer`):

Politeness spacing between fetches per worker.

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

UAE residential proxy is used by default. Leave as-is unless you have a specific reason to change it.

## Actor input object example

```json
{
  "offeringType": "rent",
  "emirate": "dubai",
  "propertyType": "apartment",
  "searchUrls": [],
  "maxResults": 25,
  "dealScore": true,
  "detailEnrichment": false,
  "monitorMode": false,
  "maxConcurrency": 4,
  "requestDelayMs": 500,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AE"
  }
}
```

# Actor output Schema

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

One row per unique listing, with agent contact and (when enabled) the Deal Score. Use Export to download as CSV or Excel.

# 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 = {
    "offeringType": "rent",
    "emirate": "dubai",
    "propertyType": "apartment",
    "maxResults": 25,
    "dealScore": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("programmx/propertyfinder-deal-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 = {
    "offeringType": "rent",
    "emirate": "dubai",
    "propertyType": "apartment",
    "maxResults": 25,
    "dealScore": True,
}

# Run the Actor and wait for it to finish
run = client.actor("programmx/propertyfinder-deal-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 '{
  "offeringType": "rent",
  "emirate": "dubai",
  "propertyType": "apartment",
  "maxResults": 25,
  "dealScore": true
}' |
apify call programmx/propertyfinder-deal-scraper --silent --output-dataset

```

## MCP server setup

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