Funda in Business Scraper - Commercial Property & Agents
Pricing
from $1.00 / 1,000 property scrapeds
Funda in Business Scraper - Commercial Property & Agents
Scrape Funda in Business commercial listings: offices, retail, industrial, catering and more. Full detail pages, pricing, floor areas, energy labels, coordinates, images, and agent/agency contacts with ratings. Dual search and URL modes, deep filters, and forward pagination.
Pricing
from $1.00 / 1,000 property scrapeds
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
5
Total users
2
Monthly active users
7 days ago
Last modified
Categories
Share
Funda in Business Scraper - Commercial Property & Agent Contacts
Extract commercial property listings from Funda in Business (fundainbusiness.nl): offices, retail units, industrial halls, catering venues, practice spaces, plots, and investment objects across the Netherlands. Every listing comes with pricing, floor areas, energy labels, coordinates, full image sets, and the listing agent and agency, including agency ratings and reviews. Search by city and filters, or paste your own listing URLs.
Why this scraper
- Rich nested output: 90+ fields per listing across pricing, location, property characteristics, media, and agency relationships, a strict superset of what other scrapers return.
- Full detail-page enrichment: complete description, every characteristic (transfer, construction, areas, layout, energy), map coordinates, all photos, and the agent phone number.
- Agency profiles with reviews: opt in to enrich each listing's agency with contact details, address, employee count, average rating, and individual reviews.
- Dual input modes: search by location plus deep filters, or scrape a list of URLs you already have.
- Deep filters: property category, buy or rent, price and area ranges, energy label, construction period, surrounding context, features, parking, publication date, auction and open-day windows, and nine sort orders.
- Forward pagination that walks result pages until your item cap is reached.
- Optional export of results into Notion, Linear, Airtable, or Apify through MCP connectors.
- Resume & recurring updates: turn on Incremental mode to get only NEW, UPDATED, and REAPPEARED listings on every scheduled run, or resume one specific interrupted crawl with
resumeFromRunId.
Data you get
Sample shape, values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
record_id | 00000001 |
entity.title | Sample Street 1, Amsterdam |
listing.deal_type | rent |
property.property_type | office |
property.usage_types | ["Office", "Retail"] |
pricing.price | 3250 |
pricing.price_text | EUR 3.250 /mnd |
property.floor_area | 98 |
property.energy_label | A |
property.construction_year | 2020 |
location.city | Amsterdam |
location.latitude | 52.0000 |
location.longitude | 4.0000 |
media.image_count | 6 |
relationships.agency.name | Sample Brokers |
relationships.agency.phone | +310000000000 |
relationships.agency.email | agent@example.com |
relationships.agency.reviews.average_score | 8.6 |
How to use
Search a city for offices for rent, listings only:
{"mode": "search","locations": ["Amsterdam"],"propertyType": "office","dealType": "rent","maxItems": 50,"fetchDetails": false}
Search with filters and full detail enrichment:
{"mode": "search","locations": ["Rotterdam", "Utrecht"],"propertyType": "retail","dealType": "buy","minPrice": 100000,"maxPrice": 2000000,"minArea": 80,"energyLabel": ["a", "b", "c"],"sortBy": "sale_price","fetchDetails": true,"includeAgencyDetails": true,"maxItems": 100}
Scrape from URLs (multiple, paginated):
{"mode": "url","urls": ["https://www.fundainbusiness.nl/kantoor/amsterdam/","https://www.fundainbusiness.nl/winkel/rotterdam/"],"maxPages": 5,"maxItems": 100,"fetchDetails": true}
Input parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search builds URLs from filters; url scrapes pasted links. |
locations | array | ["Amsterdam"] | Cities or areas to search (search mode). |
propertyType | string | all | Commercial category, for example office, retail, catering. |
dealType | string | both | Buy, rent, or both. |
keyword | string | Optional free-text term. | |
minPrice / maxPrice | integer | Price or rent bounds. | |
rentPriceBasis | string | per_month | How rent bounds are applied: per month, year, or square metre. |
minArea / maxArea | integer | Floor area bounds in square metres. | |
publicationDate | string | any | Published within today, 3, 5, 10, or 30 days. |
surrounding | array | Area context, for example town centre, office park. | |
amenities | array | Required building features. | |
availability | array | Availability signals. | |
parking | string | any | Minimum parking capacity. |
constructionType | string | any | Existing or new construction. |
propertyAge | array | Construction period buckets. | |
energyLabel | array | Energy labels A to G. | |
auctionDate | string | any | Upcoming auction window. |
openDay | string | any | Open-day availability. |
includeSoldRented | boolean | false | Also include sold or rented listings. |
sortBy | string | relevance | Result ordering (nine options). |
urls | array | URLs to scrape (URL mode). | |
highlighted | boolean | false | Only featured listings. Applies in both search mode and URL mode. |
language | string | nl | Page language, nl or en. |
fetchDetails | boolean | true | Include full detail (description, characteristics, coordinates, images, agent phone) per listing. |
includeAgencyDetails | boolean | false | Enrich each agency with profile and reviews. |
maxItems | integer | 20 | Item cap for the run (0 = unlimited). |
maxPages | integer | 200 | Safety ceiling on pages per search. |
resumeFromRunId | string | Continue one specific previous run/dataset: listings already collected there are skipped. For recurring daily monitoring, use Incremental mode instead, see "Resume & recurring updates" below. | |
incrementalMode | boolean | false | Daily/recurring monitoring of this same search. First run returns everything as NEW; later runs return only NEW/UPDATED/REAPPEARED by default. See "Resume & recurring updates" below. |
stateKey | string | Optional name for a monitoring campaign, so its incremental state stays stable or is deliberately shared. Auto-derived from your mode/location/URL and filter settings when left empty. | |
emitUnchanged | boolean | false | Incremental mode only. Also return listings unchanged since the last run, marked UNCHANGED. Adds and bills extra rows you already have. |
emitExpired | boolean | false | Incremental mode only. Also return listings from a previous run no longer found, marked EXPIRED, once a run has fully scanned the search (not capped, not a resume). Adds and bills extra synthetic rows. |
proxy | object | Apify proxy | Connection settings. |
Which filters apply in which mode
Every filter from propertyType down to sortBy is posted to the Funda in Business search form, so it only narrows results in search mode; URL mode never sends that form and ignores them. highlighted is the exception: Funda in Business has no server-side option for it, so the run applies it to every result page it walks, which means it also narrows a search-result URL you pasted in URL mode. A pasted single-listing URL is scraped directly and is never dropped by highlighted.
propertyType and dealType do one extra thing in both modes: their values are copied onto every record as labels (property.property_type, source_context.search.property_type, source_context.search.deal_type, and the listing.deal_type fallback used when a listing's price text does not say whether it is for sale or for rent). In URL mode they label the output without filtering it, so leave them at their defaults there unless you want that label.
Resume & recurring updates
There are two different things here, pick the one that matches what you're doing:
| Need | Use |
|---|---|
| A crawl stopped and should continue | resumeFromRunId |
| Run the same search every day and receive only changes | incrementalMode |
| Keep separate daily campaigns for similar searches | distinct stateKey values |
| Run a normal full snapshot | leave both off |
Resume (resumeFromRunId) continues one specific interrupted or previous large crawl: paste a run ID or dataset ID and this run skips listings already collected there, returning only the remaining new listings. An invalid or unreadable id fails the run with a clear message rather than silently re-scraping and re-billing everything.
Incremental mode (incrementalMode) is for a schedule (for example, daily): the actor remembers the previous run of the same search by itself, so you never paste a run ID. The first run returns everything as NEW. Later runs return only NEW, UPDATED, and REAPPEARED listings by default: duplicates and unchanged listings are suppressed (and not charged). Turn on emitUnchanged or emitExpired only when you also want those rows returned (and billed for). Classification happens after any detail-page enrichment, so a change visible only on the detail page (a new price, a changed status) is still detected. State is isolated per mode/location/URL and filter setup automatically; set stateKey to name or deliberately share a monitoring campaign.
Scheduled-run example, same search, run daily:
Day 1 (first run ever for this search):
{ "mode": "search", "locations": ["Amsterdam"], "propertyType": "office", "incrementalMode": true }
→ every listing comes back with "changeType": "NEW".
Day 2 (the schedule fires again, identical input):
{ "mode": "search", "locations": ["Amsterdam"], "propertyType": "office", "incrementalMode": true }
→ listings whose price/status/characteristics changed come back as "changeType": "UPDATED" with changedFields listing what changed, brand-new listings come back as "changeType": "NEW", listings that vanished and came back come back as "changeType": "REAPPEARED", and listings that are still there, unchanged, are not returned at all (suppressed, not charged) unless emitUnchanged is on. emitExpired additionally reports listings from a previous run no longer found, once a run scans the tracked search completely (no cap hit, no resume).
Incremental mode only. When incrementalMode is on, every returned record also carries:
| Field | Description |
|---|---|
changeType | NEW | UPDATED | UNCHANGED | REAPPEARED | EXPIRED |
changedFields | Top-level sections that changed since last seen; non-empty only for UPDATED |
firstSeenAt | When this listing was first observed by this monitoring campaign |
lastSeenAt | When this listing was last observed |
Send results into your apps (MCP connectors)
You can optionally pipe each run's results into the apps you already use through Model Context Protocol (MCP) connectors. Authorize a connector under Apify then Settings then API & Integrations, select it in the mcpConnectors input, and (for Notion) set notionParentPageUrl. Each item is written as a condensed, human-readable summary (a title plus the key fields flattened to plain text), not the full JSON; the complete record always stays in the Apify dataset. Leave the field empty to skip; it never changes the dataset output. Supported: Notion, Linear, Airtable, Apify.
Output example
Sample shape, values are illustrative placeholders, not from a live listing.
{"record_type": "property_listing","record_id": "00000001","source_context": {"source_domain": "fundainbusiness.nl","source_url": "https://www.fundainbusiness.nl/kantoor/amsterdam/object-00000001-sample-street-1/","enrichment_status": "enriched","page_number": 1,"position": 1,"scraped_at": "2026-01-01T00:00:00+00:00","language": "nl","country": "NL"},"entity": {"title": "Sample Street 1, Amsterdam","description": "Full listing description appears here when fetchDetails is enabled.","url": "https://www.fundainbusiness.nl/kantoor/amsterdam/object-00000001-sample-street-1/","category": "Office"},"listing": { "deal_type": "rent", "source_category": "Kantoor", "available_from": "Per direct beschikbaar" },"pricing": { "price": 3250, "currency": "EUR", "price_text": "EUR 3.250 /mnd" },"location": { "city": "Amsterdam", "region": "Noord-Holland", "latitude": 52.0000, "longitude": 4.0000 },"property": { "property_type": "office", "floor_area": 98, "energy_label": "A", "construction_year": 2020 },"media": { "image_count": 6, "image_urls": ["https://cloud.funda.nl/valentina_media/000/000/000_1440x960.jpg"] },"relationships": {"agency": {"name": "Sample Brokers","url": "https://www.fundainbusiness.nl/makelaar/0000-sample-brokers/","phone": "+310000000000","email": "agent@example.com","reviews": { "total": 2, "average_score": 8.6, "formatted_average_score": "8,6" }}}}
Plan requirement
Runs on any Apify plan.
Verification
- 2026-09-01: re-audited against the live site. Fixed search-mode filtering: the site's filter endpoint started refusing requests without a full browser header set, which made every filtered search silently fall back to the unfiltered results page; the request headers were updated so the filters narrow again. The keyword now rides the URL in the site's current
?zoek=form (the old form field stopped narrowing) and is re-attached when paginating. Re-derived live: Amsterdam offices 1,555, keyword "gracht" 106, min area 500 m2 433 (filtered pagination verified on page 2), buy-only 83; a nonsense keyword returns zero.