# Funda Scraper (`tortuga/funda-scraper`) Actor

Scrape Funda.nl homes for sale and for rent: price, address, living area, rooms, energy label, agent, photos, listing date, plus full details on request. Works with any Funda search URL.

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

## Pricing

from $2.00 / 1,000 listing scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Scraper

Scrape Funda.nl homes for sale (koop) and for rent (huur), including new builds: price, address, postcode, neighbourhood, living and plot area, rooms, bedrooms, energy label, status, listing date, estate agent and photos. Works with any Funda search URL.

Paste any funda.nl search page (with whatever filters and sort you picked in the browser) or just type an area, and get every listing as clean JSON, CSV or Excel, or straight into your app through the API. Built for reliability: it reads the structured search state Funda embeds in every page instead of scraping the visual layout, uses browser-grade TLS fingerprints, throttles itself and retries on a fresh proxy session, so runs finish instead of failing halfway. You pay only for the listings you get.

### What data does Funda Scraper extract?

Every listing from the search results gives you:

| Field | Description |
|---|---|
| `id`, `tinyId`, `url` | Funda's global listing id, the id used in the URL, and the canonical listing URL |
| `title`, `address` | "Binnenkant 46-A" and "Binnenkant 46-A, 1011 BP Amsterdam" |
| `street`, `houseNumber`, `postcode`, `city`, `neighbourhood`, `district`, `municipality`, `province` | Full address breakdown (postcode in the Dutch "1011 BP" format) |
| `listingType` | `koop` (for sale) or `huur` (for rent) |
| `price`, `priceMax`, `priceCurrency` | Numeric asking price or monthly rent in EUR; `priceMax` only for "from-to" ranges |
| `priceType` | `k.k.` (kosten koper), `v.o.n.` (vrij op naam) or `per maand` |
| `priceKind` | Funda's price kind, e.g. `regular`, `price_on_request`, `auction` |
| `pricePerSqm` | Price divided by living area (EUR/m²) |
| `livingAreaSqm`, `plotAreaSqm` | Living area and plot size in m² |
| `rooms`, `bedrooms` | Room counts |
| `propertyType` | `house`, `apartment`, `parking`, `land`, ... |
| `energyLabel` | A+++ ... G |
| `status` | `available`, `under offer`, `under option`, `sold under reservation`, `rented under reservation`, `sold`, `rented` |
| `publishedAt` | When the listing went live on Funda (ISO date-time) |
| `isNewBuild`, `constructionType` | New build (nieuwbouw) flag; `newly_built` or `resale` |
| `promoText` | The agent's one-line teaser (blikvanger) |
| `openHouse` | Open house slot when announced |
| `mediaTypes` | Which media the listing has: `floor_plan`, `video`, `photo_360` |
| `agent` | `{id, name, url, association, logoUrl}` of the estate agent office (makelaar); `agents` when several offices share a listing |
| `images`, `imageCount` | Full-size photo URLs |
| `sourceUrl`, `scrapedAt` | The search URL the listing came from and the scrape timestamp |

Turn on **Include listing details** to also open each listing page and add:

| Field | Description |
|---|---|
| `description` | Full listing text (plain text) |
| `features` | The complete kenmerken table, grouped like on Funda: `{"Overdracht": {...}, "Bouw": {...}, "Oppervlakten en inhoud": {...}, "Indeling": {...}, "Energie": {...}, "Kadastrale gegevens": {...}, "Buitenruimte": {...}, "Parkeergelegenheid": {...}, "VvE checklist": {...}}` |
| `latitude`, `longitude` | Map coordinates |
| `constructionYear`, `propertySubtype`, `volumeM3`, `bathrooms`, `floors` | Bouwjaar, "Bovenwoning", "Eengezinswoning, 2-onder-1-kapwoning", inhoud, badkamers, woonlagen |
| `heating`, `hotWater`, `insulation`, `solarPanels`, `heatPump` | Energy details |
| `garden`, `gardenDetails`, `balcony`, `roofTerrace`, `parking`, `garage` | Outdoor space and parking |
| `vveContribution`, `vveContributionPerMonth`, `ownership`, `leaseholdFees` | VvE fee, ownership situation (volle eigendom / erfpacht) and leasehold charges |
| `deposit`, `rentalAgreement`, `serviceCostsPerMonth`, `furnished`, `upholstered` | Rental terms |
| `acceptance`, `listedSince`, `statusLabel`, `isSoldOrRented`, `isAuction`, `isMonument`, `specifics` | Aanvaarding, "Aangeboden sinds", transaction label and special flags |
| `photos`, `floorPlanUrls`, `floorPlanEmbedUrls`, `videoUrls`, `virtualTourUrls`, `brochureUrl` | High-resolution photos, floor plans (image and interactive), video streams, 360° tours and the PDF brochure |
| `viewCount`, `saveCount` | How often the listing was viewed and saved on Funda (when Funda shows it) |
| `neighbourhoodStats` | `{inhabitants, familiesWithChildrenPct, averageAskingPricePerSqm}` for the neighbourhood |
| `agent.phone`, `agent.website`, `agent.email`, `agent.address` | The agent office's public business contact details (fetched once per office) |

