# Immoweb Scraper - Belgium Real Estate & Agency Leads (`scrapesage/immoweb-scraper`) Actor

Scrape Immoweb.be, Belgium's #1 real estate portal: houses & apartments for sale and rent with prices, EPC energy score, full specs, all photos, geo and agency leads (email, phone & website). Filter by postal code, province, price & type. Monitor new listings. Export JSON, CSV.

- **URL**: https://apify.com/scrapesage/immoweb-scraper.md
- **Developed by:** [Scrape Sage](https://apify.com/scrapesage) (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 $4.00 / 1,000 listing scrapeds

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/platform/actors/running/actors-in-store#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

## Immoweb Scraper — Belgium Real Estate, Prices & Agency Leads

Extract **complete real estate data from [Immoweb](https://www.immoweb.be)** — Belgium's #1 property portal. Scrape **houses and apartments for sale and for rent** with the fields other scrapers miss: **EPC energy score and consumption, cadastral income, construction year & condition, every amenity, full floor plans, view & bookmark counts** — plus the **agency's direct email, phone and website** on every listing.

No login, no cookies, no browser — fast extraction straight from Immoweb's own keyless JSON API.

### Why this Immoweb scraper?

Most Immoweb scrapers return a thin slice of the search card and stop there. This actor reads Immoweb's internal search API **and** the full classified detail object, and ships the **richest dataset in the category** — every spec, the energy certificate, and the agency contact details nobody else extracts.

| Data | Typical scrapers | This actor |
|---|---|---|
| Price + old price (price drops), €/m² | partial | ✅ |
| Full address (street, number, box, postal code) + geo | partial | ✅ |
| Bedrooms, bathrooms, surface, land, room count | partial | ✅ |
| **EPC energy score** + consumption + carbon emission | ❌ | ✅ |
| **Cadastral income**, monthly costs, VAT, furnished | ❌ | ✅ |
| Construction year, building condition, facades, floors | ❌ | ✅ |
| Every amenity — garden, terrace, parking, lift, pool, AC… | ❌ | ✅ |
| Full photo gallery + floor plans + virtual tour/video | partial | ✅ |
| View count + bookmark count (demand signal) | ❌ | ✅ |
| For sale **and** for rent, all property types | partial | ✅ |
| Agency **direct email + phone + website** | ❌ | ✅ opt-in |
| Deduplicated **agency leads** with 0–100 lead score | ❌ | ✅ opt-in |
| New-listing / price-drop **monitoring** | ❌ | ✅ |

### Use cases

- **Lead generation** — every listing carries an estate agency. Export deduplicated agencies with **direct email, phone, mobile and website**, active-listing count, areas and price range, scored 0–100 — perfect for proptech, mortgage, insurance, moving, photography, staging and SaaS sales teams.
- **Market & price intelligence** — track asking prices, €/m², EPC ratings, days-on-market signals (view/bookmark counts) and inventory across Brussels, Antwerp, Ghent, Liège and every Belgian postal code.
- **Property valuation & comps** — pull full attributes, cadastral income and energy data for any area to power AVMs, CMAs and investor underwriting.
- **Relocation & investment research** — feed apps and dashboards with structured listings + geo for international buyers, expats and relocation services.
- **Monitoring & alerts** — schedule recurring runs to capture only **new listings and price drops** in a saved search.

### How to use

1. [Sign up for Apify](https://console.apify.com/sign-up) — the free plan is enough to try this actor.
2. Open the **Immoweb Scraper**, enter Belgian postal codes or provinces (or paste Immoweb URLs), choose **For sale / For rent**, and click **Start**.
3. Watch results stream into the dataset table.
4. **Export** as JSON, CSV, Excel, XML, or RSS — or pull results programmatically via the [Apify API](https://docs.apify.com/api/v2).

### Input

```json
{
    "transactionType": "for-sale",
    "propertyType": "house-and-apartment",
    "postalCodes": ["1000", "2000"],
    "priceMax": 600000,
    "minBedrooms": 2,
    "includeListingDetails": true,
    "outputAgencyLeads": true,
    "maxResults": 500,
    "monitorMode": false
}
```

- **transactionType** *(default `for-sale`)* — `for-sale` or `for-rent`.
- **propertyType** *(default `house-and-apartment`)* — `house`, `apartment`, `new-real-estate`, `land`, `office`, and more.
- **postalCodes** — Belgian postal codes (`1000` Brussels, `2000` Antwerp, `9000` Ghent, `4000` Liège). **provinces** — search whole provinces instead.
- **startUrls** — paste any Immoweb URL: a search page (`/en/search/house/for-sale/...`) or a listing (`/en/classified/...`). The easiest way to scrape an exact search — build it on immoweb.be with the filters you want, then paste the URL.
- **listingUrls** — direct `/classified/` URLs to fetch full detail for.
- **priceMin / priceMax / minBedrooms / maxBedrooms / minSurface / maxSurface / orderBy** — filters.
- **includeListingDetails** *(default false)* — open each listing for the full description, every spec (EPC energy score, cadastral income, construction year, condition, heating, kitchen, all amenities), the complete gallery & floor plans, view/bookmark counts, **and the agency's direct email, phone & website**.
- **outputAgencyLeads** *(default false)* — also output one deduplicated lead record per agency. Implies full listing details.
- **maxResults / maxAgencyLeads / maxPagesPerSearch** — caps.
- **monitorMode** *(default false)* + **monitorKey** — emit only what's new since the last run.

### Output

One record per listing (`type: "listing"`), plus optional agency leads (`type: "agencyLead"`). A listing with details enabled:

```json
{
    "type": "listing",
    "listingId": "21648089",
    "url": "https://www.immoweb.be/en/classified/apartment/for-sale/woluwe-saint-lambert/1200/21648089",
    "transactionType": "for-sale",
    "propertyType": "APARTMENT",
    "propertySubtype": "GROUND_FLOOR",
    "title": "Ground-floor 3-bed with private garden",
    "price": 549000,
    "oldPrice": null,
    "currency": "EUR",
    "cadastralIncome": 2307,
    "monthlyCosts": 300,
    "bedroomCount": 3,
    "bathroomCount": 2,
    "netHabitableSurface": 121,
    "constructionYear": 2015,
    "buildingCondition": "AS_NEW",
    "epcScore": "B",
    "primaryEnergyConsumptionPerSqm": 77,
    "carbonEmission": 15,
    "heatingType": "GAS",
    "kitchenType": "HYPER_EQUIPPED",
    "hasTerrace": true,
    "hasGarden": true,
    "locality": "Woluwe-Saint-Lambert",
    "postalCode": "1200",
    "street": "Rue Vervloesem",
    "streetNumber": "152",
    "latitude": 50.848324,
    "longitude": 4.4295851,
    "viewCount": 2309,
    "bookmarkCount": 77,
    "imageCount": 26,
    "images": ["https://media-resize.immowebstatic.be/.../736x736/....jpg"],
    "agencyName": "ABITA IMMO",
    "agencyEmail": "immoabita_woluwe@...",
    "agencyPhone": "+3227268975",
    "agencyWebsite": "http://www.immoabita.be",
    "scrapedAt": "2026-06-19T03:00:00.000Z"
}
```

An **agency lead** (`type: "agencyLead"`) carries `agencyName`, `agencyEmail`, `agencyPhone`, `agencyMobile`, `agencyWebsite`, `agencyAddress`, `activeListingCount`, `localities`, `propertyTypes`, `minPrice`/`maxPrice`, `sampleListings` and a `leadScore`.

#### What to expect (field coverage)

Immoweb is agency-entered data, so a few fields appear only when the agency filled them in. Verified across areas, you can typically expect:

| Entity | Always present | Usually present | Present when published |
|---|---|---|---|
| **Listing** | id, url, transaction, type, price, locality, postal code, geo, agency name | bedrooms, surface, images ~98%, street ~90% | EPC, cadastral income, construction year, amenities (with details on) |
| **Agency lead** | name, active-listing count | **phone & website** ~90%, email ~85% | mobile, full address |

A blank field means it wasn't published for that listing — never that scraping failed. Nothing is dropped, so you always get the richest dataset available.

### Automate & schedule

Run this actor on autopilot and pull results into your own stack:

- **[Apify API](https://docs.apify.com/api/v2)** — start runs, fetch datasets, and manage schedules over REST.
- **[apify-client for JavaScript](https://docs.apify.com/api/client/js/)** and **[apify-client for Python](https://docs.apify.com/api/client/python/)** — official SDKs.
- **[Schedules](https://docs.apify.com/platform/schedules)** — run it hourly/daily to monitor new listings and price drops in an area; perfect for alerts and lead pipelines.
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** — trigger downstream actions (CRM import, Slack alert, valuation model) the moment a run finishes.

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

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });

const run = await client.actor('scrapesage/immoweb-scraper').call({
    transactionType: 'for-sale',
    postalCodes: ['1000', '2000'],
    includeListingDetails: true,
    outputAgencyLeads: true,
    maxResults: 500,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} listings & agency leads`);
```

### Integrate with any app

Connect the dataset to 5,000+ apps — no code required:

- **[Make](https://docs.apify.com/platform/integrations/make)** — multi-step automation scenarios.
- **[Zapier](https://docs.apify.com/platform/integrations/zapier)** — push new agency leads straight into your CRM.
- **[Slack](https://docs.apify.com/platform/integrations/slack)** — get notified when a monitored search finds new listings.
- **[Google Drive / Sheets](https://docs.apify.com/platform/integrations/drive)** — auto-export every run to a spreadsheet.
- **[Airbyte](https://docs.apify.com/platform/integrations/airbyte)** — pipe results into your data warehouse.
- **[GitHub](https://docs.apify.com/platform/integrations/github)** — trigger runs from commits or releases.

### Use with AI assistants (MCP)

The output is clean, LLM-ready JSON. Call this actor from Claude, ChatGPT, or any agent framework through the **[Apify MCP server](https://docs.apify.com/platform/integrations/mcp)** — ask your assistant to "find 3-bedroom houses under 600k in Ghent and list the agencies' contact details" and let it run this scraper for you.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** — AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** — an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** — agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### More scrapers from scrapesage

Build a complete **real estate & lead-gen stack** across markets:

- **[Rightmove Scraper](https://apify.com/scrapesage/rightmove-scraper)** — UK's #1 property portal: listings, prices & agents.
- **[Redfin Scraper](https://apify.com/scrapesage/redfin-scraper)** — US homes for sale with prices, specs & history.
- **[Realtor.ca Scraper](https://apify.com/scrapesage/realtor-ca-scraper)** — Canada real estate listings & agent leads.
- **[Crexi Scraper](https://apify.com/scrapesage/crexi-scraper)** — US commercial real estate & broker leads.
- **[Rent.com Scraper](https://apify.com/scrapesage/rent-com-scraper)** — US rentals with property-management leads.
- **[Property Finder Scraper](https://apify.com/scrapesage/property-finder-scraper)** — UAE / GCC real estate & agent contacts.
- **[Kleinanzeigen Scraper](https://apify.com/scrapesage/kleinanzeigen-scraper)** — Germany's #1 classifieds incl. property & seller leads.
- **[Gumtree Scraper](https://apify.com/scrapesage/gumtree-scraper)** — UK classifieds incl. property & seller leads.

### Tips

- **Agency leads** — turn on `outputAgencyLeads` to get one deduplicated, scored lead per agency with direct email, phone and website. It opens one page per listing, so it's richer but a bit slower.
- **EPC & energy** — every detailed record carries the energy score, consumption and carbon emission — increasingly required for Belgian property analysis and renovation targeting.
- **Exact searches** — build the search on immoweb.be with all the filters you want and paste the URL into `startUrls`; the actor reads its JSON API and paginates it.
- **Big regions**: search is paged 30 listings at a time. To exhaust a large area, split by postal code or province and/or narrow with price and type filters.
- **Recurring monitoring**: combine [Schedules](https://docs.apify.com/platform/schedules) with `monitorMode` to capture only new listings and price drops.

### FAQ

**How do I scrape Immoweb for a specific city?** Put its Belgian postal codes in `postalCodes` (`1000` Brussels, `2000` Antwerp, `9000` Ghent), or pick `provinces`. You can also paste a ready-made search URL into `startUrls`.

**Can I scrape rentals?** Yes — set `transactionType` to `for-rent`. The `price` field is then the monthly rent.

**Does it work without the Immoweb API key?** Yes. This actor reads Immoweb's own public search API and listing pages — no key or login needed.

**Where do the agency emails and phones come from?** From each listing's own public agency section on Immoweb, where the listing agency publishes its contact details. Turn on `includeListingDetails` or `outputAgencyLeads` to capture them.

**Can I export to Google Sheets, CSV, or Excel?** Yes — one click in the dataset view, or automatically on every run via the [Google Drive integration](https://docs.apify.com/platform/integrations/drive).

**How do I monitor new listings or price drops automatically?** Turn on `monitorMode`, give the search a `monitorKey`, and create a [Schedule](https://docs.apify.com/platform/schedules). Each run emits only new listings and price changes — then optionally push them to your CRM via [webhook](https://docs.apify.com/platform/integrations/webhooks) or [Zapier](https://docs.apify.com/platform/integrations/zapier).

**A field is empty — why?** Some listings don't publish an EPC score, cadastral income, photos or every amenity. Fields are blank only when the agency didn't publish that data — never because the scraper skipped it.

**Is scraping Immoweb legal?** This actor collects publicly available data only. You're responsible for using the data in compliance with applicable laws (GDPR for personal data such as agency contacts) and Immoweb's terms.

### Need help?

Open an issue on the actor's **Issues** tab, or visit the [Apify help center](https://help.apify.com/). Feature requests are welcome — this actor is actively maintained.

# Actor input Schema

## `transactionType` (type: `string`):

Scrape properties <b>for sale</b> or <b>for rent</b>.

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

Which kind of property to scrape. <code>house-and-apartment</code> covers both (the default).

## `postalCodes` (type: `array`):

Belgian postal codes to search, e.g. <code>1000</code> (Brussels), <code>2000</code> (Antwerp), <code>9000</code> (Ghent), <code>4000</code> (Liège). Leave empty to search all of Belgium (or use provinces / Start URLs).

## `provinces` (type: `array`):

Belgian provinces to search instead of, or in addition to, postal codes.

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

Paste any Immoweb URL — a search page (<code>https://www.immoweb.be/en/search/house/for-sale/...</code>) or a listing (<code>https://www.immoweb.be/en/classified/...</code>). The easiest way to scrape an exact search: build it on immoweb.be with the filters you want, then paste the URL. Used in addition to postal codes / provinces.

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

Direct Immoweb listing URLs (<code>https://www.immoweb.be/en/classified/...</code>) to scrape full detail (and agency contact) for. Each becomes a full detail record.

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

Only listings at or above this price. For rentals this is the monthly rent.

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

Only listings at or below this price (monthly rent for rentals).

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

Minimum number of bedrooms.

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

Maximum number of bedrooms.

## `minSurface` (type: `integer`):

Minimum net habitable surface in square metres.

## `maxSurface` (type: `integer`):

Maximum net habitable surface in square metres.

## `orderBy` (type: `string`):

How to order results. Newest first is recommended for monitoring.

## `includeListingDetails` (type: `boolean`):

For every listing, open its page and add the full description, every spec (construction year, building condition, EPC energy score & consumption, heating, kitchen, all amenities — garden/terrace/parking/pool/lift…), cadastral income, monthly costs, complete photo gallery & floor plans, view & bookmark counts — and the agency's direct <b>email, phone & website</b>. Charged as <code>listingDetail</code>. Slower but far richer.

## `outputAgencyLeads` (type: `boolean`):

Also output one deduplicated lead record (type = "agencyLead") per unique estate agency behind the scraped listings — name, direct <b>email, phone, mobile & website</b>, address, active-listing count, areas, property types, price range, sample listings and a 0–100 lead score. Requires opening listing pages, so this turns on full listing details.

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

Maximum number of listing records to scrape across all searches. Belgium has tens of thousands of listings — use locations, type and price filters to focus.

## `maxAgencyLeads` (type: `integer`):

Maximum number of agency-lead records to emit (when agency leads are on).

## `maxPagesPerSearch` (type: `integer`):

How many result pages (30 listings each) to page through per search.

## `monitorMode` (type: `boolean`):

Remember listings across runs in a named key-value store and emit ONLY what's new since last run — new listings and any with a changed price (flagged <code>priceChangedSinceLastRun</code>). Perfect for new-listing alerts and price-drop watches. Works with Apify Schedules.

## `monitorKey` (type: `string`):

Names the memory used by monitoring mode. Use a distinct key per saved search so different watches don't share state.

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

Proxy settings. Residential proxies (Belgium) are recommended and used by default for the most reliable access.

## Actor input object example

```json
{
  "transactionType": "for-sale",
  "propertyType": "house-and-apartment",
  "postalCodes": [
    "1000"
  ],
  "orderBy": "newest",
  "includeListingDetails": false,
  "outputAgencyLeads": false,
  "maxResults": 100,
  "maxAgencyLeads": 200,
  "maxPagesPerSearch": 100,
  "monitorMode": false,
  "monitorKey": "default",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "BE"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped property-listing and agency-lead records as JSON items in the default dataset.

# 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 = {
    "postalCodes": [
        "1000"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "BE"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/immoweb-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 = {
    "postalCodes": ["1000"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "BE",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/immoweb-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "postalCodes": [
    "1000"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "BE"
  }
}' |
apify call scrapesage/immoweb-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=scrapesage/immoweb-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/EPIUVTpWfzeNqzu8G/builds/GDNedSe6Fp3kaOEVu/openapi.json
