# Funda.nl Scraper | Dutch Property & Real Estate (`ahmed_jasarevic/funda-scraper`) Actor

Extract residential and commercial property listings from Funda.nl and FundainBusiness.nl — prices, addresses, features and images. Netherlands real estate data.

- **URL**: https://apify.com/ahmed\_jasarevic/funda-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Categories:** Real estate, Developer tools, Automation
- **Stats:** 5 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 listings

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/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

## Funda.nl & FundainBusiness.nl Scraper

The ultimate **Funda scraper** for extracting Netherlands property data — residential and commercial listings from the largest Dutch real estate platform. Get structured property data for analytics, investment screening, and market research.

### Use Cases

- **Real Estate Analytics** — Analyze Dutch housing market trends, property prices, and inventory across cities
- **Investment Screening** — Identify high-yield rental properties and commercial real estate opportunities in the Netherlands
- **Agent Lead Generation** — Collect listing agent contact details to build a Dutch real estate agent database
- **Price Monitoring** — Track property price changes and days-on-market to spot market shifts
- **Market Research** — Study Amsterdam, Rotterdam, and Den Haag apartment availability and pricing
- **Commercial Real Estate** — Scrape office, retail, and commercial listings from FundainBusiness.nl

### How It Works

1. Pass one or more Funda.nl or FundainBusiness.nl search URLs as input
2. The actor navigates each search result page and extracts property details
3. Each listing is parsed into structured JSON — address, price, size, rooms, agent, and more
4. Results are stored in a dataset you can download as JSON, CSV, or Excel

### Input

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `startUrls` | `array` | No\* | — | Funda URLs: search pages (`/zoeken/koop`, `/zoeken/huur`) or single listings (`/detail/…`, `object-…`). Leave empty to search via filters below |
| `searchLocation` | `string` | No | — | City / area slug, or `place, Nkm` for a radius (e.g. `amsterdam`, `coevorden, 10km`) |
| `searchKeywords` | `string` | No | — | Free-text keywords Funda should match (e.g. `gracht`, `tuin`, `nieuwbouw`) |
| `searchTransactionType` | `string` | No | `buy` | `buy` (koop) or `rent` (huur) |
| `searchPriceMin` | `integer` | No | — | Minimum price in EUR |
| `searchPriceMax` | `integer` | No | — | Maximum price in EUR |
| `contentLanguage` | `string` | No | `en` | Listing text language: `en` (English) or `nl` (Dutch original) |
| `scrapeDetails` | `boolean` | No | `true` | `true` = full detail pages; `false` = **Light mode** (card data only — 15-25x fewer requests) |
| `maxItems` | `integer` | No | `100000` | Stop after this many listings (`0` = unlimited) |
| `minConcurrency` | `integer` | No | `10` | Minimum parallel workers |
| `maxConcurrency` | `integer` | No | `50` | Maximum parallel requests |
| `maxRequestRetries` | `integer` | No | `3` | Retries on failed HTTP calls |
| `proxy` | `object` | No | Apify Residential | Proxy configuration for request routing |

> \* `startUrls` is optional: if empty and at least one search filter is set, the
> Actor builds the Funda search URL for you.

#### Example Input

```json
{
  "startUrls": [
    { "url": "https://www.funda.nl/zoeken/koop?selected_area=%5B%22amsterdam%22%5D" }
  ],
  "scrapeDetails": true,
  "contentLanguage": "en",
  "maxItems": 50,
  "maxConcurrency": 50,
  "proxy": {
    "useApifyProxy": true
  }
}
```

Or search purely by filters (no URLs needed):

```json
{
  "searchLocation": "amsterdam",
  "searchKeywords": "tuin",
  "searchTransactionType": "buy",
  "searchPriceMin": 300000,
  "searchPriceMax": 600000,
  "maxItems": 30
}
```

### Fast & Cheap Mode (`scrapeDetails: false`)

Set `scrapeDetails` to `false` to skip visiting every detail page. **Light mode no
longer reads only the search cards** — it parses the full listing JSON embedded in
the search page's `__NUXT_DATA__` payload, so each card yields near-detail data
(street, postcode, city, province, neighbourhood, municipality, formatted + numeric
price, rooms, bedrooms, living area, energy label, status, offering/object/construction
type, agent name, and a high-res photo URL) without a single extra request beyond the
list page itself. That cuts the number of residential proxy requests by roughly
**15-25x** while keeping most of the signal that used to require detail pages. Ideal
for bulk surveys, price monitoring, and lead lists.

Only description, coordinates, floor plans, videos, build year, and the full
characteristics tables are exclusive to Detail mode.

### Monetization (pay-per-event)