### How to scrape Funda listings

1. Open funda.nl, run the search you want (area, price, living area, property type, energy label, sort order) and copy the URL from the address bar into **Start URLs**. Or type an **Area** ("Amsterdam", "Den Haag", "1012", "utrecht/wittevrouwen") and pick koop or huur plus optional price, living area, bedrooms and property type filters.
2. Set **Max items** (cost cap). Optionally turn on **Include listing details**.
3. Click **Start**. Results appear in the **Dataset** tab; export as JSON, CSV or Excel, or read them through the API.

### Input example

```json
{
  "startUrls": [{ "url": "https://www.funda.nl/zoeken/huur?selected_area=[\"amsterdam\"]&price=\"1000-2000\"&object_type=[\"apartment\"]" }],
  "maxItems": 200,
  "includeDetails": true
}
```

or, by area:

```json
{
  "area": "Utrecht",
  "listingType": "koop",
  "minPrice": 200000,
  "maxPrice": 500000,
  "minArea": 60,
  "propertyTypes": ["house", "apartment"],
  "sort": "date_down",
  "maxItems": 100
}
```

### Output example

```json
{
  "id": "8140676",
  "tinyId": "44595039",
  "url": "https://www.funda.nl/detail/koop/amsterdam/appartement-binnenkant-46-a/44595039/",
  "title": "Binnenkant 46-A",
  "address": "Binnenkant 46-A, 1011 BP Amsterdam",
  "postcode": "1011 BP",
  "city": "Amsterdam",
  "neighbourhood": "Scheepvaarthuisbuurt",
  "district": "Nieuwmarkt/Lastage",
  "province": "Noord-Holland",
  "listingType": "koop",
  "price": 1185000,
  "priceCurrency": "EUR",
  "priceType": "k.k.",
  "pricePerSqm": 7054,
  "livingAreaSqm": 168,
  "plotAreaSqm": null,
  "rooms": 4,
  "bedrooms": 3,
  "propertyType": "apartment",
  "energyLabel": "B",
  "status": "available",
  "publishedAt": "2026-09-09T05:00:03+02:00",
  "isNewBuild": false,
  "promoText": "Charmant en ruim benedenhuis van 168m2 op eigen grond aan de gracht!",
  "agent": { "id": 24162, "name": "Hoen Makelaars", "url": "https://www.funda.nl/makelaar/24162-hoen-makelaars/", "association": "NVM" },
  "images": ["https://cloud.funda.nl/tiara-media/7f6b464f-caf4-4fd3-89f5-117001d169c6/c66e480f-e0b8-4156-8ccb-71819666ebba"],
  "imageCount": 34,
  "latitude": 52.37274,
  "longitude": 4.9060144,
  "constructionYear": 1748,
  "bathrooms": 1,
  "heating": "Cv-ketel",
  "insulation": "Dubbel glas",
  "vveContribution": "€ 300,00 per maand",
  "ownership": "Volle eigendom",
  "features": { "Overdracht": { "Vraagprijs": "€ 1.185.000 kosten koper", "Status": "Beschikbaar" }, "Bouw": { "Bouwjaar": "1748" } }
}
```

### How many listings can I get from one search?

Funda shows 15 listings per page and serves at most 666 pages, so one search yields at most about 10,000 listings even if it says "92,000 results". Amsterdam for sale (~6,000) fits in one search; for the whole country split by province, city or price band and add each URL to **Start URLs**. Duplicates across searches are removed automatically.

### Does it scrape rentals and new builds?

Yes. Use a `/zoeken/huur` URL or set **Listing type** to huur; rentals come with `priceType: "per maand"` and, with details, the deposit, rental agreement, service costs and furnished flags. New builds are included in koop searches and flagged with `isNewBuild`; filter to them with `construction_type=["newly_built"]` in the URL or **New builds only**. Funda's new-build *project* overview pages (`type=["project"]`) are rendered in the browser and are not supported; the individual homes in those projects are.

### Can I get the construction year, coordinates and floor plans?

