# EU Real Estate Scraper: Spain, Italy, Portugal, France (`bonpleincapital/eu-real-estate-scraper`) Actor

Scrape property listings for sale or rent in Spain, Italy, Portugal and France, one city per country. Price, area, price per m², rooms, photo.

License: personal use only; resale and redistribution prohibited.
Created with the help of artificial intelligence.

- **URL**: https://apify.com/bonpleincapital/eu-real-estate-scraper.md
- **Developed by:** [Bon Plein Capital](https://apify.com/bonpleincapital) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.96 / 1,000 listing 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/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

## European Real Estate Listings Scraper

**European Real Estate Listings Scraper** is a real estate listings scraper for Spain, Italy, Portugal and France, in the spirit of an Idealista scraper but built on portals whose public pages can be read normally. Give it one or several countries, a city and "buy" or "rent", and it returns clean, structured property listings (price, area, rooms, price per square metre, location, photo, link) that you can download as JSON, CSV or Excel, or pull through the Apify API. It is made for investors, agents, analysts and proptech teams who want to compare asking prices across Southern and Western Europe without copying ads by hand.

### What can this real estate listings scraper do?

- Search public listings for sale or for rent in four countries: **France** (Bien'ici), **Italy** (Immobiliare.it), **Portugal** (Imovirtual) and **Spain** (Pisos.com).
- Search several countries in one run with the `countries` list. The maximum number of listings is shared between them.
- Return one flat record per listing: portal, URL, title, property type, price, currency, area in m², **price per m²**, rooms, bedrooms, bathrooms, city, district, postal code, coordinates (when the portal publishes them), main photo, a short description and publication date.
- Accept your own public search-page URLs from the four supported portals.
- Use defensive parsers: a missing field is left out of the record, a changed page layout falls back to schema.org data when available, and one blocked portal does not stop the others.
- Run on a schedule to monitor asking prices, build market reports, feed a spreadsheet or a BI dashboard, and work with Make, Zapier, n8n and Google Sheets.

Idealista itself is not scraped: it protects its pages with anti-bot systems and this Actor never bypasses captchas or protections. If you give an Idealista URL, it is skipped with a message in the log.

### How to use it

1. Click **Try for free** and open the **Input** tab.
2. Enter one or more **countries** (`fr`, `it`, `pt`, `es`), a **city** (for example Paris, Roma, Lisboa, Madrid) and pick **For sale** or **For rent**.
3. Set the **maximum number of listings**. Keep the prefilled 5 to try it for a few cents.
4. Click **Start**, then download the dataset from the **Output** tab as JSON, CSV, Excel or HTML, or call it from the API.

To search a different city in each country, fill `cities`, for example `{"it": "Milano", "es": "Barcelona", "fr": "Lyon"}`. Without it, the `location` city applies to the first country in the list and the other countries use their capital (Roma, Lisboa, Madrid, Paris). You can also paste your own search URLs. If a portal rejects the request, add an Apify Proxy in the **Proxy configuration** field and run again.

### Input

```json
{
  "countries": ["fr"],
  "location": "Paris",
  "operation": "buy",
  "maxItems": 5
}
```

Optional fields: `cities` (a city per country), `startUrls` (public search-page URLs from bienici.com, immobiliare.it, imovirtual.com or pisos.com) and `proxyConfiguration`.

### Output

Each listing is one dataset item. Example:

```json
{
  "portal": "bienici",
  "country": "FR",
  "operation": "buy",
  "id": "ag123456",
  "url": "https://www.bienici.com/annonce/ag123456",
  "title": "Appartement 3 pieces",
  "propertyType": "flat",
  "price": 450000,
  "currency": "EUR",
  "pricePerSqm": 7500,
  "areaSqm": 60,
  "rooms": 3,
  "bedrooms": 2,
  "city": "Paris",
  "postalCode": "75011",
  "imageUrl": "https://example.com/photo.jpg",
  "scrapedAt": "2026-10-15T09:00:00+00:00"
}
```

### How much does it cost?

This Actor uses **pay per event** pricing: you pay one `result` event for each listing returned, and nothing for listings that are not produced. 1,000 listings cost the price of 1,000 `result` events shown in the **Pricing** tab. Apify's free plan gives you monthly credits to test the Actor before you pay.

### FAQ

#### Is it legal to use this real estate listings scraper? What about GDPR?

The Actor reads only public search-result data: it never logs in, never reads private accounts and never bypasses captchas. Listings can sometimes contain personal data (for instance a private seller's name or a precise address). If you store or process such data, you are responsible for complying with the GDPR (EU General Data Protection Regulation), for having a lawful basis, and for respecting each portal's terms of use. This Actor does not collect seller phone numbers or e-mail addresses.

#### Why is Idealista not in the list?

Idealista uses strong anti-bot protection. Rather than evade it, this Actor covers portals whose public pages can be read normally, in the same four countries.

#### Why did I get fewer results than requested?

The search may simply have fewer listings, or the portal may have blocked the request. Try another location, or enable Apify Proxy.

#### What if something does not work?

Portals change their pages from time to time. Open an issue in the **Issues** tab with your input and the run link, and it will be looked at as fast as possible.

#### Can I use it through the API?

Yes. Every run can be started and read through the Apify API and its Python and JavaScript clients.

***

Created with the help of artificial intelligence.

# Changelog

This Actor's version history is a separate document: https://apify.com/bonpleincapital/eu-real-estate-scraper/changelog.md

# Actor input Schema

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

Countries to search: fr (Bien'ici), it (Immobiliare.it), pt (Imovirtual), es (Pisos.com). Max listings are shared between the countries.

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

City or area name, for example Paris, Roma, Lisboa or Madrid. Applied to the first country; other countries use their capital.

## `operation` (type: `string`):

Search properties for sale or for rent.

## `cities` (type: `object`):

Optional. A city for each country, for example {"it": "Milano", "es": "Barcelona"}. Overrides the single city field for that country.

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

Optional. Public search result URLs from bienici.com, immobiliare.it, imovirtual.com or pisos.com. When set, countries and city are ignored.

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

Stop after this many listings in total. Keep it low to test the Actor cheaply.

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

Optional Apify Proxy settings, useful if a portal rejects datacenter IPs.

## Actor input object example

```json
{
  "countries": [
    "fr"
  ],
  "location": "Paris",
  "operation": "buy",
  "cities": {
    "it": "Milano",
    "es": "Barcelona"
  },
  "maxItems": 5
}
```

# Actor output Schema

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

One dataset item per result, shown in the Overview view.

# 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": [
        "fr"
    ],
    "location": "Paris",
    "operation": "buy",
    "maxItems": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("bonpleincapital/eu-real-estate-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 = {
    "countries": ["fr"],
    "location": "Paris",
    "operation": "buy",
    "maxItems": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("bonpleincapital/eu-real-estate-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 '{
  "countries": [
    "fr"
  ],
  "location": "Paris",
  "operation": "buy",
  "maxItems": 5
}' |
apify call bonpleincapital/eu-real-estate-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bonpleincapital/eu-real-estate-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/CDhbk05U5EFASAEri/builds/1drenUKZut8q3Wko4/openapi.json
