# Bayut Scraper (`parsebird/bayut-scraper`) Actor

Extract real estate listings from Bayut.com: prices, rooms, area, agent and agency contacts, TruCheck verification, permits, and payment plans for UAE properties.

- **URL**: https://apify.com/parsebird/bayut-scraper.md
- **Developed by:** [ParseBird](https://apify.com/parsebird) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.69 / 1,000 listings

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

### Bayut Scraper

Extract real estate listings from [Bayut.com](https://www.bayut.com), the UAE's largest property portal, without writing a single line of scraping code.

<table><tr>
<td style="border-left:4px solid #1C1917;padding:12px 16px;font-weight:600">
Search any UAE city or area for sale or rent, filter by price, bedrooms, area, furnishing, and completion status, and get clean, structured listing data — prices, agent and agency contacts, TruCheck verification, permits, and payment plans — ready for analysis or integration.
</td>
</tr></table>

##### Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.

```
Use the Apify actor "parsebird/bayut-scraper" via the ApifyClient. Example (Python): from apify_client import ApifyClient; client = ApifyClient("<APIFY_TOKEN>"); run = client.actor("parsebird/bayut-scraper").call(run_input={"mode": "search", "locations": ["dubai"], "purpose": "for-sale", "propertyType": "apartments", "maxListings": 20, "fetchDetails": True}); items = list(client.dataset(run["defaultDatasetId"]).iterate_items()). Key inputs: mode ("search" or "url", default "search"), locations (array of city/area slugs, default ["dubai"]), urls (array, for URL mode), purpose ("for-sale"/"to-rent", default "for-sale"), propertyType (default "property" = any type), minPrice/maxPrice, minBedrooms/maxBedrooms, minArea/maxArea, furnishing, completionStatus, rentFrequency, verifiedOnly, sortBy, maxPages (default 0 = unlimited), maxListings (default 5, 0 = unlimited), fetchDetails (default true), incrementalMode, stateKey, resumeFromRunId. Output fields per listing: externalID, url, purpose, propertyType, title, price, currency, rentFrequency, rooms, baths, area, areaUnit, furnishingStatus, completionStatus, country, city, neighbourhood, building, latitude, longitude, isVerified, verificationStatus, agentName, agencyName, phoneMobile, phoneWhatsapp, permitNumber, referenceNumber, images, amenities, description, paymentPlans, createdAt, updatedAt, scrapedAt. Full API reference: https://apify.com/parsebird/bayut-scraper/api. Get an API token at https://console.apify.com/account/integrations.
```

### What does Bayut Scraper do?

Bayut Scraper crawls [Bayut.com](https://www.bayut.com) — the UAE's largest real estate portal, part of the Dubizzle Group — and returns every listing as a clean JSON/CSV/Excel row instead of raw HTML. It works as a **Bayut.com API alternative** for anyone who needs UAE property data without maintaining their own scraper or paying for site access.

- 🔍 **Search by city or area** — Dubai, Abu Dhabi, Sharjah, Ajman, Ras Al Khaimah, and every sub-area (e.g. `dubai/dubai-marina`), for sale or for rent
- 🧭 **Or paste search URLs** — copy any filtered Bayut search URL from your browser and let the actor paginate it automatically
- 🏷️ **Filter by price, bedrooms, area, furnishing, completion status, and verification** — applied server-side where Bayut supports it and re-checked locally so results are always accurate
- 📄 **Optional full-detail enrichment** — complete description, grouped amenities, and Trakheesi permit number per listing
- 🔁 **Incremental (change-tracking) mode** — schedule daily runs and get only NEW, UPDATED, and REAPPEARED listings, with EXPIRED tracking once a search is fully scanned
- ⏸️ **Resume support** — continue an interrupted large pull from a previous run or dataset ID without re-scraping what you already have
- ⚙️ Runs on Apify: **scheduling**, **REST API access**, **webhooks/integrations** (Zapier, Make, Google Sheets), and export to **JSON, CSV, or Excel**

### What data can you extract from Bayut.com?

| Field | Description |
|-------|-------------|
| `externalID`, `url` | Bayut's internal listing ID and canonical URL |
| `purpose`, `propertyType` | for-sale / to-rent, and apartment / villa / townhouse / etc. |
| `title`, `description` | Listing title and full seller description (with `fetchDetails`) |
| `price`, `currency`, `rentFrequency` | Price in AED, and rent period for rentals |
| `rooms`, `baths`, `area`, `areaUnit` | Bedrooms, bathrooms, and floor area |
| `furnishingStatus`, `completionStatus` | Furnished/unfurnished, ready/off-plan |
| `country`, `city`, `neighbourhood`, `building`, `latitude`, `longitude` | Full location hierarchy and coordinates |
| `isVerified`, `verificationStatus`, `trucheckedAt` | Bayut TruCheck™ verification |
| `agentName`, `agencyName`, `phoneMobile`, `phoneWhatsapp` | Agent and agency contact details |
| `permitNumber`, `referenceNumber` | Trakheesi permit (with `fetchDetails`) and Bayut reference |
| `images`, `imageCount`, `amenities`, `paymentPlans` | Full photo gallery, grouped amenities, and off-plan payment plans |

### How to scrape Bayut.com with Bayut Scraper

1. Open the actor's **Input** tab on Apify Console.
2. Pick **Search by location** mode, choose a city/area (e.g. `dubai`), a purpose (`for-sale` or `to-rent`), and a property type.
3. Optionally set price, bedroom, area, furnishing, or verification filters, and a `maxListings` cap.
4. Click **Start** and watch listings land in the **Dataset** tab in real time.
5. Export the results as **JSON, CSV, or Excel**, or pull them via the **API** tab.
6. To track a search over time, turn on **Incremental mode** and attach a **Schedule** so it only returns what changed.

Prefer to paste URLs instead? Open [Bayut.com](https://www.bayut.com/for-sale/apartments/dubai/) in your browser, apply any filters you like, copy the resulting URL, and paste it into **URL mode** — one or many URLs, each paginated forward independently.

### Input parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| mode | string | No | `search` | `search` (filters) or `url` (paste URLs) |
| locations | array | Search mode | `["dubai"]` | City/area slugs, e.g. `dubai`, `dubai/dubai-marina` |
| urls | array | URL mode | — | Bayut search URLs, paginated automatically |
| purpose | string | No | `for-sale` | `for-sale` or `to-rent` |
| propertyType | string | No | `property` | `property` (any), `apartments`, `villas`, `townhouses`, `penthouses`, `hotel-apartments`, `compounds`, `duplex`, `land`, `full-floors`, `half-floors`, `whole-buildings`, `bulk-units`, `commercial` |
| minPrice / maxPrice | integer | No | — | Price range in AED |
| minBedrooms / maxBedrooms | integer | No | — | Bedroom range (0 = studio) |
| minArea / maxArea | integer | No | — | Area range in sqm |
| furnishing | string | No | `any` | `any`, `furnished`, `unfurnished` |
| completionStatus | string | No | `any` | `any`, `completed`, `off-plan` |
| rentFrequency | string | No | `any` | `any`, `yearly`, `monthly`, `weekly`, `daily` (rent only) |
| verifiedOnly | boolean | No | `false` | Only TruCheck-verified listings |
| sortBy | string | No | `popular` | `popular`, `newest`, `oldest`, `price-asc`, `price-desc`, `verified-score-desc` |
| maxPages | integer | No | `0` | Safety cap on pages walked per location/URL. 0 = unlimited (walks until a natural stop) |
| maxListings | integer | No | `5` | Sole soft cap across all locations/URLs. 0 = unlimited |
| fetchDetails | boolean | No | `true` | Adds description, amenities, and permit number per listing |
| proxy | object | No | UAE residential | Apify Proxy configuration |
| resumeFromRunId | string | No | — | Continue one interrupted/previous pull by run or dataset ID |
| incrementalMode | boolean | No | `false` | Daily/recurring monitoring — only changed listings are returned |
| stateKey | string | No | auto | Name a monitoring campaign |
| emitUnchanged / emitExpired | boolean | No | `false` | Incremental mode: also return (and bill) unchanged/expired rows |

### Output example

```json
{
  "externalID": "16478448",
  "url": "https://www.bayut.com/property/details-16478448.html",
  "purpose": "for-sale",
  "propertyType": "apartments",
  "title": "Fresh Cancellation | Trophy Asset | Sea View",
  "price": 4289000,
  "currency": "AED",
  "rentFrequency": null,
  "rooms": 2,
  "baths": 3,
  "area": 113.09,
  "areaUnit": "sqm",
  "furnishingStatus": "unfurnished",
  "completionStatus": "under-construction",
  "country": "UAE",
  "city": "Dubai",
  "neighbourhood": "Palm Jebel Ali",
  "isVerified": true,
  "agentName": "Tamara Kenia",
  "agencyName": "K U N Real Estate",
  "phoneMobile": "+971585498662",
  "referenceNumber": "102520-BX0Lxl",
  "images": ["https://images.bayut.com/thumbnails/865731748-800x600.jpeg"],
  "imageCount": 12,
  "amenities": [{ "group": "Features", "items": [{ "slug": "furnished", "text": "Furnished", "value": null }] }],
  "description": "Palm Central Private Residences by Nakheel | Frond N ...",
  "scrapedAt": "2026-09-12T12:00:00.000Z"
}
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("parsebird/bayut-scraper").call(run_input={
    "mode": "search",
    "locations": ["dubai/dubai-marina"],
    "purpose": "for-sale",
    "propertyType": "apartments",
    "maxListings": 50,
    "fetchDetails": True,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item["price"])
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<APIFY_TOKEN>' });
const run = await client.actor('parsebird/bayut-scraper').call({
    mode: 'search',
    locations: ['dubai'],
    purpose: 'to-rent',
    propertyType: 'apartments',
    maxListings: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Use cases

- Track asking prices and price-per-sqft trends across Dubai communities
- Build a lead list of verified agents and agencies for a specific area
- Monitor new off-plan project launches and payment plan terms
- Feed a property-search app or investment dashboard with live UAE listings
- Compare rent vs. buy pricing across neighbourhoods

### How it works

1. The actor opens a UAE residential proxy session and passes Bayut's anti-bot check once per run.
2. For each location/URL, it walks Bayut's own search results page by page, capturing the same structured data Bayut's website itself uses to render listings.
3. Filters you set (price, bedrooms, area, furnishing, completion, verification) are applied and double-checked against each listing.
4. With `fetchDetails` on, each listing's page is read for its full description, amenities, and permit number.
5. Results are pushed to the dataset as `title`, `price`, `rooms`, contact info, and every other field above, ready to view, filter, and export in Apify Console.

### How much does it cost to scrape Bayut.com?

Bayut Scraper uses **pay-per-event** pricing — you pay only for results, not for platform compute time.

| Event | Price per event | Price per 1,000 |
|-------|----------------|-----------------|
| listing | $0.00099 | **$0.99** |
| enrichment | $0.00099 | **$0.99** |

A `listing` event fires once per returned listing; an `enrichment` event fires once per listing when `fetchDetails` is on and the detail page is read successfully. Scraping 1,000 listings with details enabled costs roughly **$1.98** — under $2 for a full page of 1,000 results with contacts, descriptions, and amenities. Apify's monthly platform usage credits (included with every plan) cover the underlying compute and proxy costs.

### Is it legal to scrape Bayut.com?

Yes — scraping publicly available data such as real estate listings is generally legal, and this actor only collects data that Bayut already displays publicly on its website. That said, you're responsible for how you use the data: respect Bayut's terms of service, avoid excessive request rates, and don't republish personal contact data in ways that violate privacy law. See Apify's [blog post on the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) for more detail.

### Related Actors

- [Immobiliare.it Scraper](https://apify.com/parsebird/immobiliare-it-scraper) — Italian real estate listings
- [Homegate.ch Swiss Real Estate Scraper](https://apify.com/parsebird/homegate-ch-scraper) — Swiss property listings
- [Yad2 Real Estate Scraper](https://apify.com/parsebird/yad2-scraper) — Israeli real estate listings
- [Apartments.com Scraper](https://apify.com/parsebird/apartments-com-scraper) — US rental listings

### FAQ

**How fresh is the data?**
Every run scrapes Bayut.com live — there's no cache. For ongoing monitoring, turn on Incremental mode and schedule a daily run.

**Can I scrape by neighbourhood, not just city?**
Yes. Locations accept any Bayut area slug, e.g. `dubai/dubai-marina`, `dubai/downtown-dubai`, or `abu-dhabi/al-reem-island`.

**What's the difference between Resume and Incremental mode?**
Resume (`resumeFromRunId`) continues one specific interrupted or large pull without re-scraping what's already saved. Incremental mode is for a recurring schedule — it remembers the previous run automatically and returns only what changed.

**Can I schedule recurring runs?**
Yes — use Apify's built-in **Schedule** feature to run daily, weekly, or at any interval, and combine it with Incremental mode to get only new and updated listings.

**Does this work for renting as well as buying?**
Yes. Set `purpose` to `to-rent` and optionally `rentFrequency` to `yearly`, `monthly`, `weekly`, or `daily`.

**What if a run returns 0 results?**
Double-check your location slug matches Bayut's own URL structure, and that your price/bedroom filters aren't too narrow. Open an issue on the actor's Issues tab if the problem persists.

**Is API access available?**
Yes — every run can be triggered and its results retrieved via the Apify API, documented on the actor's [API tab](https://apify.com/parsebird/bayut-scraper/api), with client libraries for Python, JavaScript, and more.

# Actor input Schema

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

`search` = pick locations and filters below, `url` = paste Bayut search URLs directly.

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

Search mode. City or area slugs, e.g. `dubai`, `abu-dhabi`, `dubai/dubai-marina`. One search is run per location.

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

URL mode. Paste Bayut search-result URLs (with any filters already applied in your browser). Each URL is paginated forward independently; filter fields below are ignored in this mode.

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

Search mode.

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

Search mode.

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

Search mode. Sent to Bayut and re-checked locally.

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

Search mode.

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

Search mode. 0 = studio.

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

Search mode.

## `minArea` (type: `integer`):

Search mode. Applied locally.

## `maxArea` (type: `integer`):

Search mode. Applied locally.

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

Search mode. Applied locally.

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

Search mode. Applied locally.

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

Search mode, rent only.

## `verifiedOnly` (type: `boolean`):

Search mode. Applied locally.

## `sortBy` (type: `string`):

Applied locally to the collected results per location/URL.

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

Safety bound on result pages walked per location or URL (~24 listings per page). 0 (default) = unlimited: the walk stops on its own once a page comes back empty, once Bayut's own last-page count is reached, or once Max listings is hit. Set a number only for an explicit page cap below that natural stop.

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

The sole soft cap on the run, applied across all locations/URLs. 0 = unlimited.

## `fetchDetails` (type: `boolean`):

Visit each listing's page for a complete description, grouped amenities, and Trakheesi permit number when available. Adds the enrichment charge per listing.

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

Bayut is protected by an anti-bot challenge; a UAE residential proxy is required and is the default.

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

Continue ONE interrupted or previous large pull. Paste a previous run ID or dataset ID; listings already collected there are skipped and only new ones are appended. For recurring monitoring of the same search, use Incremental mode instead.

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

Track changes across scheduled runs of the same search. Adds a `changeType` (NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED) and `changedFields` to every row. The first run returns everything as NEW.

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

Name a monitoring campaign, or leave empty to derive one automatically from mode + locations/URLs + filters + fetchDetails.

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

Incremental mode only. Also return (and bill) listings identical to the last run.

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

Incremental mode only. Also return (and bill) listings tracked before but no longer found. Only produced once a run scans every tracked search to its natural end (not capped, blocked, or resumed).

## Actor input object example

```json
{
  "mode": "search",
  "locations": [
    "dubai"
  ],
  "urls": [],
  "purpose": "for-sale",
  "propertyType": "property",
  "furnishing": "any",
  "completionStatus": "any",
  "rentFrequency": "any",
  "verifiedOnly": false,
  "sortBy": "popular",
  "maxPages": 0,
  "maxListings": 5,
  "fetchDetails": true,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AE"
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# 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 = {
    "locations": [
        "dubai"
    ],
    "urls": [],
    "maxListings": 5,
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "AE"
    },
    "resumeFromRunId": "",
    "stateKey": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/bayut-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 = {
    "locations": ["dubai"],
    "urls": [],
    "maxListings": 5,
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "AE",
    },
    "resumeFromRunId": "",
    "stateKey": "",
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/bayut-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 '{
  "locations": [
    "dubai"
  ],
  "urls": [],
  "maxListings": 5,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AE"
  },
  "resumeFromRunId": "",
  "stateKey": ""
}' |
apify call parsebird/bayut-scraper --silent --output-dataset

```

## MCP server setup

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