# Mubawab Scraper – Morocco & Tunisia Property Data (`sian.agency/mubawab-property-scraper`) Actor

Scrape mubawab.ma and mubawab.tn property listings: asking price and rent in MAD or TND, surface, rooms, neighbourhood, GPS coordinates, agency and full advert text. Mubawab data in JSON or CSV.

- **URL**: https://apify.com/sian.agency/mubawab-property-scraper.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** Real estate, Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.06 / 1,000 listing searches

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

## Mubawab Scraper – Morocco & Tunisia Property Data 🚀

[![SIÁN Agency Store](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Bayut](https://img.shields.io/badge/Store-Bayut%20Scraper-93D500)](https://apify.com/sian.agency/bayut-property-scraper?fpr=sian) [![Hepsiemlak](https://img.shields.io/badge/Store-Hepsiemlak%20Scraper-E4002B)](https://apify.com/sian.agency/hepsiemlak-property-scraper?fpr=sian) [![Encuentra24](https://img.shields.io/badge/Store-Encuentra24%20Scraper-1AE392)](https://apify.com/sian.agency/encuentra24-property-scraper?fpr=sian)

#### 🎉 31 complete listings per page — Morocco AND Tunisia from one actor

##### Built for Maghreb market analysts, estate agencies and relocation portals working mubawab.ma and mubawab.tn

***

### 🔎 What is the Mubawab Scraper — and when should you use it?

The **Mubawab Scraper** turns mubawab.ma and mubawab.tn property adverts from any Moroccan or Tunisian city into clean, structured rows you can filter, export and feed straight into a spreadsheet, database or AI agent. No account, no portal API key, no browser automation to maintain.

**Use it when you need:** Maghreb property adverts as rows: asking price or monthly rent with its currency, MAD in Morocco and TND in Tunisia. Each row also carries the price exactly as the portal prints it, surface in m2, bedroom and bathroom counts, neighbourhood and city, amenities, photos and the advert excerpt. The advert id is Mubawab's own and is stable, so scheduled runs deduplicate cleanly. Switch to Listing Detail and a row gains real GPS coordinates from the advert's own map, the numeric price from the portal's structured data, total room count, the agency behind the advert and its attribute sheet. Apartments are one section of seven: villas, houses, riads, land, shops and offices are inputs too, across sale, long rent and holiday let.

**Use something else when:** the property is not on Mubawab, or you need a different market. Use [Bayut Scraper](https://apify.com/sian.agency/bayut-property-scraper?fpr=sian) for the UAE - Dubai, Abu Dhabi and Sharjah - a Gulf portal with its own inventory and no overlap with the Maghreb. Use [Encuentra24 Scraper](https://apify.com/sian.agency/encuentra24-property-scraper?fpr=sian) for Central American property across seven countries, on the same row shape. This actor covers the public French edition of mubawab.ma and mubawab.tn - every section the portal publishes, nationwide, with no depth ceiling. It does not cover mubawab.dz, which has no DNS records at all and is not a live site whatever a rival's title claims; the portal's Arabic edition, which uses a different URL grammar; advertiser phone numbers, which Mubawab reveals only through a lead form; or any other Moroccan or Tunisian portal, so a property also advertised on Avito will not be flagged as a cross-post.

### 🤖 Use with AI agents

Already connected to the [Apify MCP server](https://mcp.apify.com)? Just ask for this Actor by name: sian.agency/mubawab-property-scraper

**Your agent can pay for its own runs.** This Actor is eligible for [agentic payments](https://docs.apify.com/platform/actors/publishing/monetize), so an agent can discover it, run it and settle the bill over [x402](https://www.x402.org/) (USDC on Base) or [Skyfire](https://www.skyfire.xyz/) — without an Apify account or API token of its own. Billing is the same either way: per successful row, never for errors.

Otherwise copy this prompt into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```text
I want property adverts from Mubawab, the leading portal in Morocco and Tunisia using the Apify Actor `sian.agency/mubawab-property-scraper`.

Use it when I need: Maghreb property adverts as rows: asking price or monthly rent with its currency, MAD in Morocco and TND in Tunisia. Each row also carries the price exactly as the portal prints it, surface in m2, bedroom and bathroom counts, neighbourhood and city, amenities, photos and the advert excerpt. The advert id is Mubawab's own and is stable, so scheduled runs deduplicate cleanly. Switch to Listing Detail and a row gains real GPS coordinates from the advert's own map, the numeric price from the portal's structured data, total room count, the agency behind the advert and its attribute sheet. Apartments are one section of seven: villas, houses, riads, land, shops and offices are inputs too, across sale, long rent and holiday let.

Don't use it when: the property is not on Mubawab, or you need a different market — use bayut-property-scraper or encuentra24-property-scraper instead.

How to call it: set `market` to `ma` or `tn`, then pick `propertyType` (apartment, villa, house, riad, land, shop, office) and `transaction` (sale, rent, vacation). Add `city` written the way Mubawab writes it, accents included (`casablanca`, `marrakech`, `fès`, `salé`, `tunis`), or leave it empty to sweep the whole country. `minPrice`, `maxPrice`, `minRooms` and `minAreaSqm` narrow the results before you are billed. For coordinates, the agency and the full advert text, switch `operation` to `detail` and pass advert URLs in `listingUrls` as {url} objects.

Start with this input:
{
  "operation": "search",
  "market": "ma",
  "propertyType": "apartment",
  "transaction": "sale",
  "city": "casablanca",
  "minPrice": 1000000,
  "maxPrice": 3000000,
  "maxResults": 100
}

Ask me which country and cities to cover, which section they want (apartments, villas, riads, land, shops or offices, and sale or rent), and whether the coordinates, agency and full advert text are worth switching to Listing Detail, then run the Actor and summarise the results as a table.
```

**Things you can ask your agent for:**

- *Pull every apartment for sale in Casablanca between 1,000,000 and 3,000,000 MAD and give me the median price per m2 by neighbourhood*
- *Find riads for sale in Marrakech over 200 m2, then open each one to get its coordinates and the agency behind it*
- *Compare the Tunis and Casablanca rental markets: run both, and summarise median monthly rent and surface by city*

Machine-readable API, MCP config and OpenAPI definition for this Actor are published at [apify.com/sian.agency/mubawab-property-scraper.md](https://apify.com/sian.agency/mubawab-property-scraper.md).

### 📋 Overview

**Mubawab is the property portal people in Morocco and Tunisia actually use.** Around 79,000 live adverts across the two countries, and 40,500 brand searches a month in Morocco alone. This actor turns those adverts into rows.

**What you get:**

- ✅ **Two countries, one input**: mubawab.ma and mubawab.tn run on the same application and share one listing-id space. Flip `market` and the same parser reads Tunisia.
- ⚡ **31 listings per page fetch**: the portal renders its result pages server-side, so one request already contains 31 complete records. Nothing to wait on.
- 🎯 **Seven sections, apartments included**: riads, land, shops and offices are inputs in their own right. Morocco alone carries 6,994 land adverts, and Tunisia another 3,510 — inventory most portal scrapers never touch.
- 💰 **Filters that bill honestly**: price, bedroom and surface bounds are applied before the charge, so a listing you ruled out never reaches your invoice.
- 💎 **A detail record no rival carries**: exact GPS coordinates, the numeric price from the portal's own structured data, the agency behind the advert, the attribute sheet and the full advert text.
- ✨ **Stable listing ids**: schedule the run and the rows deduplicate cleanly across days.

***

### ✨ Features

- 🔍 **Listing Search**: walk any Mubawab section, country-wide or narrowed to a city, and get one complete row per advert.
- 📄 **Listing Detail**: open the adverts you name and add coordinates, agency, attribute sheet and complete text.
- 🌍 **Morocco and Tunisia**: MAD and TND, both parsed and labelled, from one `market` switch.
- 🏠 **Seven property types**: apartment, villa, house, riad, land, shop and office, across sale, long rent and holiday let.
- 📍 **Real coordinates**: latitude and longitude read from the portal's own map fields, so rows drop straight onto a map with no geocoding pass.
- 🎚️ **Price, bedroom and surface filters**: applied before billing, never after.
- 🖼️ **Full photo sets**: every image on the advert, with a count.
- 🧾 **Honest empty prices**: "Prix à consulter" stays a label. `price` stays null rather than becoming a zero that poisons your averages.
- 📊 **The portal's own match count**: every row carries how many listings Mubawab says match that search.
- 🔁 **Promoted-advert dedup**: Mubawab pins its promoted adverts to every page; repeats are dropped before you are charged.

***

### 🎬 Quick Start

Pick a market, a property type and a transaction. Add a city if you want one. Press Start.

```bash
curl -X POST "https://api.apify.com/v2/acts/sian.agency~mubawab-property-scraper/runs?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"operation":"search","market":"ma","propertyType":"apartment","transaction":"sale","city":"casablanca","maxResults":100}'
```

***

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Choose the market and the section

Morocco or Tunisia, then the property type and whether you want sale, long rent or holiday let.

#### Step 2: Narrow it, or don't

Name a city the way Mubawab writes it — `casablanca`, `marrakech`, `fès`, `tunis` — or leave it empty to sweep the whole country. Add price, bedroom or surface bounds if you have them.

#### Step 3: Run it

Set `maxResults` to cap your own spend and start the run.

**That's it. In under a minute you'll have:**

- One row per advert with price, surface, rooms, neighbourhood and photos
- A JSON or CSV export ready for a sheet, a database or an agent
- A run report showing exactly what you were charged for

***

### 📥 Input Configuration

| Field | Type | Required | Description |
|---|---|---|---|
| `operation` | string | No | `search` (default) or `detail` |
| `market` | string | No | `ma` for Morocco, `tn` for Tunisia |
| `propertyType` | string | No | `apartment`, `villa`, `house`, `riad`, `land`, `shop`, `office` |
| `transaction` | string | No | `sale`, `rent` or `vacation` |
| `city` | string | No | A city as Mubawab writes it, accents kept. Empty searches nationwide |
| `minPrice` | integer | No | Keep listings at or above this price, in MAD or TND |
| `maxPrice` | integer | No | Keep listings at or below this price |
| `minRooms` | integer | No | Keep listings with at least this many bedrooms |
| `minAreaSqm` | integer | No | Keep listings of at least this surface in m² |
| `maxResults` | integer | No | Stop after this many rows (default 100) |
| `listingUrls` | array | No | For `detail`: listing URLs as `{"url": "…"}` objects |

**Search example:**

```json
{
  "operation": "search",
  "market": "ma",
  "propertyType": "villa",
  "transaction": "sale",
  "city": "marrakech",
  "minPrice": 2000000,
  "maxResults": 200
}
```

**Detail example:**

```json
{
  "operation": "detail",
  "listingUrls": [
    { "url": "https://www.mubawab.ma/fr/a/8115280/appartement-neuf-83-m2-a-gueliz" },
    { "url": "https://www.mubawab.tn/fr/a/8308831/appartement-a-vendre-la-marsa" }
  ]
}
```

Riads are sale-only and a Moroccan format. Holiday lets exist for apartments and villas. Ask for a pairing Mubawab has no section for and the run says so, listing the pairings that section supports, rather than quietly returning a different one.

***

### 📤 Output

Every row is flat JSON. Export as JSON, CSV or Excel, or read it straight from the API.

| Field | Type | Description |
|---|---|---|
| `listingId` | string | Mubawab's own advert id — stable, and what dedup keys on |
| `url` | string | The advert's page |
| `market` / `country` | string | `ma`/`tn` and Morocco/Tunisia |
| `transaction` | string | sale, rent or vacation |
| `propertyType` | string | The section, or the portal's own label on a detail row |
| `titleText` | string | The advert headline |
| `price` | integer | The number, or null when the advert withholds it |
| `currency` | string | MAD or TND |
| `priceLabel` | string | Exactly as Mubawab prints it, including "Prix à consulter" |
| `pricePerSqm` | integer | Derived, and null unless both price and surface are real |
| `areaSqm` | integer | Surface in m² |
| `bedrooms` / `bathrooms` / `rooms` | integer | Counts as advertised |
| `neighbourhood` / `city` | string | Where the property is |
| `latitude` / `longitude` | number | Detail rows: the advert's own map position |
| `agencyName` | string | Detail rows: the agency behind the advert |
| `amenities` | array | Pool, lift, garage, air conditioning, fitted kitchen… |
| `attributes` | object | Detail rows: condition, building age, floor, flooring |
| `descriptionText` | string | The advert text |
| `isPromoted` | boolean | Whether Mubawab pinned this advert to the top |
| `imageUrl` / `imageUrls` / `photoCount` | string / array / integer | The full photo set |
| `searchUrl` / `searchResultCount` | string / integer | The page it came from and how many matches Mubawab reports |
| `scrapedAt` | string | ISO timestamp of the read |

**Example row:**

```json
{
  "operation": "detail",
  "listingId": "8115280",
  "url": "https://www.mubawab.ma/fr/a/8115280/appartement-neuf-83-m2-a-gueliz",
  "market": "ma",
  "country": "Morocco",
  "propertyType": "Appartement",
  "titleText": "Appartement Neuf 83 m² à Guéliz avec Salle de Sport",
  "price": 1560000,
  "currency": "MAD",
  "priceLabel": "1 560 000 DH",
  "pricePerSqm": 18795,
  "areaSqm": 83,
  "rooms": 3,
  "bedrooms": 2,
  "bathrooms": 1,
  "neighbourhood": "Guéliz",
  "city": "Marrakech",
  "latitude": 31.64594579908345,
  "longitude": -8.011576162757956,
  "agencyName": "Group JNANE NIZAR",
  "amenities": ["Terrasse", "Garage", "Ascenseur", "Piscine", "Climatisation"],
  "attributes": { "Type de bien": "Appartement", "Etat": "Bon état / habitable", "Étage du bien": "1er" },
  "photoCount": 29,
  "scrapedAt": "2026-09-10T02:43:46.744Z"
}
```

***

### 🗺️ Coverage

Measured live on 2026-09-10.

**Morocco (mubawab.ma) — 57,600 live adverts.** Apartments for sale 15,126 · apartments to rent 14,628 · land 6,994 · villas and luxury houses for sale 6,205 · shops and units 4,458 · offices and commercial 3,665 · villas to rent 2,861 · houses 2,201 · riads 1,149 · holiday apartments 967 · holiday villas 149.

**Tunisia (mubawab.tn) — 22,164 live adverts** across the same sections. Riads are Moroccan and do not exist there.

**Cities** are whatever the portal itself carries. Casablanca alone holds 4,805 apartments for sale, Marrakech 2,585, Tanger 1,528, Rabat 393, Fès 314, Salé 260, Kénitra 260, Temara 202, Tétouan 197, El Jadida 187. Tunisia adds Tunis, Sousse, Sfax, Ariana, Hammamet, Djerba, Nabeul, La Marsa and Carthage. Leave the city empty and the search runs nationwide.

Mubawab writes its city addresses with the accents in place, so `fès`, `salé`, `kénitra` and `béni-mellal` are the spellings that work. Type the plain name and the run lower-cases and hyphenates it for you.

***

### 💼 Use Cases & Examples

#### 1. Maghreb property-market analysts

**Track asking prices and price per m² across two countries without reconciling two scrapers.**

**Input:** a city and a section, run on a schedule
**Output:** one row per advert with price, surface, rooms, neighbourhood and the portal's own match count
**Use:** build the Casablanca or Tunis price series the portals themselves only publish in summary

#### 2. Estate agencies and brokers

**See how every competing advert on your street is priced.**

**Input:** your city plus the section you list in
**Output:** surface, bedroom count, amenities and asking price for each rival advert
**Use:** price a new instruction against live comparables instead of last quarter's feel

#### 3. Agency lead generation

**Build the list of brokers who actually carry stock.**

**Input:** a city section, then Listing Detail on the rows that matter
**Output:** `agencyName` on every detail row, alongside the advert it belongs to
**Use:** rank agencies by how many live adverts they hold, and approach the ones with volume

#### 4. Diaspora and relocation portals

**Fill a Morocco or Tunisia property search with live inventory that maps itself.**

**Input:** the cities your users search
**Output:** rows carrying real latitude and longitude from the advert's own map
**Use:** drop listings onto a map with no geocoding step and no address-matching guesswork

#### 5. Developers and land buyers

**Watch plots enter the market at a given size and price.**

**Input:** `propertyType: land`, a city, and a surface bound
**Output:** every terrain advert with its surface, price and neighbourhood
**Use:** spot land coming to market before it reaches a broker's shortlist

#### 6. Holiday-let and short-stay operators

**Read the seasonal section Mubawab keeps apart from long rentals.**

**Input:** `transaction: vacation` on apartments or villas
**Output:** 967 holiday apartments and 149 holiday villas in Morocco, priced on the nightly market
**Use:** benchmark a coastal let against the stock that is genuinely competing with it

#### 7. Investment and proptech research

**Assemble a two-country panel with one field vocabulary.**

**Input:** both markets, the sections you care about, scheduled
**Output:** ~79,000 live adverts with identical field names across Morocco and Tunisia
**Use:** compare the two markets directly instead of normalising two different data shapes

***

### 🔗 Integration Examples

#### JavaScript/Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });

const run = await client.actor('sian.agency/mubawab-property-scraper').call({
  operation: 'search',
  market: 'ma',
  propertyType: 'apartment',
  transaction: 'sale',
  city: 'casablanca',
  maxResults: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')

run = client.actor('sian.agency/mubawab-property-scraper').call(
    run_input={
        'operation': 'search',
        'market': 'tn',
        'propertyType': 'villa',
        'transaction': 'sale',
        'city': 'hammamet',
        'maxResults': 100,
    }
)

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item['titleText'], item['price'], item['currency'])
```

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~mubawab-property-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"operation":"search","market":"ma","propertyType":"riad","transaction":"sale","city":"marrakech","maxResults":50}'
```

#### Automation Workflows (N8N / Zapier / Make)

1. **Trigger**: a daily schedule, or a webhook from your own system
2. **HTTP Request**: call the actor's run endpoint with your input
3. **Process**: filter the returned rows on price, neighbourhood or agency
4. **Action**: append to a sheet, upsert to a database, or alert your team on new stock

***

### 📊 Performance & Pricing

#### FREE Tier (Try It Now)

- **25 rows** per run, with every field and both operations
- No credit card required
- Enough to see what a Casablanca or Tunis sweep actually returns

#### PAID Tier (Production Ready)

- **Unlimited** rows per run
- Pay per row returned — a failed advert and a filtered-out one both cost nothing
- A run start fee and a per-row price, both shown live on the Store page

💰 **Priced against a two-country record.** The row carries surface, bedrooms, bathrooms, neighbourhood, amenities and the advert excerpt. The detail row adds coordinates and the agency. That is a fuller record than a title-and-price scrape, at roughly the same money.

🔗 [View current pricing](https://apify.com/sian.agency/mubawab-property-scraper?fpr=sian)

***

### ❓ Frequently Asked Questions

**Q: What does the actor return per listing?**
A: Search returns one row per advert card: price and currency, the price exactly as the portal prints it, surface in m², bedroom and bathroom counts, neighbourhood and city, amenities, the advert excerpt, the photos and the URL. Detail opens the advert's own page and adds GPS coordinates, the numeric price from the portal's structured data, total room count, the agency, the attribute sheet and the complete text.

**Q: Does one actor really cover both Morocco and Tunisia?**
A: Yes, because Mubawab is one application. The two hosts serve identical code and share one listing-id space — ask the Tunisian host for a Moroccan advert id and it redirects you to the Moroccan page. Buying two scrapers would buy you the same parser twice.

**Q: Is Algeria covered?**
A: No, and not by anyone else either. mubawab.dz does not resolve: its nameservers refuse the query on both Cloudflare and Google DNS, and there is no address record. Mubawab operates in Morocco and Tunisia.

**Q: Why is price sometimes empty?**
A: Because the advert says "Prix à consulter" — price on request. That is common on high-end villas and new-build projects. The row keeps the portal's own wording in `priceLabel` and leaves `price` null rather than inventing a number. Set a price filter and those adverts drop out.

**Q: Why do the price filters not show up in the Mubawab URL?**
A: The portal does not put them there. It applies price, bedroom and surface filters through an internal request instead of a link you can bookmark, so the run reads the result pages and keeps only what matches your bounds. Filtering happens before billing.

**Q: How deep can a search go?**
A: As deep as the section does. A Moroccan apartments-for-sale run has more than 15,000 adverts behind it and pagination runs to the last page. `maxResults` exists so you can cap your own spend, not because the portal stops.

**Q: Why does the same advert appear on the first two pages?**
A: Mubawab pins promoted adverts to the top of every result page. Those rows carry `isPromoted: true`, and repeats are dropped before counting, so you are never charged twice for one advert.

**Q: What output formats are available?**
A: JSON, CSV and Excel, exported from the dataset or read straight from the API.

***

### 🐛 Troubleshooting

**The run says Mubawab publishes no page for my city**

- Write the city as Mubawab writes it, accents included: `fès`, `salé`, `kénitra`, `tétouan`, `béni-mellal`. Stripping the accent gives a 404, not a redirect.
- If you are not sure of the spelling, leave City empty and search the whole country.

**The run says there is no section for my property type and transaction**

- Riads are sale-only and Moroccan. Holiday lets exist for apartments and villas only. The message lists the pairings that section supports.

**My filters returned nothing**

- Widen the bounds. Remember that adverts marked "Prix à consulter" carry no number and are excluded whenever a price bound is set.

**A detail row came back as an error**

- The advert was sold, rented or withdrawn. Run a Listing Search over the same neighbourhood to pick up what replaced it. You are not charged for a failed row.

**A run says the portal is temporarily unavailable**

- It already retried five times. Run the same input again in a few minutes.

***

### ⚖️ Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the **GDPR** in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

Mubawab is a trademark of its owner. This actor is not affiliated with, endorsed by or sponsored by Mubawab, and reads only pages that are already public.

***

### 🤝 Support

**Join our active support community**

- For issues or questions, open an issue on the actor's page
- Check the [SIÁN Agency Store](https://apify.com/sian.agency?fpr=sian) for more automation tools
- 📧 <apify@sian-agency.online>

***

**Built by [SIÁN Agency](https://www.sian-agency.online)** | **[More Tools](https://apify.com/sian.agency?fpr=sian)**

# Actor input Schema

## `operation` (type: `string`):

One per run. Listing Search walks Mubawab's result pages and returns a full record per listing card. Listing Detail opens the listings you list under Listing URLs and adds GPS coordinates, the numeric price, the agency and the complete advert text.

## `market` (type: `string`):

Which Mubawab market to search. Morocco prices in MAD (dirham), Tunisia in TND (dinar). Riads are a Moroccan section only. Applies to Listing Search — Listing Detail follows whatever each URL points at.

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

Mubawab's own section. Not every type exists in every transaction: riads are sale-only and a Moroccan format, and holiday lets exist only for apartments and villas. The run stops with the valid combinations listed rather than returning an unrelated section.

## `transaction` (type: `string`):

Sale reads the à-vendre section, rent the à-louer section, and holiday let the seasonal section Mubawab keeps separate from long rentals. Holiday lets exist for apartments and villas only.

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

A city as Mubawab writes it, accents and all: `casablanca`, `marrakech`, `tanger`, `rabat`, `fès`, `salé`, `kénitra`, `tétouan`, `agadir`, `temara`, `el-jadida`, `oujda`, `nador`, `essaouira`, `dakhla` in Morocco; `tunis`, `sousse`, `sfax`, `ariana`, `hammamet`, `djerba`, `nabeul`, `la-marsa`, `carthage` in Tunisia. Plain names are lower-cased and hyphenated for you (El Jadida → el-jadida) but accents are kept, because the portal keeps them. Leave it empty to search the whole country.

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

Keep only listings at or above this asking price (sales) or monthly rent (long rentals), in the market's own currency — MAD for Morocco, TND for Tunisia. Listings whose advert says "price on request" carry no number and are dropped when either price bound is set. Applied before you are charged, so filtered-out listings cost nothing.

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

Keep only listings at or below this asking price or monthly rent, in MAD or TND. Leave both price fields empty to keep every listing including the "price on request" ones.

## `minRooms` (type: `integer`):

Keep only listings advertising at least this many bedrooms (chambres). Land and some commercial listings publish no bedroom count and are dropped when this is set.

## `minAreaSqm` (type: `integer`):

Keep only listings advertising at least this many square metres. Listings with no surface on the card are dropped when this is set.

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

Stop after this many listings (search) or this many detail rows. One row per listing; listings repeated across pages — Mubawab pins its promoted adverts to every page — are skipped before the count.

## `listingUrls` (type: `array`):

For Listing Detail: Mubawab listing URLs, one object per row, e.g. {"url": "https://www.mubawab.ma/fr/a/8115280/appartement-neuf-83-m2-a-gueliz"}. Either market works and either host resolves any listing id. FREE runs read up to 5.

## Actor input object example

```json
{
  "operation": "search",
  "market": "ma",
  "propertyType": "apartment",
  "transaction": "sale",
  "city": "casablanca",
  "maxResults": 100,
  "listingUrls": []
}
```

# Actor output Schema

## `mubawabMaListings` (type: `string`):

Every listing this run returned.

## `scrapingSummary` (type: `string`):

HTML summary showing successful and failed results with key metrics

# 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 = {
    "operation": "search",
    "market": "ma",
    "propertyType": "apartment",
    "transaction": "sale",
    "city": "casablanca",
    "maxResults": 100,
    "listingUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/mubawab-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 = {
    "operation": "search",
    "market": "ma",
    "propertyType": "apartment",
    "transaction": "sale",
    "city": "casablanca",
    "maxResults": 100,
    "listingUrls": [],
}

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/mubawab-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 '{
  "operation": "search",
  "market": "ma",
  "propertyType": "apartment",
  "transaction": "sale",
  "city": "casablanca",
  "maxResults": 100,
  "listingUrls": []
}' |
apify call sian.agency/mubawab-property-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sian.agency/mubawab-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/D7Q9bcVjee4MpN7Jh/builds/QZg7yCzSihewUha0M/openapi.json
