# Bayut Property Scraper (`one-api/bayut-property-scraper`) Actor

Scrape Bayut.com UAE listings, property details, agency / agent / truBroker lookups, claimed-deals stats, agent stories, and location autocomplete in real time. Search by city or neighbourhood externalID with full filters (purpose, completion status, price, beds, baths, area).

- **URL**: https://apify.com/one-api/bayut-property-scraper.md
- **Developed by:** [ONE API](https://apify.com/one-api) (community)
- **Categories:** Lead generation, Real estate
- **Stats:** 22 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 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

## Bayut.com Property Scraper

Scrape **Bayut.com** UAE property listings (Dubai, Abu Dhabi, Sharjah, Ajman, RAK, Fujairah, UAQ), full property details, agency / agent / truBroker lookups, claimed-deals stats, agent stories, and location autocomplete — all from one Actor. Backed by [realtyapi.io](https://realtyapi.io)'s real-time Bayut API.

⭐️ Found this useful? Please leave 5 stars! Issues / requests: 📬 **oneapi.project@gmail.com**

***

### What you can do

| Section | What it does | Input format |
|---|---|---|
| 🏠 **Property Details** | Full details for a specific listing | `externalID` digits, Bayut listing URL, or `details_NNN` slug — auto-detected per row |
| 🔎 **Search Listings** | Paginated UAE property search with full filter set | location externalID (e.g. `5002` for Dubai), Bayut slug, or Bayut search URL |
| 🔍 **Autocomplete** | Location lookup: cities, neighbourhoods, sub-communities, towers | partial query string (`dubai marina`, `palm jumeirah`) |
| 🏢 **Agency Details** | Full agency profile by externalID | digits |
| 👤 **Agents under an Agency** | All agents at one agency, with their slugs | agency externalID |
| 👤 **Agent Details** | Full agent profile with listing counts | agent slug `<name>-<externalID>` |
| ⭐ **TruBroker Agents** | Top-ranked agents in a location | location externalID |
| 📖 **Agent Stories** | Recent posts/updates an agent has published | agent externalID |
| 💰 **Agent Claimed Deals** | Lifetime deal count + total transaction price (For Sale, For Rent, Wanted) | agent externalID |

You can fill any combination of sections in a single run — leave the others empty.

***

### Output

Each listing / agent / agency / story / autocomplete suggestion is pushed as **one dataset row**, flattened to friendly columns plus a `Raw` column with the original JSON.

| Mode | External ID | Status | Price (AED) | Beds | Baths | Sqft | Type | Completion | City | Community | Agency |
|---|---|---|---|---|---|---|---|---|---|---|---|
| `search/byid` | 11602994 | active | 15599999 | 5 | 7 | 8612 | Villas | under-construction | Dubai | The Oasis by Emaar | Hills Field Real Estate |
| `details/property` | 15062791 | active | 15599999 | 5 | 7 | 8612 | Villas | under-construction | Dubai | The Oasis by Emaar | Hills Field Real Estate |
| `autocomplete` | 5002 | — | — | — | — | — | location | — | Dubai | — | — |
| `trubroker/byid` | 2099259 | rank 18 | — | 47 | 12 | — | — | — | Dubai | — | — |

Plus: `Reference Number`, `Title`, `Purpose`, `Rent Frequency`, `Plot Area Sqft`, `Permit Number`, `Furnishing`, `Verified`, `Sub Community`, `Latitude`, `Longitude`, `Created At`, `Updated At`, `Photo` (cover URL), `Photo Count`, `Panorama Count`, `Video Count`, `Agent ID`, `Agent Name`, `Phone`, `WhatsApp`, `Listing URL`.

For nested fields (full photo arrays, panoramas, payment plans, amenities, completion details, multi-language titles), the complete upstream JSON is in the `Raw` column.

> **Area note**: Bayut's API returns `area` in **square metres**. The `Area Sqft` and `Plot Area Sqft` columns are converted to sqft for you. The `areaSqftRange` filter is also taken in sqft and converted before sending.

***

### Sample input

```json
{
    "property_inputs": [
        "15062791",
        "https://www.bayut.com/property/details_15062791.html"
    ],
    "search_inputs": ["5002", "dubai-marina"],
    "purpose": "for-sale",
    "category": "residential",
    "completionStatus": "completed",
    "priceRange": "min:1000000,max:5000000",
    "beds": "3",
    "areaSqftRange": "min:1500",
    "pages": 2,

    "autocomplete_inputs": ["dubai marina"],
    "agency_inputs": ["10499"],
    "agency_agents_inputs": ["10499"],
    "agent_inputs": ["salma-mohamed-mahmoud-hashem-2521536"],
    "trubroker_inputs": ["6901"],
    "stories_inputs": ["2510010"],
    "claimeddeals_inputs": ["1919589"]
}
```

***

### Search filters (apply to every `search_inputs` row)

- **purpose** — `for-sale` (default) or `for-rent`.
- **category** — `residential` (default) or `commercial`.
- **completionStatus** — `completed` (ready), `under-construction` (off-plan), or empty (any).
- **priceRange** — `min:X` | `max:Y` | `min:X,max:Y` in AED.
- **beds, baths** — exact integer match (Bayut's API only accepts a single value, not a range). For studios use `0`.
- **areaSqftRange** — `min:X` | `max:Y` | `min:X,max:Y` in sqft (we convert to sqm internally).
- **furnishingStatus** — `furnished`, `unfurnished`, `partly-furnished`, or empty (any).
- **rentFrequency** — `yearly`, `monthly`, `weekly`, `daily` (used only when `purpose=for-rent`).
- **hasPanorama, hasVideo, hasFloorplan** — booleans, true = listings with that asset only.
- **agency\_external\_ids** — comma list (e.g. `10499,29599755`) — restrict to those agencies.
- **hitsPerPage** — 1–25 (Bayut's max page size). Default 25.
- **pages** — pages to fetch per query (1–50). Bayut deep pagination caps around 40 pages.

***

### Pricing

**Pay per result** — $3 per 1,000 items pushed. Failed inputs return a row with `Status: ERROR: ...` and are billed the same as a successful row.

To cap spend, set `Max paid dataset items` on the run page.

***

### Tips

- **Need just one property?** Use `property_inputs` — auto-detects externalID, URL, or `details_NNN` slug.
- **Pull all listings in a city?** Use `search_inputs: ["5002"]` (Dubai) with `pages: 5` for ~125 listings; `5002`=Dubai, `6020`=Abu Dhabi, `6901`=Sharjah, `5891`=Ajman, `7008`=RAK.
- **Don't know the location externalID?** Run `autocomplete_inputs` first with the area name (e.g. `dubai marina`) — the first result's `External ID` is what you want.
- **Find every agent at an agency?** Use `agency_agents_inputs: ["<agencyID>"]` — returns each agent with their slug, ready to drop into `agent_inputs`.
- **Off-plan only?** Set `completionStatus: "under-construction"`.
- **Top agents in a city?** Use `trubroker_inputs: ["5002"]` with `purpose=for-sale, completionStatus=completed`.
- **Resolve a Bayut search URL?** Drop the URL into `search_inputs` — we extract the location slug and resolve via autocomplete.

# Actor input Schema

## `property_inputs` (type: `array`):

Auto-detects each entry: digits → externalID, http(s) URL → Bayut listing URL (we extract the externalID), `details_NNN` slug → externalID. Each row = 1 property detail call.

## `search_inputs` (type: `array`):

Auto-detects each entry. Examples:
• `5002` (Dubai externalID — get from /autocomplete)
• `6020` (Abu Dhabi), `6901` (Sharjah)
• `dubai-marina` (slug — we resolve via /autocomplete)
• `https://www.bayut.com/to-rent/property/dubai/` (Bayut URL — we resolve)

Filters below apply to every search. Each LISTING is pushed as one dataset item.

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

for-sale (default) or for-rent.

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

Top-level category. Defaults to residential.

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

Bayut filter: `completed` (ready), `under-construction` (off-plan), or empty (any).

## `priceRange` (type: `string`):

`min:500000`, `max:5000000`, or `min:500000,max:5000000`.

## `beds` (type: `string`):

Bayut filters by exact bed count (e.g. `2`, `5`). Empty = any. Bayut's range filter uses single values only — for studio enter `0`.

## `baths` (type: `string`):

Exact bath count (e.g. `2`). Empty = any.

## `areaSqftRange` (type: `string`):

`min:800`, `max:3000`, `min:800,max:3000`. Bayut's API works in sqm — we convert sqft→sqm automatically.

## `furnishingStatus` (type: `string`):

Bayut furnishing filter. Empty = any.

## `rentFrequency` (type: `string`):

Used when `purpose` = `for-rent`. Yearly is most common in the UAE.

## `hasPanorama` (type: `boolean`):

Only listings with at least one 360° panorama image.

## `hasVideo` (type: `boolean`):

Only listings with at least one video tour.

## `hasFloorplan` (type: `boolean`):

Only listings with a floor plan attached.

## `agency_external_ids` (type: `string`):

Restrict to listings owned by one or more agencies. e.g. `10499,29599755`.

## `hitsPerPage` (type: `integer`):

Bayut allows up to 25 listings per page (default).

## `pages` (type: `integer`):

Each page = up to 25 listings. Bayut caps deep pagination — typical max useful depth is ~40 pages.

## `autocomplete_inputs` (type: `array`):

Bayut location lookup: cities, neighbourhoods, sub-communities, towers. Use the resulting `externalID` as `search_inputs`.

## `agency_inputs` (type: `array`):

Get the full agency profile (name, agents count, license number, phone). The agency `externalID` is shown as `Agency ID` in any search row.

## `agency_agents_inputs` (type: `array`):

Returns every agent registered under this agency, with their own externalID + slug for use in the Agent Details section.

## `agent_inputs` (type: `array`):

Agent slug — find it from any search row's `ownerAgent.externalID` looked up via `agency_agents_inputs`, or directly from the Bayut.com agent profile URL. Format: `<name>-<externalID>`.

## `trubroker_inputs` (type: `array`):

Bayut's top-ranked agents in a location, with badges (truBroker, responsive, quality lister). Same format as `search_inputs` — use a location externalID. Honours `purpose`, `category`, `completionStatus`.

## `stories_inputs` (type: `array`):

Recent updates / posts an agent has published on Bayut. Pass agent `externalID` (digits, e.g. `2510010`).

## `claimeddeals_inputs` (type: `array`):

Lifetime closed-deal stats per agent: count of pending/rejected/approved deals (For Sale, For Rent, Wanted) and their total transaction value in AED. Returns 2 dataset rows per agent (one for /count, one for /totalPrice).

## Actor input object example

```json
{
  "property_inputs": [
    "15062791",
    "https://www.bayut.com/property/details_15062791.html"
  ],
  "search_inputs": [
    "5002"
  ],
  "purpose": "for-sale",
  "category": "residential",
  "completionStatus": "",
  "priceRange": "",
  "beds": "",
  "baths": "",
  "areaSqftRange": "",
  "furnishingStatus": "",
  "rentFrequency": "",
  "hasPanorama": false,
  "hasVideo": false,
  "hasFloorplan": false,
  "agency_external_ids": "",
  "hitsPerPage": 25,
  "pages": 1
}
```

# 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 = {
    "property_inputs": [
        "15062791",
        "https://www.bayut.com/property/details_15062791.html"
    ],
    "search_inputs": [
        "5002"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("one-api/bayut-property-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 = {
    "property_inputs": [
        "15062791",
        "https://www.bayut.com/property/details_15062791.html",
    ],
    "search_inputs": ["5002"],
}

# Run the Actor and wait for it to finish
run = client.actor("one-api/bayut-property-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 '{
  "property_inputs": [
    "15062791",
    "https://www.bayut.com/property/details_15062791.html"
  ],
  "search_inputs": [
    "5002"
  ]
}' |
apify call one-api/bayut-property-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,one-api/bayut-property-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/G3v3fbuCkU9WmrmLC/builds/RyG4RW4nc0ZlWJQDA/openapi.json
