# Idealista Scraper - Spain, Italy, Portugal Listings (`nice_dev/idealista-listings-scraper`) Actor

Scrape Idealista property listings in Spain, Italy and Portugal: price, size, rooms, GPS, photos, agency name and phone, price drops. Sale, rent and rooms. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/nice\_dev/idealista-listings-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** Real estate, Lead generation, MCP servers
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.25 / 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.
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

### 🏠 What is Idealista Scraper?

**Idealista Scraper** extracts **property listings from [idealista](https://www.idealista.com)** in **Spain, Italy and Portugal**: **price, size, bedrooms, GPS, photos, full description, the advertiser's name and phone number, price drops** and, on request, the full listing page, the agency's profile (year on idealista, listings, office, website) and its e-mail. Homes for sale or rent, new builds, rooms to share, holiday rentals, offices, shops, garages, land and buildings.

Type a **city** (`Madrid`, `Milano`, `Lisboa`), pick **sale or rent**, click **Start**, and download the listings in JSON, CSV or Excel. No login, nothing to set up, and it is **fast: about 1,000 listings a minute**.

### 📋 What data can you extract from idealista?

One item per listing, 105 fields:

| Category | What you get |
| --- | --- |
| 🏷️ **Listing** | title, link, idealista code, sale or rent, property type — `Piso en Calle de López de Hoyos, Castellana, Madrid` |
| 💰 **Price** | price, price per m², previous price, drop in € and %, date of the drop — `2,695,000 EUR`, `-2 %` |
| 📐 **Property** | size, bedrooms, bathrooms, floor, condition, lift, parking, terrace, pool, air conditioning, garden |
| 📍 **Location** | address, neighbourhood, district, city, province, GPS coordinates |
| 📷 **Photos and media** | photo links with the room of each photo, videos, 3D tours, floor plan |
| 📞 **Advertiser** | agency or private seller, contact name, **phone number** (`+34919381590`), agency page and logo |
| 🏷️ **Badges** | idealista labels (luxury, bright…), new build, new listing, paid highlights |
| 📄 **Listing page** (option) | every photo, energy certificate, community costs, built / usable area, year built, heating, orientation, last update, description in every language |
| 🏢 **Agency** (option) | **agency profile**: year it joined idealista, number of listings, description, cover photo, video, office address, GPS and phone, website — and the **e-mail** found on the agency website |

Every field, with an example, is listed in the **Output** section below.

Fields marked **(listing page)** are filled when **Open each listing page** (`includeDetails`) is on, those marked **(agency page)** when **Add the agency profile** (`includeAgencyProfile`) is on. Everything else — phone number included — comes with every listing.

### ✅ Why use Idealista Scraper?

- 🚀 **Fast**: about 1,000 listings a minute; with **Add the agency profile** and **Find agency e-mails**, about 200-400 a minute (with **Open each listing page**: about 40 listings a minute).
- 📞 **The advertiser's phone number comes with the search results**, at no extra cost (no listing page to open).
- 🧩 **Past the 2,500-listing limit of a search**: a bigger search is split by price ranges automatically, so a whole city can be read.
- 🎯 **60+ filters**: price, size, bedrooms, bathrooms, condition, floor, energy rating, lift, parking, terrace, pool, auctions, bank properties, tenanted or free, furnished, and every filter of rooms to share (gender, couples, pets, smokers…).
- 🌍 **Spain, Italy and Portugal** — search by city, keyword, agency, point and radius, map area, or listing codes.
- 🔔 **Monitoring built in**: tick **Only new listings**, schedule the Actor, and each run returns (and charges) only what it has never delivered before. **Price drops only** returns the listings whose price went down.
- 🔌 API, scheduling, integrations (Make, Zapier, n8n, Google Sheets…) and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape idealista

1. Create a free Apify account.
2. Open **Idealista Scraper**, choose the **Country**, **Operation** (sale or rent) and **Property type**, and type a **Location** (e.g. `Madrid`).
3. Or paste idealista search, listing or agency URLs into **Start URLs**, listing codes into **Listing IDs**, or agency names into **Agencies**.
4. Set **Max listings** (100 by default, 0 = no limit) — and **Max listings per search** when you run several searches — then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

### 💰 How much does it cost to scrape idealista?

This Actor uses **pay per event** pricing: **$0.25 per 1,000 listings**, phone numbers included — plus **$0.001 per run start**. Options are charged only when you tick them: **$0.25 per 1,000 listings** with **Open each listing page**, **$0.10 per 1,000 listings** that get their agency's profile (**Add the agency profile**; private sellers have none, so are not charged), and **$0.50 per 1,000 listings** whose agency e-mail is found (**Find agency e-mails**). Filters that idealista does not offer are applied by the Actor on every listing it reads: a listing you keep costs its normal price, a listing a filter drops costs **$0.29 per 1,000 listings dropped** by *Private advertisers only*, *With phone only*, *Price drops only* or *Exclude keywords*, and **$0.29 per 1,000 listing pages dropped** by *Updated after / before* — both $0.28 on Bronze, $0.27 on Silver and $0.26 on Gold. Example: 20,000 listings of a city ≈ $5; a daily monitor of 300 new listings ≈ $0.08 a day. Platform usage (compute, proxy) is included in the price.

### ⚙️ Input

```json
{
    "country": "es",
    "operation": "sale",
    "propertyType": "homes",
    "location": "Madrid",
    "maxItems": 200
}
```

Several cities, a cap per city, filters, only the listings not delivered before:

```json
{
    "country": "it",
    "operation": "rent",
    "propertyType": "homes",
    "locations": ["Milano", "Roma"],
    "maxItemsPerQuery": 500,
    "maxPrice": 1500,
    "bedrooms": ["2", "3"],
    "features": ["elevator", "terrace"],
    "onlyNew": true,
    "stateKey": "rent-milano-roma"
}
```

Or with your own URLs and codes:

```json
{
    "startUrls": [
        { "url": "https://www.idealista.com/venta-viviendas/madrid/chamberi/" },
        { "url": "https://www.idealista.com/inmueble/112272495/" }
    ],
    "listingIds": ["36890709"],
    "includeDetails": true
}
```

| Field | Notes |
| --- | --- |
| `country` | Spain (`es`), Italy (`it`) or Portugal (`pt`). |
| `operation` | `sale` or `rent`. |
| `propertyType` | `homes`, `newDevelopments`, `bedrooms` (rooms to share, rent only), `vacationRentals` (rent only), `offices`, `premises`, `transfers` (sale only), `garages`, `storageRooms`, `lands`, `buildings`. |
| `location`, `locations` | City, district, province or neighbourhood as typed on idealista, or an idealista location ID; the place found is written in the log. |
| `query`, `searchQueries` | Keywords searched in the listings (e.g. `ático terraza`), inside each location, or in the whole country without one. |
| `startUrls` | idealista search URLs (country, operation, type and location — or map area — are kept; set the filters with the fields below), listing URLs or agency URLs. |
| `listingIds` | idealista listing codes of the chosen country, fetched directly. |
| `agencies` | Every listing of these agencies: the name in their idealista page URL (`engel-volkers`) or the whole URL. |
| `latitude`, `longitude`, `radiusKm` | Search around a point, radius from 0.1 to 50 km. |
| `polygon` | Area drawn on the idealista map: the shape value of the map URL, or latitude,longitude points separated by semicolons. |
| `maxItems` | Stop after this many listings for the whole run (`0` = unlimited). |
| `maxItemsPerQuery` | Cap for EACH search (location × keyword, agency, URL…). 0 = no per-search cap. |
| `splitLargeSearches` | Split a search of more than 2,500 listings by price ranges to reach every listing (on by default). |
| `sortBy` | `relevance`, `newest`, `lastUpdated`, `priceLow`, `priceHigh`, `priceDrops`, `pricePerM2Low`, `pricePerM2High`, `sizeLarge`, `sizeSmall`. |
| `includeDetails` | Open each listing page: every photo, energy certificate, community costs, areas, year built, heating, orientation, agency address and website, last update. |
| `enrichEmails` | Read the agency's e-mail on its own website (needs `includeAgencyProfile` — fast, no listing page opened — or `includeDetails`). |
| `includeAgencyProfile` | Add the agency's idealista profile to each of its listings: year on idealista, listings count, description, cover photo, video, office address, GPS and phone, website. One request per agency, not per listing. |
| `language` | Language of the descriptions and labels (idealista's translation when the advertiser did not write it). |
| `minPrice`, `maxPrice`, `minSize`, `maxSize` | Price in euros (monthly rent for rentals), built area in m². |
| `bedrooms`, `bathrooms`, `condition`, `homeTypes`, `floors`, `energyRating` | Any of the chosen values; `4` bedrooms and `3` bathrooms mean "or more". |
| `publishedSince` | idealista's own date filter: `lastDay`, `last2Days`, `lastWeek`, `lastMonth`. idealista offers 48 hours on sales and 24 hours on rentals: `lastDay` on a sale searches 48 hours, `last2Days` on a rental searches the last week. |
| `features` | Keep only the listings with ALL of these: `elevator`, `airConditioning`, `parking`, `garden`, `swimmingPool`, `terrace`, `balcony`, `storeRoom`, `builtinWardrobes`, `exterior`, `accessible`, `luxury`, `seaViews`, `virtualTour`, `hasPlan`, `exteriorDomesticSpace`. |
| `auction` | `excludeAuctions` or `onlyAuctions` (sale). |
| `occupationStatus` | `free`, `tenanted`, `bareOwnership`, `illegallyOccupied` (sale). |
| `bankOffer` | Only the properties sold by banks. |
| `furnished` | Rent: `furnished` or `furnishedKitchen`. |
| `rentalTypes`, `petsAllowed` | Rent: `longTerm` and / or `seasonal`; pets accepted. |
| `roomGender` | Rooms to share: `female` or `male`. |
| `roomOccupation` | `students` or `workers`. |
| `roomBedType`, `roomFlatmates`, `roomRules`, `roomAvailableFrom`, `roomAvailableTo` | Bed, flatmates, house rules, move-in and move-out dates of a room to share. |
| `postedAfter`, `postedBefore` | Last-update date range read on the listing page (needs `includeDetails`): `2026-09-01`, or a period before now (`7 days`, `2 weeks`, `1 month`). |
| `excludeKeywords` | Drop the listings whose title or description contains one of these words (case and accents ignored). |
| `privateSellersOnly`, `requirePhone` | Drop the listings of agencies and developers; drop the listings without a phone number. |
| `onlyPriceDrops`, `minPriceDropPercent` | Only the listings whose price went down, and by at least this percentage. |
| `onlyNew`, `stateKey`, `resetState` | Monitoring: only the listings never delivered under this memory key; `resetState` forgets the memory. |
| Advanced | `proxyConfiguration` (Apify proxy by default, included in the price; the residential proxy is not available), `maxConcurrency`, `maxRequestRetries`, `debugLog`. |

### 📦 Output

A listing of a search (shortened: 105 fields in all, the ones of the listing page are `null` here):

```json
{
    "id": "112272495",
    "url": "https://www.idealista.com/inmueble/112272495/",
    "title": "Piso en Calle de López de Hoyos, Castellana, Madrid",
    "country": "es",
    "operation": "sale",
    "propertyType": "homes",
    "typology": "flat",
    "price": 2695000,
    "currency": "EUR",
    "pricePerM2": 9489,
    "previousPrice": 2750000,
    "priceDropPercent": 2,
    "size": 284,
    "rooms": 3,
    "bathrooms": 4,
    "floor": "2",
    "condition": "good",
    "hasLift": true,
    "labels": ["Lujo"],
    "address": "Piso en Calle de López de Hoyos, Castellana, Madrid",
    "neighborhood": "Castellana",
    "municipality": "Madrid",
    "latitude": 40.4379032,
    "longitude": -3.6883,
    "images": ["https://img4.idealista.com/s/v1/yLueJcFa…?Expires=1790292734&Signature=…&Key-Pair-Id=K20EOYVFELHOX5"],
    "imageTags": ["livingRoom"],
    "videos": ["https://st3v.idealista.com/fd/15/66/1470511706.mp4"],
    "virtualTours": ["https://my.matterport.com/show/?m=qQ4pCJDD6FA&lang=es"],
    "advertiserName": "Gilmar Barrio de Salamanca",
    "advertiserType": "professional",
    "phone": "+34919381590",
    "agencySlug": "gilmarsalamanca",
    "features": [],
    "descriptionLanguages": [],
    "search": "es · sale · homes · Madrid",
    "scrapedAt": "2026-09-24T08:00:00.000Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### All 105 fields

| Fields | What you get |
| --- | --- |
| `id`, `url`, `title`, `country`, `operation`, `propertyType`, `typology`, `subTypology` | **Listing** — `112272495`, web link, title, `es`, `sale`, `homes`, `flat`, `independantHouse` |
| `price`, `currency`, `pricePerM2`, `previousPrice`, `priceDropValue`, `priceDropPercent`, `priceDropDate` | **Price** — sale price or monthly rent, `EUR`, €/m², price before the last drop, drop in € and %, ISO date |
| `size`, `rooms`, `bathrooms`, `floor`, `condition` | **Property** — m², bedrooms, bathrooms, `2` / `bj` (ground), `good` / `renew` / `newdevelopment` |
| `hasLift`, `isExterior`, `hasParkingSpace`, `parkingIncludedInPrice`, `parkingPrice`, `hasAirConditioning`, `hasSwimmingPool`, `hasTerrace`, `hasGarden`, `hasBoxRoom` | **Property** — `true` / `false` / `null` |
| `labels`, `isNewDevelopment`, `isNewListing`, `isTopHighlight`, `isVisualHighlight`, `isTopPlus`, `isUrgent` | **Badges** — idealista labels, new build, new on idealista, paid highlights |
| `address`, `addressVisible`, `neighborhood`, `district`, `municipality`, `province`, `locationId`, `latitude`, `longitude` | **Location** — the line idealista shows on the results page (`Piso en Calle de Goya, Recoletos, Madrid`: type, street when shown, area, city), whether the exact address is shown, idealista location ID, GPS |
| `description`, `highlightPhrase` | full description, the advertiser's highlight phrase |
| `thumbnail`, `images`, `imageTags`, `imageCount`, `videos`, `virtualTours`, `hasVideo`, `has3DTour`, `has360`, `hasPlan`, `hasHomeStaging` | **Photos and media** — photo links and the room of each (`livingRoom`, `kitchen`…), videos, 3D tours |
| `advertiserName`, `contactName`, `advertiserType`, `phone`, `phoneFormatted`, `agencySlug`, `agencyUrl`, `agencyLogo`, `externalReference` | **Advertiser** — name, contact, `professional` / `private`, `+34919381590`, `919 38 15 90`, agency page, logo, the advertiser's reference |
| `updatedAt`, `street`, `communityCosts`, `energyCertificate`, `energyConsumption`, `emissionsRating`, `furnished` | **Listing page** — last update (ISO), street alone (`Calle de Goya, 135`), monthly community costs, energy rating, kWh/m² year, emissions, furnishing |
| `builtArea`, `usableArea`, `plotArea`, `isPenthouse`, `isDuplex`, `isStudio`, `isTopFloor`, `yearBuilt`, `heating`, `orientation`, `features`, `descriptionLanguages` | **Listing page** — m², flags, `1950`, `Central heating: gas` (or `No heating`), `east, west`, every feature line, languages of the description |
| `agencyAddress`, `agencyPostalCode`, `agencyCity`, `agencyWebsite`, `agencyId`, `agencyPhrase`, `allowsCounterOffers`, `allowsRemoteVisit` | **Agency** (listing or agency page) — office address, postal code, city, website, idealista agency number, slogan, counter-offers, remote visits (listing page) |
| `agencySinceYear`, `agencyListingsCount`, `agencyCoverImage`, `agencyVideo`, `agencyPhone`, `agencyLatitude`, `agencyLongitude` | **Agency** (agency page) — year it joined idealista (`2001`), listings on idealista (`47`), cover photo, video, office phone (`+34919382902`), office GPS |
| `email` | **Agency** — e-mail found on the agency website (`enrichEmails`) |
| `search`, `scrapedAt` | the search that found the listing, ISO timestamp |

### 💡 Tips

#### How to get more results

Set `maxItems` to `0` and keep **Split large searches** on: a search of more than 2,500 listings (idealista's own limit per search) is read by price ranges, so a whole city comes out. Several cities or districts in `locations` also widen the run.

#### How to reduce costs

The price is per listing, so the levers are `maxItems`, `maxItemsPerQuery`, the filters (a filtered-out listing is not saved and costs only the filter fee, see above) and `onlyNew` for recurring runs (you never pay twice for the same listing). Leave **Open each listing page** off unless you need its fields: the search already gives the price, the GPS, the description and the phone number.

#### Several searches in one run

Fill `locations` and / or `searchQueries`: the Actor runs one search per location × keyword (up to 500 per run), plus one per agency, point, area or search URL — with no location, each of those is searched once per keyword (500 at most) instead. A listing found by several searches is saved — and charged — once. Set `maxItemsPerQuery` to give every search its own cap: without it the first searches can use up the whole `maxItems` budget.

#### Monitoring: only the new listings

Tick **Only new listings** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the listings already delivered: they are not saved and not charged. The memory lives in a named key-value store of your account (`idealista-listings-scraper-seen`, up to 150,000 listings per key) and is only updated with listings that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey`, and tick `resetState` once to start over. Searches are then sorted by newest (unless you pick another **Sort by**), and a search stops once it meets 250 listings in a row you already have (paid listings pinned at the top are not counted). Add **Price drops only** to follow the price cuts.

#### Filter by date

`publishedSince` is idealista's own filter (published or reduced in the last day, 2 days, week or month) and works on every run. `postedAfter` and `postedBefore` read the last update of each listing on its listing page, so they need **Open each listing page**: a date (`2026-09-01`, the whole day is included, Madrid time) or a period before now (`7 days`, `2 weeks`, `1 month`). Filtered-out listings are not saved and do not count in `maxItems`; each listing page they drop costs the filter fee (see Pricing).

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per idealista property listing. Actor id: `nice_dev/idealista-listings-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/idealista-listings-scraper`.

Smallest input, for a cheap first call:

```json
{
    "country": "es",
    "operation": "sale",
    "propertyType": "homes",
    "location": "Madrid",
    "maxItems": 10
}
```

Key output fields: `url`, `title`, `price`, `currency`, `size`, `rooms`, `address`, `phone`.

Cost: $0.25 per 1,000 listings plus $0.001 per run start; the options (listing page, agency profile, agency e-mail) and the filters cost extra, see the pricing section above. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape idealista?

The Actor only reads what idealista shows publicly to any anonymous visitor. It logs in to nothing and solves no captcha. Results contain personal data — the name and phone number of the advertisers, private sellers included, and with **Find agency e-mails** the business addresses published on the agencies' own websites — which is protected by GDPR: you need a lawful basis before using it, and rules for contacting people differ by country. You are responsible for using the data in compliance with idealista's Terms of Use and applicable law. This Actor is not affiliated with idealista.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request the site turns away is retried at once on a new proxy session (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds).

#### Is the data safe to open in Excel or to show on a web page?

Every phone number starts with `+` (international format): import the `phone` column as text in Excel or Google Sheets, or it may be read as a number. Titles and descriptions are the advertisers' own words, copied as they are: a text can begin with `-`, `+`, `=` or `@`, which a spreadsheet may read as a formula. Every URL field holds an http(s) link or `null`. On a web page, escape every field like any text written by a stranger.

#### Known limitations

- idealista shows at most 2,500 listings per search: with **Split large searches** off, a bigger search stops there.
- A search of more than 2,500 listings is read by price ranges: with a price sort (`priceLow`, `priceHigh`) **Max listings** still gives the cheapest (or dearest) listings of the whole search; with any other sort (newest, size…) it gives listings sorted inside each price range, not the first ones of the whole search.
- The filters written in the path of a pasted search URL are not read: set them with the filter fields.
- Photo links are signed by idealista and stop working 24 hours after the run: download the photos you need before.
- idealista gives no first-publication date, only the last update (on the listing page).
- `onlyNew` remembers listing codes, not their content: a listing whose price changed is not returned again (use `onlyPriceDrops` on a separate run for that).

**A run the platform stops without warning** (out of memory, run timeout)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the listings already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved once a minute: resurrect the stopped run and the listings it had saved meanwhile join the memory; leave it stopped for good, and the next run may return up to a minute of them once more.

#### Something doesn't work?

The last line of the log counts the listings saved, filtered out and no longer on idealista (removed while the run was reading them), and the requests that failed after every retry. Those requests and the removed listings are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause. A run that saved some listings but lost at least as many requests as it read fails too ("Most requests failed…"), so that a block after the first page never passes for a finished run: the listings it kept stay in the dataset.

If idealista changes its pages, you are told instead of paying for blank rows. If the first 20 listings read all lack their title, price, GPS, description, photos or type of advertiser (or the phone of every agency) — or, with **Open each listing page**, their last update, energy certificate or feature lines — the run saves nothing more, stops and fails, and its last message names the missing field: at most those first listings are charged.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which searches failed and why.

# Actor input Schema

## `country` (type: `string`):

Idealista site to search: Spain (idealista.com), Italy (idealista.it) or Portugal (idealista.pt). Pasted URLs keep their own country.

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

For sale or for rent.

## `propertyType` (type: `string`):

**Rooms to share** and **Holiday rentals** exist for rent only, **Businesses for transfer** for sale only.

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

City, district, province or neighbourhood as typed on idealista (e.g. `Madrid`, `Milano`, `Lisboa`), or an idealista location ID (`0-EU-ES-28-07-001-079`). The best match of the site's location search is used and written in the log.

## `locations` (type: `array`):

Several locations in one run (same country): one search per location, times each keyword below (locations × keywords: max 500). Added to **Location**; listings found by several searches are saved once.

## `query` (type: `string`):

Free text searched by idealista in the listings (e.g. `ático terraza`). With a location: keyword inside that location. Without one: keyword inside each search URL, agency, point or area, or the whole country if there is none.

## `searchQueries` (type: `array`):

Several keywords in one run: one search per keyword (times each location). Added to **Keyword**.

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

idealista search-result URLs (idealista.com, .it, .pt — the country, operation, property type and location, or the map area, of the URL are kept; set the filters with the fields below) or single listing URLs (`https://www.idealista.com/inmueble/12345678/`). Added to the searches above. Max 1 000 URLs.

## `listingIds` (type: `array`):

idealista listing codes (the number `12345678` of a listing URL such as https://www.idealista.com/inmueble/12345678/) of the chosen **Country**, fetched directly.

## `agencies` (type: `array`):

Every listing of these agencies: the agency name as it appears in its idealista page URL (`engel-volkers` in `https://www.idealista.com/pro/engel-volkers/`) or the whole URL. The operation, type and filters below still apply.

## `latitude` (type: `string`):

Search around a point instead of a location: latitude in decimal degrees (e.g. `40.4168`), with **Longitude** and **Radius**.

## `longitude` (type: `string`):

Longitude in decimal degrees (e.g. `-3.7038`).

## `radiusKm` (type: `number`):

Radius around the point, in kilometres (0.1 to 50).

## `polygon` (type: `string`):

Search inside an area drawn on the idealista map: paste the whole map URL or its shape value (`((_puuFnrsU?o}@n}@??n}@o}@?))`), or at least 3 points such as `40.42,-3.71;40.42,-3.70;40.41,-3.70`.

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

Maximum number of listings to save for the whole run (after deduplication and filters). 0 = no limit.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (location × keyword, agency, URL…), so that the first search cannot use up the whole **Max listings** budget. 0 = no per-search cap.

## `splitLargeSearches` (type: `boolean`):

idealista shows at most 2 500 listings per search. When a search has more, split it by price ranges automatically to reach every listing.

## `sortBy` (type: `string`):

Order of the results (it decides which listings come first when **Max listings** stops the run). A search of more than 2 500 listings is read by price ranges: a price sort keeps its order over the whole search, any other sort only inside each range.

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

1 extra request per listing for: exact address fields, all photos, energy certificate, community costs, the advertiser's office address and website, description in every language, last update date. Off = the search fields only (already with phone, GPS, description, photos).

## `enrichEmails` (type: `boolean`):

Visit the agency website and read its e-mail address. Needs **Add the agency profile** (fast: no listing page opened) or **Open each listing page** — the website is on both. One visit per agency website (not per listing). Charged separately, only when an e-mail is found.

## `includeAgencyProfile` (type: `boolean`):

For each listing of an agency: its idealista agency page — year it joined idealista, number of listings, description, cover photo, video, office address, GPS and phone, website. One extra request per agency (not per listing). Charged separately, only for listings that got it (private sellers have none).

## `language` (type: `string`):

Language of the descriptions and labels returned by idealista (automatic translation by the site when the advertiser did not write it).

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

In euros (monthly rent for rentals).

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

In euros (monthly rent for rentals).

## `minSize` (type: `integer`):

Built area, m².

## `maxSize` (type: `integer`):

Built area, m².

## `bedrooms` (type: `array`):

Keep these bedroom counts (several = any of them). `4` = 4 or more.

## `bathrooms` (type: `array`):

Keep these bathroom counts. `3` = 3 or more.

## `condition` (type: `array`):

New build, good condition, or to renovate.

## `homeTypes` (type: `array`):

For **Homes**: flats, penthouses, duplexes, studios, lofts, detached / semi-detached / terraced houses, villas, country houses.

## `floors` (type: `array`):

Ground floor, intermediate floors, top floor.

## `energyRating` (type: `array`):

High (A-B), medium (C-D) or low (E-G) energy efficiency.

## `publishedSince` (type: `string`):

idealista's own date filter (publication or last price drop). idealista offers 48 hours on sales and 24 hours on rentals: the other one searches the next wider period. For an exact date, see **Posted after**.

## `features` (type: `array`):

Keep only the listings with ALL of these.

## `bankOffer` (type: `boolean`):

Only the properties sold by banks.

## `auction` (type: `string`):

Keep, exclude or only show the auctions (sale).

## `occupationStatus` (type: `array`):

Sale: free, rented (with tenant), bare ownership, illegally occupied.

## `furnished` (type: `string`):

Rent: furnished home, or equipped kitchen only.

## `rentalTypes` (type: `array`):

Rent: long-term residential and / or seasonal.

## `petsAllowed` (type: `boolean`):

Rent: only the homes that accept pets.

## `roomGender` (type: `string`):

Room for a woman or a man.

## `roomOccupation` (type: `string`):

Students or workers.

## `roomBedType` (type: `string`):

Bed in the room.

## `roomFlatmates` (type: `array`):

Number of people already living in the flat.

## `roomRules` (type: `array`):

Keep only the rooms with ALL of these.

## `roomAvailableFrom` (type: `string`):

Move-in date (`2026-10-01`).

## `roomAvailableTo` (type: `string`):

Move-out date (`2027-06-30`).

## `postedAfter` (type: `string`):

Only listings last updated on or after this date (`2026-09-01`, or `7 days`, `2 weeks`, `1 month`). idealista gives the update date (not the first publication date) on the listing page: needs **Open each listing page**: without it, this date is not applied (the log says so) — use **Published since** instead.

## `postedBefore` (type: `string`):

Only listings last updated on or before this date (the whole day is included), or older than a period such as `30 days`. Needs **Open each listing page**.

## `excludeKeywords` (type: `array`):

Drop the listings whose title or description contains one of these words (case and accents ignored).

## `privateSellersOnly` (type: `boolean`):

Drop the listings of agencies and developers. Rare on homes in Spain (about 3 in 1,000 listings): most searches there return few or none.

## `requirePhone` (type: `boolean`):

Drop the listings without a phone number.

## `onlyPriceDrops` (type: `boolean`):

Only the listings whose price went down (idealista shows the former price).

## `minPriceDropPercent` (type: `integer`):

With **Price drops only**: only drops of at least this percentage.

## `onlyNew` (type: `boolean`):

Skip the listings that a previous run (same **Memory key**) already delivered: they are not saved and not charged. First run = everything is new.

## `stateKey` (type: `string`):

Name of the memory used by **Only new listings**. Give each schedule / task its own key (e.g. `madrid-rentals`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every listing again. Untick it afterwards.

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

Keep the default Apify Proxy: it is included in the price. The residential Apify proxy is not available in this Actor.

## `maxConcurrency` (type: `integer`):

Maximum number of requests processed in parallel.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "country": "es",
  "operation": "sale",
  "propertyType": "homes",
  "location": "Madrid",
  "locations": [],
  "searchQueries": [],
  "startUrls": [],
  "listingIds": [],
  "agencies": [],
  "radiusKm": 1,
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "splitLargeSearches": true,
  "sortBy": "relevance",
  "includeDetails": false,
  "enrichEmails": false,
  "includeAgencyProfile": false,
  "language": "",
  "bedrooms": [],
  "bathrooms": [],
  "condition": [],
  "homeTypes": [],
  "floors": [],
  "energyRating": [],
  "publishedSince": "",
  "features": [],
  "bankOffer": false,
  "auction": "",
  "occupationStatus": [],
  "furnished": "",
  "rentalTypes": [],
  "petsAllowed": false,
  "roomGender": "",
  "roomOccupation": "",
  "roomBedType": "",
  "roomFlatmates": [],
  "roomRules": [],
  "excludeKeywords": [],
  "privateSellersOnly": false,
  "requirePhone": false,
  "onlyPriceDrops": false,
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 4,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# 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 = {
    "location": "Madrid",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/idealista-listings-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": "Madrid",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/idealista-listings-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": "Madrid",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/idealista-listings-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/idealista-listings-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/6LWv6jUsG9iCnaSGV/builds/slClKyZ36eOfLipaf/openapi.json