The code already emits charge events via
[`Actor.charge()`](https://docs.apify.com/sdk/js/docs/concepts/pay-per-event), but
they only activate once you enable monetization — otherwise runs stay free.

There are **two chargeable events**, mirroring the two output tiers:

| Event name | Fires when | Meaning |
|---|---|---|
| `listing-scraped` | every listing, **both** modes | your "default dataset item" — one charge per pushed result |
| `detail-item` | only when `scrapeDetails: true` | the extra per-item charge for full detail data |

So in **Light mode** every result fires 1 charge (`listing-scraped`), and in
**Detail mode** every result fires 2 charges (`listing-scraped` + `detail-item`).

To start charging:

1. In Apify Console open **Publishing → Monetization** and choose the **pay-per-event** model.
2. Define a chargeable event and name it **exactly `listing-scraped`** and set its price.
3. Optionally define a second event named **exactly `detail-item`** and set its price
   (users only pay it when they enable full detail scraping).
4. Publish/save — charges start applying on the next runs. The run stops automatically at the user's budget limit.

Test locally: `ACTOR_TEST_PAY_PER_EVENT=true apify run` — records appear in the
`charging-log` dataset at the default $1 test price.

Cheapest tips for you (and your users): keep `maxItems` bounded, prefer
`scrapeDetails: false` (charges only 1 event, not 2), use a low price per event
(e.g. `$0.0005` for `listing-scraped` and `$0.00075` for `detail-item`), skip any
Actor Start fee. It runs on a **default 512 MB** (CheerioCrawler is memory-light),
so compute stays cheap while the fast parser keeps concurrency high.

### Output

#### Light mode — near-detail data per card (single list-page request):

`url`, `tinyId`, `title`, `address` (street, postcode, city, province, neighbourhood, municipality), `price` (`{ formatted, numeric }`), `stats` (rooms, bedrooms, livingArea, plotArea), `energyLabel`, `status`, `offeringType`, `objectType`, `constructionType`, `publicationDate`, `agentName`, `photoUrl`, `scrapeMode`, `scrapedAt`

#### Detail mode — each result contains:

| Field | Description |
|-------|-------------|
| `url` | Direct link to the listing on Funda |
| `title` | Property headline (e.g., "Ruim 3-kamer appartement") |
| `tinyId` / `globalId` | Funda internal identifiers |
| `address` | street, postcode, city, province, neighborhood, municipality |
| `coordinates` | `{ latitude, longitude }` when available |
| `agentName` | Listing agent / makelaar |
| `price` | `{ formatted, numeric }` (e.g. `"€ 425.000 k.k."` / `425000`) |
| `stats` | rooms, bedrooms, living area (m²), plot area (m²) |
| `status` | listing status (available, sold…) |
| `offeringType` | `koop` or `huur` |
| `objectType` / `constructionType` | Property & construction type |
| `publicationDate` | When the listing was published |
| `surfaces` | Total surface & number of floors |
| `build` | Build year & energy label |
| `media` | photo URLs, floor-plan URLs, video URLs |
| `characteristicsBySection` | Full characteristic tables (overdracht, oppervlakten, energie…) |
| `advertisementTargeting` | Funda native targeting payload |
| `description` | Full property description |
| `scrapedAt` | Timestamp of when the listing was scraped |

#### Example Output

```json
{
  "url": "https://www.funda.nl/koop/amsterdam/appartement-stationsplein-10/",
  "tinyId": "12345678",
  "title": "Stationsplein 10 1012AB Amsterdam",
  "scrapeMode": "detail",
  "address": { "streetAddress": "Stationsplein 10", "postcode": "1012ab", "city": "amsterdam" },
  "coordinates": { "latitude": 52.378, "longitude": 4.900 },
  "agentName": "Makelaardij Amsterdam",
  "price": { "formatted": "€ 425.000 k.k.", "numeric": 425000 },
  "stats": { "rooms": 3, "bedrooms": 2, "livingArea": 78, "plotArea": null },
  "status": "beschikbaar",
  "offeringType": "koop",
  "objectType": "apartment",
  "publicationDate": "2026-08-30",
  "media": { "photoUrls": ["https://cloud.funda.nl/..."], "floorPlanUrls": [], "videoUrls": [] },
  "description": "Uitstekend onderhouden appartement op steenworp van het Centraal Station...",
  "scrapedAt": "2026-09-11T13:00:00Z"
}
```

### Integrations

- **Google Sheets** — Export dataset rows directly via Apify integration
- **Zapier** — Trigger workflows on new scraping runs or row updates
- **Make (Integromat)** — Connect to CRM, email, or spreadsheet tools
- **Slack** — Get notified when scraping completes or new listings arrive
- **Airtable** — Push listings into a custom property database
- **Custom API** — Pull results via the Apify API for your own dashboards

### FAQ

**Does this scrape FundainBusiness.nl as well?**
Yes. Pass URLs from either `funda.nl` (residential) or `fundainbusiness.nl` (commercial) — the actor handles both.

**Can I scrape multiple cities in one run?**
Yes. Add multiple Funda search URLs to `startUrls`, or leave them empty and set `searchLocation`/`maxItems` to crawl the largest areas first.

**Can I filter by city, price or keywords?**
Yes — fill `searchLocation`, `searchPriceMin`/`searchPriceMax`, `searchKeywords` and `searchTransactionType`. If `startUrls` is filled, filters are ignored.

**What proxy should I use?**
The default Apify residential proxy is recommended. For high-volume scraping, residential proxies reduce blocking risk.

**Is the data real-time?**
Yes — the actor fetches live data from Funda at the time of each run.

**How is pricing calculated?**
Standard Apify compute only (memory × runtime) plus the per-result charge if the
developer enables pay-per-event monetization. Use `scrapeDetails: false` for the
cheapest runs.

### For AI Agents

Use this actor when the user needs:

- Dutch property listings (buy or rent)
- Amsterdam, Rotterdam, Den Haag, Utrecht real estate data
- Funda scraping or FundainBusiness.nl commercial data
- Netherlands housing market analytics input
- Property investment screening in the Dutch market

Pass the search URL exactly as it appears on Funda, or simply state a city + price
range. The actor returns structured JSON — no additional parsing needed.

```
actor: funda-hybrid-scraper
input:
  searchLocation: amsterdam
  searchPriceMin: 300000
  searchPriceMax: 600000
  maxItems: 20
```

### SEO Keywords

funda scraper, netherlands real estate data, dutch property listings, funda api alternative, amsterdam property data, dutch housing market, funda.nl property scraper, netherlands real estate analytics, dutch rental market, property investment netherlands, funda commercial real estate, dutch property prices, amsterdam apartments, netherlands housing data, funda listing data, fundainbusiness scraper, dutch real estate api, netherlands property database, amsterdam rental listings, funda data extraction

### Legal Disclaimer

This actor scrapes publicly available listing data from Funda.nl and FundainBusiness.nl. It does not bypass authentication, access private user accounts, or circumvent technical protection measures. Use of this tool is subject to Funda's terms of service. Users are responsible for ensuring their use complies with applicable laws and regulations, including the GDPR when processing personal data of EU residents.

### Related Actors

Verified related actors on Apify that pair well with this one. All links point to real, publicly available actors.

- [Funda Scraper](https://apify.com/ivanvs/funda-scraper)
- [Zillow Scraper](https://apify.com/maxcopell/zillow-scraper)
- [Immobilienscout24 Scraper](https://apify.com/memo23/immobilienscout24-scraper)

# Actor input Schema

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

Search pages (/zoeken/koop, /zoeken/huur) or single listing (/detail/…, object-…). Example: https://www.funda.nl/zoeken/koop?selected\_area=\[%22amsterdam%22]. Leave empty and use the search filters below instead.

## `searchLocation` (type: `string`):

City or area slug, or 'place, Nkm' for radius. Examples: amsterdam, rotterdam, coevorden, 10km. Used to auto-build a search URL when 'Funda URLs' is empty.

## `searchKeywords` (type: `string`):

Words Funda should match in listings. Examples: gracht, tuin, zuid, nieuwbouw. Leave empty to skip the text filter.

## `searchTransactionType` (type: `string`):

Koop (sale) or huur (rent).

## `searchPriceMin` (type: `integer`):

Lower price bound in whole euros. Example: 200000.

## `searchPriceMax` (type: `integer`):

Upper price bound in whole euros. Example: 450000.

## `contentLanguage` (type: `string`):

Accept-Language for listing copy: English translation vs Dutch original.

## `scrapeDetails` (type: `boolean`):

Enabled: visits every listing detail page and extracts rich data (description, characteristics, price, agent, coordinates, media, build info). Disabled: light mode extracts essentials (title, price, surface, postcode, city, photo) directly from search-result pages — 15-25x fewer requests, much faster and cheaper.

## `maxItems` (type: `integer`):

Stop after this many listings. Set to 0 for unlimited.

## `minConcurrency` (type: `integer`):

Minimum parallel workers. Higher values keep the crawl fully parallel.

## `maxConcurrency` (type: `integer`):

Maximum parallel requests. 50 is a good default with residential proxies.

## `maxRequestRetries` (type: `integer`):

Retries on failed HTTP calls.

## `proxy` (type: `object`):

Residential proxies are recommended for Funda to avoid blocks and interstitials.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.funda.nl/zoeken/koop?selected_area=[%22amsterdam%22]"
    }
  ],
  "searchTransactionType": "buy",
  "contentLanguage": "en",
  "scrapeDetails": true,
  "maxItems": 100000,
  "minConcurrency": 10,
  "maxConcurrency": 50,
  "maxRequestRetries": 3,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

Scraped Funda listings

## `datasetUrl` (type: `string`):

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://www.funda.nl/zoeken/koop?selected_area=[%22amsterdam%22]"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/funda-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 = { "startUrls": [{ "url": "https://www.funda.nl/zoeken/koop?selected_area=[%22amsterdam%22]" }] }

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/funda-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 '{
  "startUrls": [
    {
      "url": "https://www.funda.nl/zoeken/koop?selected_area=[%22amsterdam%22]"
    }
  ]
}' |
apify call ahmed_jasarevic/funda-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ahmed_jasarevic/funda-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/eob6yoaesgkSCCRU5/builds/bBRfoedat9vrlJuPy/openapi.json
