# Funda Scraper - Dutch Houses for Sale and Rent (`s-r/funda-scraper`) Actor

Funda scraper for Dutch homes for sale and rent. Enter a city, area or Funda search URL and get one row per property: asking price (k.k./v.o.n.), address with postcode, living area, rooms, broker and photos. For brokers, investors and proptech teams.

- **URL**: https://apify.com/s-r/funda-scraper.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Funda Scraper - Dutch Houses for Sale and Rent

Funda Scraper collects Dutch property listings for sale and rent from Funda, the largest housing portal in the Netherlands. Search by a location or paste a Funda search URL, then export asking prices, addresses, postcodes, living area, rooms, brokers and photos as structured rows for brokers, investors, proptech teams and housing researchers.

Use the results to compare advertised properties, follow a local market, prepare a brokerage shortlist or match public listings with another address-based dataset. Every row includes the public Funda listing ID and its source URL, so you can return to the original listing and check the advertised information. Download the data as JSON, CSV or Excel, or read it through the Apify API.

### What the Funda Scraper is used for

- **Market monitoring.** Run the same search every day or week and compare dated exports to see new listings, price changes and properties that disappeared from the market.
- **Brokerage and lead research.** Count listings per brokerage in a city or province, see which brokers list which property types and find the brokerage page behind each listing.
- **Investment screening.** Filter by asking price, living area and rooms, then calculate the asking price per square metre per neighbourhood before you look at individual properties.
- **Rental market research.** Collect monthly asking rents for a city and compare them by size, number of bedrooms or district.
- **Address matching.** Postcode, house number and suffix are separate fields, so listings can be joined with other Dutch address-based sources such as registered transaction data.

### How to scrape Funda without code

1. Enter a city, municipality, province, neighbourhood or postcode area in `location`, or paste a Funda search URL in `url`.
2. Choose `buy` or `rent`, and optionally add a price range, property type and minimum size.
3. Set `max_items` and start the run. Results appear in the dataset table and can be exported straight away.

### Funda Scraper input

| field | default | meaning |
|---|---|---|
| `location` | — | City, municipality, province, neighbourhood or postcode area; a list combines up to 10 areas |
| `url` | — | Funda buy or rent search URL; its filters take precedence |
| `offering_type` | `buy` | `buy` or `rent` |
| `status` | `available` | `available` (includes negotiations) or `sold` |
| `sort` | `relevance` | `relevance`, `newest`, `oldest`, `price_asc`, `price_desc`, `floor_area_desc` |
| `object_type` | all | `house`, `apartment`, `parking`, `land`, `berth`, `pitch`, `storage`, `storage_space`, `substructure` |
| `price_min`, `price_max` | — | Asking price in euros; per month for rent |
| `min_floor_area` | — | Minimum living area in square metres |
| `min_rooms`, `min_bedrooms` | — | Minimum rooms and bedrooms |
| `max_items` | 100 | Maximum unique listings, 1 to 9,990 |

Start with a Dutch city, municipality, province, neighbourhood or postcode area in `location`. The result includes the resolved area so you can check how Funda interpreted your input. For a combined-area search, pass a list of up to 10 areas in `location`, or paste a Funda search URL with several selected areas. Those areas are combined with OR rather than requiring a property to belong to every area.

Alternatively, supply `url` with a Funda buy or rent search URL. The URL determines the transaction type and search filters. This is useful when you have already prepared a search on Funda with several filters. Collection starts at the first page even if the pasted URL points to a later results page. Search URLs with a radius are currently unsupported; use a named area instead.

This input was used for the included Amsterdam example:

```json
{"location":"Amsterdam","max_items":15}
```

For rental searches, choose `offering_type: "rent"`. Asking-price filters use euros per month for rent and euros per property for sale. Set `price_min` and `price_max` to narrow the range. The included rental example uses this actual input:

```json
{"location":"Den Bosch","offering_type":"rent","price_min":1000,"price_max":2000,"max_items":15}
```

Other options include `object_type`, `min_floor_area`, `min_rooms` and `min_bedrooms`. Property types use Funda's names, including `house`, `apartment` and `parking`. Leave `object_type` empty to include every type. Sort by relevance, newest, oldest, ascending price, descending price or descending living area. URL filters take precedence when you supply a search URL.

`max_items` defaults to 100 and accepts values from 1 to 9,990. It is a maximum number of unique listings, not a promise that the location contains that many properties. A search with seven matching properties returns seven rows even if the requested maximum is fifteen.

### Output

The default dataset contains one row per unique property. The public `listing_id` comes from the detail URL; `search_id` is Funda's separate internal search identifier. Keep `listing_id` or `url` when matching repeated collections.

Address fields include the complete formatted `address`, `street` with number and suffix, `street_name`, `house_number`, `house_number_suffix`, `postal_code`, `city`, province in `state`, municipality and neighbourhood information when supplied. The postcode is preserved without a space for address matching. The formatted address includes the usual space in the postcode.

