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
(3)
Developer
Muhamed Didovic
Maintained by CommunityActor stats
1
Bookmarked
60
Total users
10
Monthly active users
5 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.proxyCountry(2-letter code, optional) — geo-targets the Apify residential proxy. Immoweb is a Belgium-only site, soBEis the most legitimate, least-throttled choice. Ignored when a customproxyUrlsis supplied.completionWebhookUrl(URL, optional) — POST a rich completion payload (status, item count, property-type breakdown, sample record) when the run finishes. See Integrations & Webhooks.
Sample Output
{"externalReference": "7797745","lastModificationDate": "2026-08-11T07:45:57.460Z","id": 21756742,"SEOUrl": "https://www.immoweb.be/en/ad/house/for-sale/chaumont-gistoux/1325/21756742","media_pictures_baseUrl": "https://media-resize.immowebstatic.be/classifieds/2064ba5e-5ea3-4ac8-9d53-c2d38e32365c/","media_pictures_count": 27,"media_pictures_items": [{"orientation": "LANDSCAPE","relativeUrl": {"small": "100x100/06fb11b80ccebebe602d58ec405a4f0f.jpg","large": "736x736/06fb11b80ccebebe602d58ec405a4f0f.jpg","extralarge": "2560x1440/06fb11b80ccebebe602d58ec405a4f0f.jpg","medium": "300x300/06fb11b80ccebebe602d58ec405a4f0f.jpg"}}],"property_basement_exists": true,"property_parking_parkingSpaceCount_total": 1,"property_parking_parkingSpaceCount_indoor": 1,"property_specificities_SME_office_exists": true,"property_commonEquipment_hasLift": false,"property_commonEquipment_hasSecureAlarm": false,"property_commonEquipment_hasDisabledAccess": false,"property_laundryRoom_exists": true,"property_livingRoom_exists": false,"property_type": "HOUSE","property_privateEquipment_hasDoorPhone": false,"property_privateEquipment_hasVisiophone": false,"property_building_condition": "GOOD","property_building_constructionYear": 1890,"property_building_floorCount": 1,"property_building_facadeCount": 3,"property_bedroom_count": 3,"property_bedroom_items": [{"surface": 17}],"property_livingDescription_netHabitableSurface": 178,"property_outdoor_exists": true,"property_outdoor_garden_surface": 400,"property_outdoor_garden_exists": true,"property_outdoor_terrace_surface": 40,"property_outdoor_terrace_exists": true,"property_wellnessEquipment_hasSwimmingPool": true,"property_certificates_electricalInstallationComplianceCertificate": "YES_CONFORM","property_certificates_hasElectricalInstallationComplianceCertificate": true,"property_certificates_oilTankCertificateStatus": "NO","property_subtype": "HOUSE","property_attic_exists": false,"property_constructionPermit_totalBuildableGroundFloorSurface": 175,"property_constructionPermit_floodZoneType": "NON_FLOOD_ZONE","property_land_surface": 626,"property_land_landWidth": 0,"property_land_hasGasWaterElectricityConnection": true,"property_land_sewerConnection": "NOT_CONNECTED","property_location_address_number": "16","property_location_address_country": "Belgium","property_location_address_province": "Walloon Brabant","property_location_address_street": "Chemin du Fonds des Goffes","property_location_address_postalCode": "1325","property_location_address_district": "Nivelles","property_location_address_locality": "Chaumont-Gistoux Bonlez","property_location_address_region": "Wallonie","property_location_address_placeName": "R BRABANT WALLON","property_location_address_countryCode": "BE","property_location_address_provinceCode": "WALLOON_BRABANT","property_location_address_districtCode": "NIVELLES","property_location_address_regionCode": "WALLONIE","property_location_geoPoint_latitude": 50.6993237,"property_location_geoPoint_longitude": 4.6973104,"property_kitchen_type": "HYPER_EQUIPPED","property_kitchen_isSetup": true,"property_bathroom_count": 1,"property_energy_hasDoubleGlazing": true,"property_energy_heatingType": "FUELOIL","property_energy_hasThermicPanels": false,"property_title": "Provence on Brussels’ doorstep – Swimming pool and garage!","property_alternativeTitles_fr": "VISITES SUSPENDUES - CRENEAUX REMPLIS","property_alternativeTitles_nl": "De Provence aan de poorten van Brussel – Zwembad en garage!","property_description": "Can you really fall in love with a house at first sight? The answer is yes… All that is missing a...","property_alternativeDescriptions_fr": "VISITES COMPLETES Peut-on réellement avoir un coup de cœur un jour ? La réponse est oui… Il ne ma...","property_alternativeDescriptions_nl": "Kun je werkelijk op een dag helemaal verliefd worden op een woning? Het antwoord is ja… Het enige...","flagsAndStatistics_flags_isANewlyPublishedClassified": true,"flagsAndStatistics_flags_isNewlyBuilt": false,"flagsAndStatistics_flags_isUnderOption": false,"flagsAndStatistics_flags_isInvestmentProject": false,"flagsAndStatistics_flags_isAPublicSale": false,"flagsAndStatistics_flags_isALifeAnnuitySale": false,"flagsAndStatistics_flags_isAPropertyWithNewPrice": false,"flagsAndStatistics_statistics_popularity": 0.0382,"flagsAndStatistics_statistics_bookmarkCount": 89,"flagsAndStatistics_statistics_viewCount": 2329,"publication_lastModificationDate": "2026-08-10T14:01:44.879Z","publication_visualisationOption": "XL","publication_activationDate": "2026-08-10T09:02:43.128Z","publication_creationDate": "2026-08-10T09:02:43.128Z","publication_detailedPageVisibility": "CLASSIC","customers": [{"id": 1942392,"type": "AGENCY","location": {"address": {"country": "Belgium","province": "Brussels","street": "Bld. Brand Whitlock 112","postalCode": "1200","district": "Brussels","locality": "Woluwe-Saint-Lambert"},"geoPoint": {"latitude": 50.84281413611313,"longitude": 4.4066328719721755}},"isOwner": true,"contactInfo": [{"usage": "DEFAULT","email": "bathimco_bruxelles@importfrommedia.be","landline": "+3227330000"}],"contactHours": {"mobile": "ANYTIME","landline": "ANYTIME"},"publicInfo": {"ipiNo": "505122","logoUrl": "https://media.immowebstatic.be/customers/0012p00002TxtxwAAB/logo/46b47200ca5bd8dff3fca8508f85106f...","name": "BATHIM RESIDENTIAL"},"features": {"page404": true,"investorFlag": false,"relatedClassifieds": true,"leafletsCTA": false,"leadQualification": true,"recommendation": true}}],"transaction_investor_isInvestmentProperty": false,"transaction_sale_isSubjectToVat": false,"transaction_sale_price": 545000,"transaction_sale_cadastralIncome": 900,"transaction_sale_isFurnished": false,"transaction_certificates_carbonEmission": 73,"transaction_certificates_primaryEnergyConsumption_perSqm": 295,"transaction_certificates_primaryEnergyConsumption_yearlyTheoreticalTotal": 53015,"transaction_certificates_epc_score": "D","transaction_certificates_epc_logoUrl": "https://media.immowebstatic.be/epc/pics/peb/peb_d.png","transaction_subtype": "BUY_REGULAR","transaction_availabilityDate": "2027-02-01","transaction_type": "FOR_SALE","transaction_soldOrRented_isStatusDisplayed": false,"transaction_soldOrRented_isSoldOrRented": false,"url": "https://www.immoweb.be/en/classified/house/for-sale/chaumont-gistoux%20bonlez/1325/21756742","original_request_url": "https://www.immoweb.be/en/search/house/for-sale?countries=BE"}
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 — and set proxyCountry: "BE" so the IP matches the site's country. The scraper also rotates the client's app-version identity across requests so a run doesn't look like thousands of identical calls.
The run exported nothing and mentions a 403 / revoked key — what happened?
Detail records come from Immoweb's mobile API, which is gated by an API key. If that key is rotated by Immoweb, every detail fetch returns 403. The scraper detects this: after a handful of auth failures with zero successful exports it aborts fast with a clear x-api-key appears REVOKED message (and reports FAILED to your completion webhook), instead of silently grinding the whole run to its timeout. If you see this, the actor needs a key refresh.
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
🤖 For AI Agents & LLM Apps
Compact reference for AI agents calling this actor via the Apify MCP server or the Apify API (actor: memo23/immoweb-scraper).
Purpose: Extract Belgian real estate listings from Immoweb.be — one flattened row per property (sale or rent) with price, type, surface, rooms, location, energy/EPC, agency contact and media, from search URLs, filtered searches, direct classifieds or project pages.
Minimal input:
{"startUrls": ["https://www.immoweb.be/en/search/house/for-sale?countries=BE"],"maxItems": 50,"locale": "en","expandProjectUnits": false,"enrichEmails": false,"qualifyByPayment": false,"proxyCountry": "BE","maxConcurrency": 10,"minConcurrency": 1,"maxRequestRetries": 60}
You can mix locales and URL types in startUrls, e.g. a direct classified "https://www.immoweb.be/en/classified/office-block/for-rent/houthalen-helchteren/3530/21064580" or a project page "https://www.immoweb.be/en/classified/house_group/for-sale/poperinge/8970/21513540".
Output: one flattened dataset row per listing (60–120+ fields) — id, url, original_request_url, SEOUrl, property_type, property_subtype, property_title, property_bedroom_count, property_bathroom_count, property_livingDescription_netHabitableSurface, property_location_address {street, postalCode, locality, province, country}, property_location_geoPoint {latitude, longitude}, property_energy_heatingType, transaction_certificates_epc_score, transaction_type, transaction_sale_price, customers {type, contactInfo, publicInfo}, media_pictures_items, flagsAndStatistics_statistics {viewCount, bookmarkCount}, publication_creationDate.
Behaviors an agent should know:
startUrlsaccepts search, filtered-search, direct classified and project URLs in any locale (en/fr/nl/de), mixed in one run; type is auto-detected.- Always set
maxItems(default 1000). The cap is atomic — the run stops exactly at the cap with no overshoot. expandProjectUnits: truealso exports each sub-unit of aHOUSE_GROUP/APARTMENT_GROUPproject as its own row; sub-units count towardmaxItems.proxyCountry: "BE"geo-targets the Apify residential proxy to Belgium (least throttled); output is always flattened with_separators for CSV/Excel.enrichEmails: true(opt-in) addscontactEmail/contactWebsite+emailEnrichment, billed only per email found;qualifyByPayment: truerequires it and adds payment-processor flags at no extra charge. SetcompletionWebhookUrlfor a rich completion POST.- Billing: approximately $1.20 per 1,000 listings — see the Pricing tab on the actor page for the current rate.
⚠️ Disclaimer
This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Immoweb SA or any of its subsidiaries or parent companies. All trademarks mentioned are the property of their respective owners.
The scraper accesses only publicly available Immoweb.be property listing pages — no authenticated endpoints, paid features, or content behind the immoweb.be login wall. Users are responsible for ensuring their use complies with Immoweb.be's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organization.
SEO Keywords
immoweb scraper, scrape immoweb, immoweb.be scraper, immoweb API, Apify immoweb, belgium real estate scraper, property listings scraper, real estate data extraction, belgian property data, house price scraper, rental listings scraper, real estate market research, property lead generation, epc energy data, brussels wallonia flanders property data, real estate data export, property intelligence, immoweb listings API