# European Property Search - Search 24 EU Property Portals (`studio-amba/european-property-search`) Actor

Search 24 European real-estate portals in a single run. Unified feed with EUR-normalized price, surface and price-per-m2. No login required.

- **URL**: https://apify.com/studio-amba/european-property-search.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 result scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## European Property Search

Search twenty-four European real-estate portals in a single run. This actor queries each portal in parallel, normalizes every listing to a common schema, converts prices to EUR using live ECB rates, computes price-per-m2, and removes duplicates. One search across most of the European property market.

No login. No cookies. No account.

### What it does

- Searches 24 European property portals at once: 4zida (RS), Aruodas (LT), athome (LU), Boliga (DK), Daft (IE), Fotocasa (ES), Gratka (PL), Idealista (ES), Immobiliare (IT), Immoscoop (BE), ImmoScout24 (DE), Immoweb (BE), Immowelt (DE), imot.bg (BG), kv.ee (EE), Logic-Immo (FR), Nepremicnine (SI), Oikotie (FI), Otodom (PL), Pararius (NL), Rightmove (GB), Sreality (CZ), Willhaben (AT), Zimmo (BE).
- Normalizes every listing to a common schema (title, listing type, property type, price, surface, bedrooms, location).
- Converts prices to EUR with live European Central Bank rates and computes price-per-m2 where surface is available.
- Deduplicates by listing URL and sorts results by EUR price, cheapest first.

### How to scrape European real estate data

1. Enter what you are looking for in the **Search Query** field, for example `apartment`, `house`, or a city name.
2. Optionally restrict to certain countries with the **Countries** field (for example `["ES", "IT"]`). Leave it empty to query every portal.
3. Set **Max Items Per Portal** to control how many listings are pulled from each portal.
4. Run the actor. Each portal is queried in parallel, listings are normalized, priced in EUR, and deduplicated.
5. Open the dataset. Each row is one unique property listing with the portal it came from.

### Input

| Field | Type | Description |
|-------|------|-------------|
| `searchQuery` | string | What to search for. Defaults to `apartment`. |
| `countries` | array | Optional country filter. Empty means all portals. |
| `maxItemsPerPortal` | integer | Max listings per portal (1–200, default 20). |
| `timeoutPerPortalSecs` | integer | Max seconds to wait per portal (30–600, default 120). |
| `proxyConfiguration` | object | Proxy settings passed to the underlying scrapers. Residential recommended. |

#### Example input

```json
{
    "searchQuery": "apartment",
    "countries": ["ES", "IT", "PT"],
    "maxItemsPerPortal": 25,
    "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

### Output

Each item in the dataset is one unique property listing:

```json
{
    "title": "Bright 2-bedroom apartment near the center",
    "listingType": "sale",
    "propertyType": "apartment",
    "price": 285000,
    "currency": "EUR",
    "priceEur": 285000,
    "surface": 78,
    "pricePerSqmEur": 3654,
    "bedrooms": 2,
    "location": "Valencia",
    "country": "ES",
    "url": "https://...",
    "source": "Idealista",
    "imageUrl": "https://...",
    "scrapedAt": "2026-06-15T18:00:00.000Z"
}
```

| Field | Description |
|-------|-------------|
| `title` | Listing title. |
| `listingType` | Sale, rent or auction, if available. |
| `propertyType` | Apartment, house, studio, etc., if available. |
| `price` / `currency` | Price in the portal's native currency. |
| `priceEur` | Price converted to EUR with live ECB rates. |
| `surface` | Living area in m2, if available. |
| `pricePerSqmEur` | EUR price divided by surface, when both are known. |
| `bedrooms` | Number of bedrooms or rooms, if available. |
| `location` | City or region, if available. |
| `country` | ISO country code of the source portal. |
| `url` | Link to the original listing. |
| `source` | Name of the portal the listing came from. |
| `scrapedAt` | ISO 8601 timestamp. |

A final `__SUMMARY__` item lists which portals answered, which failed, the total unique listings, and how many duplicates were removed.

### Currency conversion and price-per-m2

Prices arrive in each portal's local currency. The actor fetches live EUR reference rates from the European Central Bank at the start of every run and converts each price to EUR. Where a listing exposes its surface area, price-per-m2 is computed in EUR so listings of different sizes and currencies can be compared on a like-for-like basis. Native price and currency are always preserved.

### Use cases

- Cross-border property-price research and relocation planning.
- Price-per-m2 benchmarking across European cities and countries.
- Feeding a real-estate dashboard with EUR-normalized listings.
- Market analysis of supply and pricing for a property type across Europe.

### Notes

- This is a meta-actor. It orchestrates our individual national property-portal scrapers and runs them in parallel, so a single run can cover most of Europe at once.
- Field coverage depends on each portal exposing surface, bedrooms and the rest; not every portal provides every field.
- Coverage for a query depends on each underlying portal returning results. A broad term like `apartment` matches more portals than a hyper-specific local query.
- Use residential proxies for the most reliable results.

# Actor input Schema

## `searchQuery` (type: `string`):

Location (city or region) passed to every selected portal. Leave empty to use each portal's default city (recommended when searching multiple countries — a city name only matches its own country).

## `countries` (type: `array`):

Filter which countries to include. Leave empty for all (RS, LT, LU, DK, IE, ES, PL, IT, BE, DE, BG, EE, FR, SI, FI, NL, GB, CZ, AT).

## `maxItemsPerPortal` (type: `integer`):

Maximum items to fetch from each portal.

## `timeoutPerPortalSecs` (type: `integer`):

Maximum seconds to wait for each portal scraper.

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

Proxy settings passed to the underlying scrapers. Residential recommended.

## Actor input object example

```json
{
  "countries": [
    "IE",
    "NL",
    "DK"
  ],
  "maxItemsPerPortal": 5,
  "timeoutPerPortalSecs": 120,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "countries": [
        "IE",
        "NL",
        "DK"
    ],
    "maxItemsPerPortal": 5,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/european-property-search").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 = {
    "countries": [
        "IE",
        "NL",
        "DK",
    ],
    "maxItemsPerPortal": 5,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/european-property-search").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "countries": [
    "IE",
    "NL",
    "DK"
  ],
  "maxItemsPerPortal": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call studio-amba/european-property-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=studio-amba/european-property-search",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/TYRaPAMkz190rAEpL/builds/mbL7j8rXNgAid6sMD/openapi.json