Each listing also contains `property_type`, `living_area`, `lot_area`, `rooms`, `bedrooms`, energy label, source status and publication date where available. Area units are square metres. `broker` identifies the primary brokerage, while `brokers` contains the listed brokerage organisations. `image_url` contains the first photo and `image_urls` contains all listing photos. The collection does not include individual broker contact details.

`source`, `platform`, `fetched_at`, `query` and `position` describe where and when a row was collected. Positions continue across collected pages after duplicate removal. The original listing URL provides a direct route back to the property's current public information.

The response also reports `total_results`, resolved `areas`, `pages_fetched`, continuation status and warnings. Apify collects continuation pages automatically. Source warnings explain when the requested collection could not be completed.

This is the first row of the Amsterdam example above (`{"location":"Amsterdam","max_items":15}`), collected on 5 October 2026. Only the photo list is shortened; the listing has 37 photos.

```json
{
  "source": "funda-scraper",
  "platform": "funda",
  "fetched_at": "2026-10-05T17:34:06.148Z",
  "url": "https://www.funda.nl/detail/koop/amsterdam/appartement-wijsmullerstraat-12-3/44523337/",
  "listing_id": "44523337",
  "search_id": 8178974,
  "listing_type": "for_sale",
  "query": "Amsterdam",
  "position": 1,
  "address": "Wijsmullerstraat 12-3, 1058 JJ Amsterdam",
  "street": "Wijsmullerstraat 12-3",
  "street_name": "Wijsmullerstraat",
  "house_number": "12",
  "house_number_suffix": "3",
  "city": "Amsterdam",
  "postal_code": "1058JJ",
  "state": "Noord-Holland",
  "country_code": "NL",
  "municipality": "Amsterdam",
  "wijk": "Hoofddorppleinbuurt",
  "neighbourhood": "Surinamepleinbuurt",
  "is_bag_address": true,
  "price": 825000,
  "currency": "EUR",
  "price_condition": "kosten_koper",
  "price_type": "regular",
  "selling_price": 825000,
  "rent_price": null,
  "offering_types": [
    "buy"
  ],
  "property_type": "apartment",
  "living_area": 80,
  "living_area_unit": "m2",
  "lot_area": null,
  "lot_area_unit": "m2",
  "rooms": 4,
  "bedrooms": 3,
  "construction_type": "resale",
  "energy_label": "A+",
  "status": "none",
  "publish_date": "2026-10-05T17:01:21.2823041+02:00",
  "broker": "Van Baerle Makelaars",
  "broker_id": 24569,
  "broker_url": "https://www.funda.nl/makelaar/24569-van-baerle-makelaars/",
  "broker_association": "NVM",
  "brokers": [
    {
      "id": 24569,
      "name": "Van Baerle Makelaars",
      "association": "NVM",
      "is_primary": true,
      "url": "https://www.funda.nl/makelaar/24569-van-baerle-makelaars/"
    }
  ],
  "image_url": "https://cloud.funda.nl/tiara-media/81d77c36-6204-4fd4-847d-b05344800640/243c717c-32eb-4549-9d7c-0f63fc3a254d?options=width=720",
  "image_urls": [
    "https://cloud.funda.nl/tiara-media/81d77c36-6204-4fd4-847d-b05344800640/243c717c-32eb-4549-9d7c-0f63fc3a254d?options=width=720",
    "https://cloud.funda.nl/tiara-media/81d77c36-6204-4fd4-847d-b05344800640/68cf476d-d016-4962-b8e8-49197743e65e?options=width=720"
  ],
  "photo_count": 37,
  "promo_text": null,
  "media_types": [
    "floor_plan",
    "photo_360",
    "video"
  ],
  "project": null
}
```

### Asking prices and sold properties

For an active sale search, `price` is the asking price in euros. For an active rental search, it is the monthly rental asking price. `currency` is EUR. `price_condition` preserves `kosten_koper` for k.k., `vrij_op_naam` for v.o.n. and `per_month` for monthly rent. A price on request produces a null value, which should not be treated as a zero-price property.

A property advertised for both sale and rent follows your selected search type in `price` and `listing_type`. Its separate `selling_price` and `rent_price` remain available so the two advertised amounts are not confused.

Choose `status: "sold"` to search sold or rented properties. Funda's search results provide their last asking price, not their actual transaction price. Consequently, the standard `price` field is null in these results. The last advertised amount remains in `selling_price` or `rent_price`. Sold purchase listings have `listing_type: "sold"`; rented listings have a null listing type because the common dataset format does not define a rented category.

### Funda Scraper compared with other ways to get Funda data

