Immoweb.be [Only $1.2π°] Scraper
Pricing
from $1.20 / 1,000 results
Immoweb.be [Only $1.2π°] Scraper
π°$1.2/1K Scrape real estate listings from Immoweb.be effortlessly. This actor extracts properties for sale or rent. You get comprehensive data, including prices, precise addresses, property types, bedrooms, living areas, EPC scores, image URLs and agency contact details. Perfect for market analysis
Pricing
from $1.20 / 1,000 results
Rating
5.0
(2)
Developer
Muhamed Didovic
Maintained by CommunityActor stats
1
Bookmarked
35
Total users
8
Monthly active users
9 days ago
Last modified
Categories
Share
Immoweb.be Scraper

The fastest, cheapest, most accurate Immoweb.be scraper on Apify β $1.20 per 1,000 listings, 50+ items/minute on residential proxies, and exact maxItems compliance with no overshoot. Whether you're monitoring rental markets, tracking sale prices, or building a property database for Flanders, Wallonia, or Brussels, this scraper delivers complete, structured data in JSON or CSV.
"From houses and apartments to office blocks and investment projects, we turn Immoweb's real estate data into your competitive advantage."
Why this scraper
| Feature | This actor | Typical competitor |
|---|---|---|
| Price per 1,000 listings | $1.20 | $1.50β$4.00 |
| Locale support (en / fr / nl / de input URLs) | β auto-normalized | β English only |
Project sub-unit expansion (house_group) | β opt-in | β |
| Stale-listing fast-fail (no 60-retry waste on 404s) | β | β |
Exact maxItems (no over/undershoot) | β atomic cap | β usually overshoots |
| Periodic status heartbeat in logs | β every 10s | β logs go silent on stuck fetches |
| Live per-item dataset push | β | varies |
| Single actor handles both search URLs and direct listings | β | many split into two paid actors |
Project listings (HOUSE_GROUP / APARTMENT_GROUP) | β | rarely supported |
Supported Inputs
The scraper accepts a mix of URLs in startUrls. Any Immoweb locale is fine β French, Dutch, German, or English URLs are auto-normalized internally.
β Supported:
- Search Pages:
https://www.immoweb.be/en/search/house/for-sale?countries=BE&page=1 - French search:
https://www.immoweb.be/fr/recherche/appartement/a-louer?countries=BE&maxPrice=700 - Dutch search:
https://www.immoweb.be/nl/zoeken/huis/te-koop?countries=BE&minPrice=300000 - Filtered Searches:
https://www.immoweb.be/en/search-3-rooms/house/for-rent/bruxelles/district - Direct Listings:
https://www.immoweb.be/en/classified/office-block/for-rent/houthalen-helchteren/3530/21064580 - Project Listings:
https://www.immoweb.be/en/classified/house_group/for-sale/poperinge/8970/21513540
β Not Supported:
- User account dashboards or saved favorites (
/my-immoweb/) - URLs outside the
immoweb.bedomain
Quick Start
- Open the actor on Apify, paste one or more URLs into
startUrls, setmaxItems, click Run. - Wait. Items stream into the dataset live β you don't have to wait until the run finishes to start downloading.
- Export as JSON, CSV, Excel, HTML, or RSS.
Input Configuration
{"startUrls": ["https://www.immoweb.be/fr/recherche/appartement/a-louer?countries=BE&maxPrice=700&postalCodes=1000,1050,1180","https://www.immoweb.be/en/classified/house_group/for-sale/poperinge/8970/21513540"],"maxItems": 100,"locale": "fr","expandProjectUnits": true,"maxConcurrency": 10,"maxRequestRetries": 60,"proxy": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"]}}
Notable input fields
locale(en/fr/nl/de, defaulten) β language forSEOUrlin each output record. Input URLs in any locale are accepted regardless.expandProjectUnits(boolean, defaultfalse) β when a project listing (HOUSE_GROUP/APARTMENT_GROUP) is scraped, also export each of its sub-units as separate dataset records. Sub-units count towardmaxItems.maxItemsβ strict cap. The scraper exits exactly at this count, never one over. Tested at 1, 5, 10, 15, 30, 33, 75, 90, 100, 120 β 0 overshoot across all values.maxConcurrency(default10) β how many listings to fetch in parallel.maxRequestRetries(default100) β per-request retry budget. Stale404 CLASSIFIED_NOT_FOUNDresponses skip immediately instead of consuming the budget.
Sample Output
{"id": 21064580,"url": "https://www.immoweb.be/en/classified/office-block/for-rent/houthalen-helchteren/3530/21064580","original_request_url": "https://www.immoweb.be/en/classified/office-block/for-rent/houthalen-helchteren/3530/21064580","SEOUrl": "https://www.immoweb.be/en/ad/office-block/for-rent/houthalen-helchteren/3530/21064580","customers": [{"id": 1248059,"type": "AGENCY","email": "info@agency.be","phoneNumber": "+3211800000","name": "Vestio","website": "http://www.vestio.com","location": {"country": "Belgium","province": "Limburg","locality": "Hasselt","postalCode": "3500","street": "20 Kolonel Dusartplein"},"ipiNo": "206808","isOwner": true}],"media_pictures": [{ "smallUrl": "...", "largeUrl": "...", "extralargeUrl": "..." }],"property_type": "OFFICE","property_subtype": "OFFICE_BLOCK","property_title": "Flexibele kantoorruimtes in bedrijvencentrum","property_location_country": "Belgium","property_location_region": "Flanders","property_location_locality": "Houthalen-Helchteren","property_location_postalCode": "3530","property_location_latitude": 51.0256269,"property_location_longitude": 5.3723637,"property_hasLift": true,"transaction_type": "FOR_RENT","price_mainValue": 34,"publication_creationDate": "2025-10-03T10:04:27.998Z","publication_lastModificationDate": "2026-04-13T18:38:28.747Z"}
Each record has 60β120+ flattened fields depending on the listing type. Nested objects are flattened with _ separators so they fit cleanly into CSV / Excel columns.
Performance
Measured locally on Apify residential proxies, maxConcurrency=10, broad Belgian house search:
| maxItems | Wall time | Items / minute |
|---|---|---|
| 5 | 17 s | 18 |
| 30 | 21 s | 86 |
| 75 | 72 s | 63 |
| 100 | 94 s | 64 |
| 120 | 81 s | 89 |
A specific French rental URL with 73 unique listings: 73 items in 94 seconds (47 items/min) end-to-end including pagination, mobile-API fetches, and dataset export.
Output Fields Reference
This section provides a detailed breakdown of all key fields. The output is flattened so nested objects fit cleanly into CSV/Excel columns.
Core Listing Details
id(Number): Internal Immoweb listing ID.url(String): The direct URL to the listing.original_request_url(String): The URL the user supplied (or the search page where this listing was discovered).SEOUrl(String): Canonical localized URL (language controlled by thelocaleinput field).
Agency / Customer Details
customers(Array): Real estate agency or seller details.type(String): Usually"AGENCY".email,phoneNumber,name,websiteβ direct contact info.location(Object): Agency address (country, province, locality, postalCode, street).ipiNo(String): Belgian BIV/IPI license number.isOwner(Boolean): Whether the agency owns the listing directly.
Media
media_pictures(Array): Image URLs atsmallUrl,mediumUrl,largeUrl,extralargeUrlresolutions.media_virtualTourUrl(String|null),media_floorPlans(Array|null),media_documents(Array).
Property
property_type,property_subtypeβ e.g.HOUSE/HOUSE_GROUP,APARTMENT/FLAT_STUDIO,OFFICE/OFFICE_BLOCK.property_title,property_description.property_bedroomCount,property_bathroomCount,property_roomCount.property_netHabitableSurface(mΒ²).property_monthlyCosts.
Location
property_location_country,property_location_region,property_location_province,property_location_district,property_location_locality,property_location_postalCode,property_location_street,property_location_number.property_location_latitude,property_location_longitude(GPS).
Building & Construction
property_building_condition(e.g.GOOD,AS_NEW,TO_RENOVATE).property_building_constructionYear,property_building_facadeCount,property_building_floorCount.property_hasLift,property_constructionPermit_isObtained.
Features
property_hasGarden,property_gardenSurface.property_hasTerrace,property_terraceSurface.property_hasSwimmingPool,property_hasAirConditioning.property_kitchen_type(e.g.HYPER_EQUIPPED,INSTALLED).property_parkingCountIndoor,property_parkingCountOutdoor.
Energy / EPC
property_energy_epcScore(A,B, ...G).property_energy_heatingType(GAS,ELECTRIC,PELLET, ...).property_energy_primaryEnergyConsumptionPerSqm(kWh/mΒ²/year).
Transaction & Pricing
transaction_type(FOR_SALE,FOR_RENT),transaction_subtype.price_mainValue(β¬),price_type.flags_isNewlyBuilt,flags_isPublicSale,flags_isUnderOption.
Publication & Statistics
publication_creationDate,publication_lastModificationDate(ISO 8601).statistics_viewCount,statistics_bookmarkCount.
Project-Specific (when property_type is HOUSE_GROUP or APARTMENT_GROUP)
cluster_projectInfo_groupId,cluster_projectInfo_name,cluster_projectInfo_totalHousingUnitsCount.cluster_priceRange_min,cluster_priceRange_max.cluster_surfaceRange_min,cluster_surfaceRange_max.cluster_bedroomCountRange_min,cluster_bedroomCountRange_max.cluster_units(Array): each unit type group with its individual sub-units (each has its ownid).- Use
expandProjectUnits: trueto also export each sub-unit as a separate record.
FAQ
How does this avoid getting blocked? The scraper fetches data through Immoweb's own structured JSON endpoints rather than scraping HTML pages. The success rate on the first attempt is high; a small retry loop with proxy rotation handles transient failures. The HTML page is used only as a fallback when the JSON endpoint returns unexpected data.
What does the flattened output look like?
Nested properties like property: { location: { street: "Main St" } } are flattened into single-level keys: property_location_street: "Main St". Arrays (like media_pictures) remain as lists.
Can I mix search URLs and direct listings?
Yes β put any combination into startUrls. The scraper detects each URL type automatically. You can also mix locales: a French search URL alongside an English direct listing works fine.
What is expandProjectUnits?
Immoweb's "house_group" or "apartment_group" entries represent new-build developments. By default the scraper exports one record per project (with a cluster_units array containing the sub-unit IDs). When expandProjectUnits is true, the scraper also fetches each sub-unit individually and exports it as its own record. Useful when you want every house in a development as a separate row.
Does maxItems actually stop exactly at the cap?
Yes. The cap reservation is atomic (single-threaded JS), so concurrent in-flight fetches can't push past the limit. Tested at 1, 5, 10, 15, 30, 33, 75, 90, 100, 120 β zero overshoot. Several competing actors silently overshoot by up to maxConcurrency-1 items per run.
What happens to listings that have been removed?
A 404 CLASSIFIED_NOT_FOUND response triggers an immediate skip (single log line, no retries). This is especially important for project sub-units, which can go stale faster than regular listings. Competing actors typically retry 60 times per stale ID, burning proxy budget and run time.
The run looks stuck β how do I tell?
Status heartbeat lines fire every 10 seconds regardless of what's happening: [internal-handler-impit] status queue=N (listing=X search=Y) active=Z queuedListings=Q exported=E/maxItems. If active is non-zero and exported is incrementing, the run is healthy. If you see no change across multiple heartbeats, a fetch is wedged β wait or abort.
Why am I still getting blocked?
For high-volume scraping use Apify's Residential Proxies (apifyProxyGroups: ["RESIDENTIAL"]). Datacenter proxies are flagged by Belgian real estate sites.
Integrations & Webhooks
The actor stores results in the default dataset, accessible via:
- Direct download: JSON, CSV, Excel, HTML, RSS from the Apify Console.
- Apify API: programmatic access to the dataset.
- Built-in webhooks (Apify platform): configure in Apify Console β Actor β Integrations β Webhooks. Apify will POST to your URL on
ACTOR.RUN.SUCCEEDED,ACTOR.RUN.FAILED, orACTOR.RUN.ABORTEDwith run metadata (run ID, dataset ID). Your endpoint can then fetch the dataset. - Custom completion webhook (this actor): set
completionWebhookUrlin input β see below. - Pre-built integrations: Google Sheets, Slack, Email, Zapier, Make, Airtable.
Custom completion webhook (completionWebhookUrl)
If you set the completionWebhookUrl input field, the actor POSTs a rich JSON payload to that URL when the run finishes (success or failure). Compared to Apify's built-in webhooks this payload includes the item count, a property-type breakdown, a sample record, and a sanitized echo of your input β so you can decide whether to fetch the full dataset without a second round-trip.
Retries: up to 3 attempts with 1s/3s backoff. Timeout: 15s per attempt. All webhook errors are logged and swallowed β they cannot fail or stall the actor run.
Example payload:
{"status": "SUCCEEDED","actorRunId": "UgKgANdBaGOHiy29J","actorId": "7hrExNTiDRs0nPUXh","userId": "ngn8vRESTkseyWE6p","defaultDatasetId": "...","startedAt": "2026-05-27T20:50:11.000Z","finishedAt": "2026-05-27T20:51:45.000Z","durationSeconds": 94,"itemCount": 100,"breakdown": {"byPropertyType": { "APARTMENT": 97, "APARTMENT_GROUP": 3 },"byTransactionType": { "FOR_SALE": 100 }},"sample": {"id": 21597303,"SEOUrl": "https://www.immoweb.be/fr/annonce/rez-de-chaussee/a-vendre/braine-le-comte/7090/21597303","property_type": "APARTMENT","price_mainValue": 285000,"...": "(full first record, ~90 fields)"},"inputSummary": {"startUrls": ["https://www.immoweb.be/en/search/apartment/for-sale?countries=BE&orderBy=newest"],"maxItems": 100,"locale": "fr","expandProjectUnits": false}}
On failure, status is "FAILED" and an "error" field contains the message. itemCount and breakdown reflect whatever was exported before the failure β so partial runs are still useful to your downstream system.
Receivers that work out of the box:
- Make / Zapier / n8n webhook triggers
- Slack incoming webhook (pipe
breakdown.byPropertyTypeinto a chat message) - Your own service (
itemCountβ decide whether to pull the dataset)
Explore More Scrapers
If you found this scraper useful, check out the rest at memo23's Apify profile. We build scrapers for a wide range of platforms.
Support
- For issues or feature requests, use the Issues section of this actor.
- For customizations or questions: muhamed.didovic@gmail.com
- Author's website: https://muhamed-didovic.github.io/
Additional Services
- Custom dataset requests or actor customization: muhamed.didovic@gmail.com
- Dedicated API services (no Apify fee, usage-based pricing only): muhamed.didovic@gmail.com