# Property Finder MENA Listings & Agent Contact Extractor (`dataspryva/property-finder-mena-listings-and-agent-contact`) Actor

Reads Property Finder listings across the UAE, Saudi Arabia, Qatar, Bahrain, and Egypt, returning price, size, location hierarchy, amenities, and agent or brokerage contact details.

- **URL**: https://apify.com/dataspryva/property-finder-mena-listings-and-agent-contact.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** Real estate, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Property Finder MENA Listings & Brokerage Contacts

Property Finder is the leading real-estate portal across the UAE, Saudi Arabia, Qatar, Bahrain and Egypt. This actor turns its public listing pages into structured property records — prices, rooms, size, location, amenities, permits, photos, floor plans and agent profile details — together with the public contact information that the listing publishes: usually the brokerage's switchboard and email, and at smaller agencies an individual broker's line.

It works with a city-and-purpose search, with canonical listing URLs you already have, or with agent and broker profile URLs. No login, cookie, API key or proxy setup is required.

### What this actor does

- **Search five markets** — the UAE, Saudi Arabia, Qatar, Bahrain and Egypt, each with local currency and city/province slugs.
- **Filter by intent** — buy, rent, commercial buy, commercial rent; property type; bedrooms; price range; furnishing; and ready/off-plan for residential sales.
- **Scrape listing or search URLs** — landing pages, individual listing pages, sitemaps, and search URLs you supply. Canonical detail URLs are robots-allowed; Property Finder's robots.txt disallows `/en/search?*` and `/to/*` short links, so prefer canonical detail URLs.
- **Collect agent and broker profiles** — agent profiles work in the UAE, Qatar and Bahrain; broker/agency profiles work in all five markets. Saudi and Egyptian agent-profile URLs currently return 404 at the source.
- **Enrich every listing** — the full photo gallery, community and tower images, permit validation link, licences, floor plans, building facts and agent ratings.
- **Honest contact data** — Property Finder leaves `agent.email` and `agent.phone` empty (0/217 listings and 0/40 details measured). The actor returns the contact published with the listing: broker email/phone plus the listing's WhatsApp relay number (usually Property Finder's market number, not the agent's personal number). At small agencies the broker line or email can be the agent's own (for example a Gmail address matching the agent's name).
- **Empty fields are omitted** — a missing value is never replaced with `null` or an empty string. Placeholder numbers published by the source are returned as-is.

### Output per record

Each record has `recordType`: `listing`, `agent` or `broker`.

#### Listing

- `id`, `listingId`, `reference`, `rera` / `permitNumber`, `url`, `title`, `description`
- `purpose` (`sale` / `rent`), `country`, `sourceDomain`
- `propertyType`, `propertyTypeId`, `offeringType`, `categoryId`
- `price`, `priceCurrency`, `priceDuration`, `priceHidden`, `pricePerArea`, `pricePerAreaUnit`
- `bedrooms`, `bedroomsLabel`, `isStudio`, `bathrooms`, `size`, `sizeUnit`, `sizeSqm`
- `furnished`, `completionStatus`, `completionStatusRaw`
- `city`, `community`, `subCommunity`, `tower`, `locationFullName`, `locationId`, `locationPath`, `locationTree`
- `latitude`, `longitude`
- `coverImage`, `images`, `imagesCount`, `communityImages`, `towerImages`
- `amenities`, `amenityNames`, `floorPlans`, `floorPlanCount`
- `agentId`, `agentName`, `agentProfileUrl`, `agentImage`, `agentSlug`, `agentIsSuperAgent`, `agentLanguages`, `agentPosition`, `agentRating`, `agentReviewCount`, `agentYearsOfExperience`, `agentTotalProperties`, `agentTransactionsCount`, `agentLicenseNumber`
- `brokerId`, `brokerName`, `brokerProfileUrl`, `brokerLogo`, `brokerEmail`, `brokerPhone`, `brokerWhatsapp`, `brokerAddress`, `brokerLicenseNumber`, `brokerSlug`, `clientId`
- `contactPhone`, `contactEmail`, `contactWhatsapp`, `contactOptions`
- `permitValidationUrl`, `permitAuthority`, `permitIssuedLicenseNumber`, `zoneName`, `licenses`
- `isVerified`, `isDirectFromDeveloper`, `isNewConstruction`, `isFeatured`, `isPremium`, `isExclusive`, `isPfExclusive`, `isAvailable`, `isNewInsert`, `isPriceDrop`, `isGreatValue`, `isHighDemand`, `isLuxe`, `isSpotlight`, `isUnderOffer`
- `leadValue`, `listingLevel`, `videoUrl`, `view360Url`, `has360View`
- `serviceChargePerSqft`, `buildingDetails`
- `listedDate`, `lastRefreshedAt`, `scrapedAt`

`agentEmail`, `agentPhone` and `agentWhatsapp` are retained for compatibility but are only present when the source itself publishes them; in practice those fields are almost always absent.

#### Agent

- `agentId`, `agentName`, `agentProfileUrl`, `agentImage`, `agentSlug`
- `agentIsSuperAgent`, `agentVerified`, `agentLanguages`
- `agentExperienceSince`, `agentTotalProperties`, `agentRentCount`, `agentSaleCount`, `agentCommercialRentCount`, `agentCommercialSaleCount`
- `agentAvgWhatsappResponseTime`, `agentRating`, `agentReviewCount`
- `brokerName`, `brokerEmail`, `brokerPhone`, `brokerWhatsapp`, `brokerProfileUrl`
- `contactPhone`, `contactWhatsapp`, `contactOptions`, `country`, `sourceDomain`, `scrapedAt`

#### Broker

- `brokerId`, `brokerName`, `brokerProfileUrl`, `brokerLogo`, `brokerSlug`
- `brokerEmail`, `brokerPhone`, `brokerAddress`
- `brokerLicenseNumber`, `brokerLicenseLabel`, `brokerLocation`, `brokerDescription`, `brokerVerified`
- `brokerTotalProperties`, `brokerTotalAgents`, `brokerTotalSuperAgents`, `brokerRentCount`, `brokerSaleCount`
- `contactEmail`, `contactPhone`, `contactOptions`, `country`, `sourceDomain`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search`, `listings`, `agents` or `brokers` |
| `country` | string | `ae` | `ae`, `sa`, `qa`, `bh` or `eg` |
| `city` | string | `dubai` | City, province or governorate; `all` for a country-wide search |
| `purpose` | string | `buy` | `buy`, `rent`, `commercial-buy` or `commercial-rent` |
| `propertyType` | string | `any` | Apartment, villa, townhouse, penthouse, duplex, compound, land, whole building, half floor, office, shop, warehouse, factory or showroom |
| `bedrooms` | string | `any` | `studio`, 1–6, or `7+`; residential searches only |
| `priceMin` / `priceMax` | integer | – | Asking price in the market's local currency |
| `furnishing` | string | `any` | `furnished` or `unfurnished` |
| `completionStatus` | string | `any` | `completed` or `off_plan`; residential sale searches |
| `maxItems` | integer | `100` | Maximum records (1–100,000) |
| `includeDetails` | boolean | `true` | Add the full gallery, permit link, licences, floor plans and agent statistics |
| `startUrls` | array | – | `[{"url": ...}]` objects for listing, search, short or sitemap URLs in `mode: listings` |
| `agentUrls` | array | – | Agent profile URLs or numeric IDs for `mode: agents` |
| `brokerUrls` | array | – | Broker profile URLs or numeric IDs for `mode: brokers` |

**Profile records:** full profile URLs use their own market; `country` is only needed for bare numeric IDs. City is ignored in agent/broker modes.

**Older inputs:** `max_items` and `fetch_full_details` are no longer schema fields but are still honoured, and they take precedence over platform-injected `maxItems`/`includeDetails` defaults. A saved input with `startUrls` plus a legacy key automatically uses `mode: listings`, so old sitemap prefills keep working with their original limit. `max_retries` and `ignore_url_failures` are accepted but ignored.

#### Example: Dubai apartments for sale

```json
{
  "mode": "search",
  "country": "ae",
  "city": "dubai",
  "purpose": "buy",
  "propertyType": "apartment",
  "bedrooms": "2",
  "priceMin": 1000000,
  "priceMax": 2500000,
  "maxItems": 100
}
```

#### Example: furnished Riyadh rentals

```json
{
  "mode": "search",
  "country": "sa",
  "city": "ar-riyadh",
  "purpose": "rent",
  "propertyType": "apartment",
  "furnishing": "furnished",
  "maxItems": 50
}
```

#### Example: scrape specific listing URLs

```json
{
  "mode": "listings",
  "startUrls": [
    {"url": "https://www.propertyfinder.ae/en/plp/buy/apartment-for-sale-dubai-downtown-dubai-bellevue-towers-bellevue-tower-2-158222918.html"},
    {"url": "https://www.propertyfinder.qa/en/rent/doha/apartments-for-rent.html"}
  ],
  "maxItems": 20
}
```

#### Example: collect broker contacts

```json
{
  "mode": "brokers",
  "brokerUrls": ["https://www.propertyfinder.ae/en/broker/betterhomes-business-bay-2593"],
  "maxItems": 5
}
```

### Use cases

- **Property investors** — compare asking prices, size and price per square foot across Dubai, Riyadh, Doha, Manama and Cairo.
- **Lead-generation teams** — collect the public broker/listing contact published on each listing, alongside the listing agent's name and profile.
- **PropTech and valuation teams** — build a fresh inventory snapshot with coordinates, amenities, completion status and permit links.
- **Market researchers** — track new listings, price bands, furnishing and ready/off-plan supply in a specific community.
- **Agency analysts** — monitor an agency's active inventory and profile statistics.

### FAQ

#### Which countries are supported?

The UAE (`propertyfinder.ae`), Saudi Arabia (`.sa`), Qatar (`.qa`), Bahrain (`.bh`) and Egypt (`.eg`). Prices are returned in AED, SAR, QAR, BHD or EGP respectively.

#### Does it return agent email addresses and mobile numbers?

Not as `agentEmail`/`agentPhone`. Property Finder leaves those source fields empty on listings and public profiles (0/217 listings, 0/40 details and 0/37 agent profiles measured). The actor returns the agent's name, profile and statistics, plus the contact published on the listing: broker email/phone and the listing WhatsApp relay number, which is usually Property Finder's market number rather than the agent's personal number. At small agencies the broker line or email can be the agent's own (for example a Gmail address matching the agent's name). The legacy `agentEmail`/`agentPhone`/`agentWhatsapp` fields are kept for compatibility and omitted when empty.

#### Why are some listings missing bedrooms or completion status?

Commercial offices, warehouses and land often have no bedroom count, and completion status is primarily relevant to for-sale listings. Empty values are omitted rather than filled with zero or a placeholder; all-zero placeholder phone numbers such as `+0000000000` are also dropped.

#### What permit data is available?

Saudi listings publish an Elan/REGA permit number and validation link. UAE listings usually publish a Trakheesi validation link and the brokerage licence number, while the permit number itself is less often present. Qatar, Bahrain and Egypt do not publish permit links in the listing payload.

#### Can I collect every listing for a city?

Property Finder allows up to 4,000 pages per search, but the last page varies by query: a broad UAE search returned listings on page 4,000, while Dubai apartments for sale ended at page 3,398 on 2026-10-21. Pages carry 25–35 listings. The actor stops at the first 404 or empty page, and an early source cap is not always flagged in the status message, so watch the emitted count. Split by city, property type or bedrooms to cover more; query-string price/furnishing/completion filters are allowed on page 1 only, because adding `page` to those queries is restricted by robots.txt.

#### What does `includeDetails` add?

It opens each listing's detail page to add the full photo gallery, community and tower images, the permit validation link, licences, floor plans, building details and agent ratings. Turn it off for a lighter dataset with the core search-page fields.

#### Are duplicates removed?

Yes. Listings are deduplicated by Property Finder's numeric listing ID across pages, URLs and sitemaps.

#### Do I need a proxy or a Property Finder account?

No. The actor reads public pages with no login, cookie or API key. It chooses a working connection automatically.

#### Is this affiliated with Property Finder?

No. This is an independent third-party actor. Property Finder's terms prohibit automated scraping and restrict reuse of the content, and its privacy policy applies to contact data. You are responsible for having a lawful basis and for how you use contact details.

#### How fresh is the data?

Each run reads live pages. Schedule the actor daily or weekly to track new listings, price changes and delistings.

# Actor input Schema

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

What to scrape. Search listings by filters, scrape specific listing URLs, or collect agent/broker profiles.

## `country` (type: `string`):

Market to search or the country used for bare agent/broker ids.

## `city` (type: `string`):

City, province or governorate to search. Choose All cities for a country-wide search.

## `purpose` (type: `string`):

Buy, rent, or the commercial equivalents.

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

Residential types: apartment, villa, townhouse, penthouse, duplex, compound, land, whole building, half floor. Commercial types: office, shop, warehouse, factory, showroom.

## `bedrooms` (type: `string`):

Bedroom filter for residential searches. Studio is supported for apartments and mixed-type searches.

## `priceMin` (type: `integer`):

Minimum asking price in the market's local currency (AED, SAR, QAR, BHD or EGP).

## `priceMax` (type: `integer`):

Maximum asking price in the market's local currency.

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

Furnished or unfurnished. Leave on Any furnishing to include both.

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

Ready or off-plan. Applies to residential for-sale searches; ignored for rentals and commercial searches.

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

Maximum number of listings or profiles to return.

## `includeDetails` (type: `boolean`):

Open each listing page to add the full photo gallery, permit validation link, licences, floor plans and agent ratings. Turn off for a faster, lighter dataset.

## `startUrls` (type: `array`):

Property Finder landing, search, listing or short URLs. Used with mode=listings. Sitemap and sitemap-index URLs are also accepted.

## `agentUrls` (type: `array`):

Property Finder agent profile URLs, or bare numeric agent IDs. Used with mode=agents.

## `brokerUrls` (type: `array`):

Property Finder broker/agency profile URLs, or bare numeric broker IDs. Used with mode=brokers.

## Actor input object example

```json
{
  "mode": "search",
  "country": "ae",
  "city": "dubai",
  "purpose": "buy",
  "propertyType": "apartment",
  "bedrooms": "any",
  "furnishing": "any",
  "completionStatus": "any",
  "maxItems": 2,
  "includeDetails": true
}
```

# Actor output Schema

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

Listing, agent and broker records produced by this run.

# 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",
    "country": "ae",
    "city": "dubai",
    "purpose": "buy",
    "propertyType": "apartment",
    "bedrooms": "any",
    "furnishing": "any",
    "completionStatus": "any",
    "maxItems": 2,
    "includeDetails": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/property-finder-mena-listings-and-agent-contact").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",
    "country": "ae",
    "city": "dubai",
    "purpose": "buy",
    "propertyType": "apartment",
    "bedrooms": "any",
    "furnishing": "any",
    "completionStatus": "any",
    "maxItems": 2,
    "includeDetails": True,
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/property-finder-mena-listings-and-agent-contact").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",
  "country": "ae",
  "city": "dubai",
  "purpose": "buy",
  "propertyType": "apartment",
  "bedrooms": "any",
  "furnishing": "any",
  "completionStatus": "any",
  "maxItems": 2,
  "includeDetails": true
}' |
apify call dataspryva/property-finder-mena-listings-and-agent-contact --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataspryva/property-finder-mena-listings-and-agent-contact"
        }
    }
}
```

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/6tmA1k9u56N6klleB/builds/xMhCXrO7B9kNH6URi/openapi.json