| option | what you get | what to consider |
|---|---|---|
| This Funda Scraper | Search results as rows: asking price, price condition, address with postcode, living area, rooms, broker and photos, for sale and rent | No code, export to JSON, CSV or Excel, pay per delivered listing |
| Funda's own APIs | Funda offers data exchange for brokerages, such as lead delivery | Meant for brokerages' own listings and leads, not for searching the whole market |
| Open-source Python projects | Code you run and maintain yourself | You handle pagination, changes to the site and scheduling |
| Copying from the website | A few listings at a time | Slow, no structured postcode or price-condition fields |

### Pricing

The actor uses one run-start event and one listing event per delivered dataset row. Listing charges follow duplicate removal and the applicable free-user limit. A search without matching properties produces no listing charges; its run-start event still applies. Check the current Pricing tab for the published event amounts before starting a run.

The free-user allowance is up to ten delivered listings per run. Paying users can request the full supported search limit. Increasing `max_items` only increases delivered volume when matching properties exist and collection can complete. Properties without a numeric asking price are still valid listing rows.

### Limits and practical use

Funda exposes at most 9,990 accessible results for an individual search. For broader coverage, split searches by city, municipality, province or asking-price range. `total_results` can exceed the accessible result window; it describes the matching population reported by Funda rather than the number the actor promises to deliver.

Listings can change while collection is running. A price, status or sort order may be updated between pages. The actor removes duplicate listing IDs but does not provide a frozen historical snapshot. Save dated exports if you want to build your own sequence of observations.

This version collects public search-listing information. Detailed descriptions, construction year, coordinates, cadastral records and realised transaction prices are outside this output. Use the provided address fields as matching candidates and verify any external match before drawing property-specific conclusions.

### FAQ

#### Can I use a search URL instead of a city?

Yes. Paste an HTTPS Funda buy or rent search URL in `url`. Its filters determine the search. Detail-page URLs and radius searches are unsupported.

#### Does a sold listing include the final sale price?

No. Funda supplies the last asking price in search results. The actor preserves that amount separately and leaves `price` null for sold and rented results.

#### Why did the actor return fewer listings than max_items?

The limit is a maximum. Your filters may have fewer matches, the source's result window may be reached, or a source response may prevent completion. Check the returned total and warnings.

#### Can I identify the same property across exports?

Use its public `listing_id` and `url`. The postcode, house number and suffix also support matching with address-based sources, subject to checking the match.

#### Is there an official Funda API?

Funda offers data exchange for brokerages, for example a lead API for its own customers. There is no public API for searching all listings. This Funda Scraper returns the public search results as structured rows that you can read through the Apify API.

#### Can I export Funda listings to Excel or CSV?

Yes. Every run stores its rows in an Apify dataset, which you can download as JSON, CSV, Excel or XML, or connect to Google Sheets and other tools through integrations.

#### Can I search several cities at once?

Yes. Pass a list of up to 10 areas in `location`, for example two neighbouring municipalities. A property is included when it lies in any of them, and duplicates are removed.

# Actor input Schema

## `location` (type: `string`):

City, municipality, province, neighbourhood or postcode area. A list combines up to 10 areas with OR.

## `url` (type: `string`):

A Funda buy or rent search URL. Its filters take precedence over location and other search filters. Radius searches are unsupported.

## `offering_type` (type: `string`):

Buy listings or monthly rental listings. The URL determines this when supplied.

## `status` (type: `string`):

Available includes negotiations. Sold returns sold or rented listings with their last asking price only.

## `sort` (type: `string`):

Result ordering. Price ordering uses the selected transaction type.

## `object_type` (type: `array`):

Optional Funda property types. An empty list includes all types.

## `max_items` (type: `integer`):

Maximum unique listings across cursor pages; at most 9,990 per search.

## `cursor` (type: `string`):

Opaque next_cursor from a previous request. Keep the same search input. Apify follows continuations automatically.

## `price_min` (type: `integer`):

Minimum asking price in euros; per month for rent.

## `price_max` (type: `integer`):

Maximum asking price in euros; per month for rent.

## `min_floor_area` (type: `integer`):

Minimum living area in square metres.

## `min_rooms` (type: `integer`):

Minimum number of rooms.

## `min_bedrooms` (type: `integer`):

Minimum number of bedrooms.

## Actor input object example

```json
{
  "location": "Amsterdam",
  "offering_type": "buy",
  "status": "available",
  "sort": "relevance",
  "max_items": 100
}
```

# Actor output Schema

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

One row per unique property in the default dataset.

## `output` (type: `string`):

Counts, continuation status and warnings.

# 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 = {
    "location": "Amsterdam"
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/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 = { "location": "Amsterdam" }

# Run the Actor and wait for it to finish
run = client.actor("s-r/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 '{
  "location": "Amsterdam"
}' |
apify call s-r/funda-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/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/mweZBnRH2g54RzDkG/builds/0zLGMeiSh5VQ7kBxU/openapi.json