Turn on **Include listing details**. Each listing page is opened once to add the description, the full kenmerken table, construction year, coordinates, floor plans, videos, 360° tours, brochure, VvE contribution, ownership/leasehold, garden/balcony/parking and view counts, plus the agent office's business phone, website and email (fetched once per office). Without details you still get price, address, areas, rooms, energy label, status, listing date, agent office and photos from the search page. Details cost a little extra per listing (see the Pricing tab).

### Does it work without login or cookies?

Yes. Everything comes from public search and listing pages; no Funda account is used. Funda is protected by Akamai Bot Manager; the default proxy setting (Apify residential proxies) is the reliable choice. Datacenter proxies worked in testing but can be blocked at volume: if a run shows 403 responses in the log, keep or switch to the RESIDENTIAL group.

### Pricing

Pay per result: a small fee per listing scraped, plus a small extra fee per listing page opened when details are on. No subscription; Apify's free plan is enough to try it.

### Integrations and API

Use the run in Zapier, Make, n8n, Google Sheets, or call it from Python/Node with the Apify client. See the **API** tab for ready-made snippets. Schedule it daily to monitor new listings, price changes and status changes (under offer, sold) in an area.

### Is it legal to scrape Funda?

This Actor collects only publicly available listing data (properties, prices and the advertising estate agent office's business details). It does not collect any data about private individuals; the names of individual agents that Funda shows in "personal contact" blocks are deliberately dropped. You are responsible for how you use the data and for complying with Funda's terms and applicable law.

### Support

Found a bug or need a field added? Open an issue in the **Issues** tab; it is usually answered within a day.

# Actor input Schema

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

Funda search result pages to scrape, with any filters and sort applied in the browser, e.g. https://www.funda.nl/zoeken/koop?selected\_area=\["amsterdam"] or https://www.funda.nl/zoeken/huur?selected\_area=\["utrecht"]\&price="1000-2000". Koop (for sale) and huur (for rent) searches work, including new-build filters (construction\_type=\["newly\_built"]). A single listing URL (…/detail/koop/…/12345678/) is also accepted and returns that one listing with full details. Leave empty if you use Area instead.

## `area` (type: `string`):

Alternative to Start URLs: a city, municipality, neighbourhood or postcode (4 digits or full), e.g. "Amsterdam", "Den Haag", "Utrecht, Amersfoort", "1012", "nl" for the whole country. Funda's own area slugs (e.g. "amsterdam/jordaan") also work.

## `listingType` (type: `string`):

Used with Area: homes for sale (koop) or for rent (huur).

## `minPrice` (type: `integer`):

Used with Area. Asking price, or monthly rent for rentals.

## `maxPrice` (type: `integer`):

Used with Area. Asking price, or monthly rent for rentals.

## `minArea` (type: `integer`):

Used with Area. Minimum living area in square metres.

## `minBedrooms` (type: `integer`):

Used with Area.

## `propertyTypes` (type: `array`):

Used with Area. Leave empty for all types.

## `newBuildsOnly` (type: `boolean`):

Used with Area: only newly built homes (nieuwbouw). Note: Funda's new-build *project* pages are rendered client-side and are not covered; individual new-build homes are.

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

Used with Area. Funda's default is relevance.

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

Stop after this many listings in total (across all start URLs). Keeps cost predictable. Funda shows 15 listings per page and serves at most 666 pages (about 10,000 listings) per search, so split large areas by price band or district to get more.

## `includeDetails` (type: `boolean`):

Also open every listing page to get the full description, the complete kenmerken table (construction year, volume, bathrooms, floors, heating, insulation, VvE contribution, ownership/leasehold, deposit and rental terms), coordinates, floor plans, videos, 360° tours, brochure, garden/balcony/parking flags, view and save counts, and the agent office's business phone, website and email. One extra request per listing plus one per distinct agent office; charged extra per listing (see pricing).

## `proxyConfiguration` (type: `object`):

Apify Proxy is recommended. Funda sits behind Akamai Bot Manager; datacenter IPs worked in testing but residential is the safer default for larger runs. If you see 403s in the run log, switch to (or keep) the RESIDENTIAL group.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.funda.nl/zoeken/koop?selected_area=%5B%22amsterdam%22%5D"
    }
  ],
  "listingType": "koop",
  "propertyTypes": [],
  "newBuildsOnly": false,
  "sort": "",
  "maxItems": 100,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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=%5B%22amsterdam%22%5D"
        }
    ],
    "area": "",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/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=%5B%22amsterdam%22%5D" }],
    "area": "",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/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=%5B%22amsterdam%22%5D"
    }
  ],
  "area": "",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call tortuga/funda-scraper --silent --output-dataset

```

## MCP server setup

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