# Idealista Alternative Scraper: Spain & Portugal (`bonpleincapital/idealista-keyword-listings`) Actor

Idealista alternative: Spain and Portugal listings from Pisos.com and Imovirtual (not Idealista, no Italy yet). Keyword, price and area filters, price per m2.

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

- **URL**: https://apify.com/bonpleincapital/idealista-keyword-listings.md
- **Developed by:** [Bon Plein Capital](https://apify.com/bonpleincapital) (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 $0.36 / 1,000 property listings

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

## Idealista Alternative: Property Keyword Scraper (Spain & Portugal)

This **Idealista-keyword property listings scraper** is an Idealista alternative for people who need property listings from Spain and Portugal filtered by keyword, with the **price per m2** calculated for every listing that publishes a price and an area. Type words such as `terraza`, `piscina`, `ascensor` or `varanda`, pick a city, and get a clean table of matching flats and houses that you can download as JSON, CSV or Excel, or read through the Apify API. Be aware that it reads Pisos.com (Spain) and Imovirtual (Portugal), not Idealista itself, and it costs less than the big Idealista scrapers.

### What can this Actor do?

- Search public property listings for sale or for rent in Spanish and Portuguese cities.
- Keep only the listings whose public text contains at least one of your keywords (accents are ignored, so `atico` finds `ático`). The `matchedKeywords` field tells you which ones matched.
- Calculate `pricePerSqm` (price divided by area) for every listing that publishes both, and filter on a maximum price per m2 to spot bargains.
- Filter by minimum and maximum price and by minimum area. Skipped listings are never billed.
- Return price, area, rooms, bedrooms, city, district, features, photo, agency name and the link to the listing.
- Free plan: Apify's monthly free credits cover thousands of listings at this price.

Italy is not supported in this version: the Italian portals block datacenter servers (HTTP 403).

### How to use it

1. Click **Try for free** and open the **Input** tab.
2. Choose the countries (`es`, `pt`), a city per country, and your keywords. Keep the prefilled values to see an example.
3. Set the maximum number of listings and click **Start**.
4. Download the results from the **Output** tab (Overview view), or call the Actor from the API, Make, Zapier or n8n.

Tip: with keywords set, the Actor reads more result pages to find enough matches, so a rare keyword can take longer. Runs stop gracefully after about three and a half minutes.

### Input

```json
{
  "countries": ["es"],
  "citiesByCountry": {"es": "Madrid"},
  "keywords": ["terraza"],
  "operation": "buy",
  "maxPricePerSqm": 6000,
  "maxItems": 5
}
```

Other fields: `minPrice`, `maxPrice`, `minAreaSqm`, `proxyConfiguration` (optional, off by default).

### Output

```json
{
  "portal": "pisos",
  "country": "ES",
  "operation": "buy",
  "title": "Piso en Chamberí",
  "price": 450000,
  "currency": "EUR",
  "areaSqm": 90,
  "pricePerSqm": 5000,
  "matchedKeywords": ["terraza"],
  "bedrooms": 2,
  "city": "Madrid",
  "url": "https://www.pisos.com/comprar/piso-chamberi28010-12345678/"
}
```

Fields that a listing does not publish are left out instead of being invented. `pricePerSqm` is present only when the listing publishes both price and area; with `maxPricePerSqm` set, every returned listing has it.

### How much does it cost?

This Actor uses **pay per event** pricing: you pay one `result` event per listing returned, and nothing for listings that are filtered out. The price is **$0.60 per 1,000 results** (about $0.0006 per listing), so 1,000 listings cost $0.60 and 10,000 cost $6.00, plus Apify platform usage if any. Start with `maxItems` at 5 to test it for a few cents.

### FAQ

#### Does it scrape Idealista?

No. Idealista protects its pages with anti-bot systems and this Actor does not bypass them. It gives you comparable data from Pisos.com and Imovirtual.

#### Is it legal to use this Actor?

The Actor only reads public listing pages, with no login. You remain responsible for using the data lawfully. Listings may contain business contact names (agencies); if you process personal data, follow the GDPR (RGPD).

#### Why did my run return no listing?

Your keywords may be too strict for the chosen city, or the portal may have blocked the request or changed its layout. Try fewer keywords, another city, or enable the proxy option.

#### 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/idealista-keyword-listings/changelog.md

# Actor input Schema

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

es = Spain (Pisos.com), pt = Portugal (Imovirtual). Max listings are shared between the countries.

## `citiesByCountry` (type: `object`):

Optional. One city per country code, for example {"es": "Barcelona", "pt": "Porto"}. Defaults: Madrid and Lisboa.

## `keywords` (type: `array`):

Keep listings whose public text contains at least one keyword (accents ignored), for example terraza, ascensor, piscina, varanda, T2. Leave empty to keep all listings.

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

Search properties for sale or for rent.

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

Optional. Skip cheaper listings (monthly rent when renting). Skipped listings are not billed.

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

Optional. Skip more expensive listings. Skipped listings are not billed.

## `minAreaSqm` (type: `integer`):

Optional. Skip smaller listings and listings without a published area.

## `maxPricePerSqm` (type: `integer`):

Optional. Keep only listings whose price per m2 is at or below this value (find bargains).

## `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. Off by default: the portals usually work better without it.

## Actor input object example

```json
{
  "countries": [
    "es",
    "pt"
  ],
  "citiesByCountry": {
    "es": "Barcelona",
    "pt": "Porto"
  },
  "keywords": [
    "terraza",
    "piscina"
  ],
  "operation": "buy",
  "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": [
        "es"
    ],
    "citiesByCountry": {
        "es": "Madrid"
    },
    "keywords": [
        "piso"
    ],
    "operation": "buy",
    "maxItems": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("bonpleincapital/idealista-keyword-listings").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": ["es"],
    "citiesByCountry": { "es": "Madrid" },
    "keywords": ["piso"],
    "operation": "buy",
    "maxItems": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("bonpleincapital/idealista-keyword-listings").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": [
    "es"
  ],
  "citiesByCountry": {
    "es": "Madrid"
  },
  "keywords": [
    "piso"
  ],
  "operation": "buy",
  "maxItems": 5
}' |
apify call bonpleincapital/idealista-keyword-listings --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bonpleincapital/idealista-keyword-listings"
        }
    }
}
```

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/pr3FWfydrxZo5hduy/builds/i4CmcmrFCTwPnAOef/openapi.json
