# Dubai Property Investment Analyzer — Yield & Deal Score (`malikgen/dubai-property-analyzer`) Actor

Turn Dubai/UAE property listings into investment intelligence: gross rental yield, median price/sqft, per-listing deal score (under/over market), off-plan vs ready premium, and developer benchmarks by area. The analytics layer no raw scraper offers.

- **URL**: https://apify.com/malikgen/dubai-property-analyzer.md
- **Developed by:** [Malikgen](https://apify.com/malikgen) (community)
- **Categories:** Real estate
- **Stats:** 4 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $5.00 / 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?

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

## Dubai Property Investment Analyzer — Yield, Price/Sqft & Deal Score

Turn Dubai/UAE property listings into **investment intelligence**. Enter an area (e.g. *Dubai Marina*) and get what raw scrapers don't: **gross rental yield**, **median price/sqft** (with percentiles), a per-listing **Deal Score** (under/over market), **off-plan vs ready premium**, and **developer/tower benchmarks** — plus every analyzed listing with its score. Clean JSON for spreadsheets, dashboards, or AI pipelines.

> Built for investors, buyer's agents, and PropTech teams who need market context before committing capital.

***

### Why this is different

Most UAE scrapers dump raw listings. This one **computes the analytics on top**:

| | Raw listing scrapers | **This analyzer** |
|---|:---:|:---:|
| Listings (price, beds, area, agent) | ✅ | ✅ |
| **Gross rental yield** (rent ÷ sale, per bedroom) | ❌ | ✅ |
| **Median price/sqft + p25/p75** | ❌ | ✅ |
| **Per-listing Deal Score** (under/over market) | ❌ | ✅ |
| **Off-plan vs ready premium** | ❌ | ✅ |
| **Developer / tower benchmarks** | ❌ | ✅ |
| Reliable (no browser, pure API) | varies | ✅ |

***

### Quick start

1. Enter an **Area / community** (e.g. `Dubai Marina`, `Business Bay`, `JVC`, `Downtown Dubai`) — or several in **Areas**.
2. Pick **Property type** (apartments / villas / townhouses / penthouses) and **Max listings per area** (default 200).
3. Click **Start**. You get one **area\_insights** rollup per area + every analyzed sale listing (with its deal score).

If an area name doesn't resolve, pass the exact **locationSlug** (e.g. `/dubai/dubai-marina`).

***

### Output

Two record types in one dataset (the **All data** view shows everything; use **Listings only** / **Area insights only** for focused tables):

**`area_insights`** (one per area): `medianSalePrice`, `medianPricePerSqft` (+`pricePerSqftP25/P75`), `medianAnnualRent`, **`grossRentalYieldPct`** (+ `yieldBasis`), per-`bedroomBreakdown` (count, median price, price/sqft, gross yield, `sampleReliability`), `offplanPremiumPct` (+`readyCount`/`offplanCount`), `topTowers`, `verifiedListingsPct`, `furnishedRentalsPct`, `saleSampleCoveragePct`/`rentSampleCoveragePct`, `methodology`.

**`listing`** (one per analyzed sale listing): `price`, `areaSqft`, `pricePerSqft`, `bedrooms`, `bathrooms`, `status` (ready/off-plan), **`dealScorePct`** + `dealLabel` + `underpriced`, `tower`, `developer`, `project`, `furnishingStatus`, `isVerified`, `agencyName`, `coordinates`, `url`, `title`. All fields always present (`null` when unavailable).

Sample: [`docs/example-output.json`](docs/example-output.json).

***

### ⚠️ Methodology & honest caveats (read before using the numbers)

These are **estimates from public asking-price listings** for market research — **not financial advice**, and not official transaction data.

- **Asking prices, not actuals.** Both the rent and sale figures are Bayut **asking** prices, not DLD-registered sale prices or RERA-contracted rents (Dubai asking rents often run 5–15% above contracted). `grossRentalYieldPct` is therefore an **asking yield**.
- **Gross, pre-all-costs.** Yield is **pre-vacancy, pre-service-charge, pre-agency-fee, pre-finance, pre-tax** (see `yieldBasis`). Net yields are materially lower.
- **Sample bias.** Metrics use up to `maxListings` listings out of potentially thousands (see `saleSampleCoveragePct`). Bayut's default sort over-represents featured listings, so the "market median" baseline reflects the **sampled set**. Increase `maxListings` for a fuller picture.
- **Thin bedroom buckets.** Per-bedroom yields are omitted (`null`, with a `yieldNote`) when a bucket has fewer than 5 sale or rent listings; each carries a `sampleReliability` (low/medium/high).
- **Off-plan premium is not risk-adjusted.** `offplanPremiumPct` is an asking price/sqft difference; it ignores developer/construction risk. Check `offplanCount`/`readyCount` for sub-sample size.
- **`verifiedListingsPct` = Bayut TruCheck** (agent visited the property) — it is **not** DLD/title verification or a price-accuracy guarantee.
- **Webhook envelope:** payloads are wrapped as `{ source, timestamp, data }` — unwrap `body.data` in n8n/Make.

> **Roadmap:** DLD actual-sold transaction enrichment (Dubai Pulse) to add "asking vs actual" and historical trends.

***

### How it works

Reliable **pure-HTTP** — no browser, no captcha. Pulls listings from Bayut's own search API using browser-grade TLS/headers over an Apify **residential (UAE)** proxy, then computes the analytics in-actor. Leave the default proxy on.

### Run via API

```bash
curl -X POST "https://api.apify.com/v2/acts/malikgen~dubai-property-analyzer/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"location":"Dubai Marina","propertyType":"apartments","maxListings":200}'
```

### Pricing

Pay per result. Headline **≈ $6 / 1,000 results** — the only investment-analytics actor for Dubai (raw listing scrapers are $0.0008–0.003 but compute none of this).

### Changelog

- **0.1** — Initial release. Area → per-listing deal scores + per-area rollup (yield, price/sqft, off-plan premium, developer/tower benchmarks). Pure-HTTP Bayut data source.

***

*Not affiliated with Bayut, Dubai Land Department, or any portal. Produces estimates from publicly available listing data for research. Respect each site's Terms of Service and applicable laws.*

# Actor input Schema

## `location` (type: `string`):

A Dubai/UAE area to analyze, e.g. "Dubai Marina", "Business Bay", "JVC", "Downtown Dubai". (Or use Areas for several.)

## `areas` (type: `array`):

Analyze several areas in one run (each becomes one insights record). Overrides Area.

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

Used to build the location path.

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

Which property category to analyze.

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

How many sale (and rent) listings to sample per area for the analytics. Higher = more accurate, more cost.

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

Filter out sale listings below this price.

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

Filter out sale listings above this price.

## `minBeds` (type: `integer`):

Only analyze listings with at least this many bedrooms.

## `includeRentalYield` (type: `boolean`):

Also fetch rentals to compute gross rental yield (median annual rent ÷ median sale price).

## `includeDealScore` (type: `boolean`):

Score each sale listing's price/sqft vs the area median (under/over market).

## `includeListings` (type: `boolean`):

Output every analyzed sale listing (with deal score). Turn off for area-summary records only.

## `locationSlug` (type: `string`):

Override the auto-built path, e.g. "/dubai/dubai-marina". Use if an area name doesn't resolve.

## `webhookUrl` (type: `string`):

POST the full result set here when the run finishes (n8n / Make / Zapier).

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

Bayut requires UAE residential proxies. Leave the default.

## Actor input object example

```json
{
  "location": "Dubai Marina",
  "emirate": "dubai",
  "propertyType": "apartments",
  "maxListings": 200,
  "includeRentalYield": true,
  "includeDealScore": true,
  "includeListings": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AE"
  }
}
```

# Actor output Schema

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

Key identity, price, rating, and location per listing

## `full` (type: `string`):

All fields including amenities, images, host info, and price breakdown

# 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 = {
    "location": "Dubai Marina",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "AE"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("malikgen/dubai-property-analyzer").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 = {
    "location": "Dubai Marina",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "AE",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("malikgen/dubai-property-analyzer").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 '{
  "location": "Dubai Marina",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AE"
  }
}' |
apify call malikgen/dubai-property-analyzer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,malikgen/dubai-property-analyzer"
        }
    }
}

```

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/0y2BeM9YQDNrlT5VY/builds/cAoj4St4VKVdY0fb7/openapi.json
