Idealista Scraper - Property Listings, Prices & Contacts avatar

Idealista Scraper - Property Listings, Prices & Contacts

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Idealista Scraper - Property Listings, Prices & Contacts

Idealista Scraper - Property Listings, Prices & Contacts

From $1/1K. Scrape Idealista properties across Spain, Italy, and Portugal. Extract 35+ fields including prices, sizes, rooms, coordinates, advertiser contacts, phone numbers, descriptions, and photos. Supports properties for sale, rent, and rooms.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

7

Total users

0

Monthly active users

14 days ago

Last modified

Share

Idealista Scraper: Spain, Italy and Portugal Property Listings

Idealista Scraper turns idealista into a clean property data feed across its three markets: idealista.com (Spain), idealista.it (Italy) and idealista.pt (Portugal). Search by location or paste any idealista search link, get price, size, rooms, energy rating, GPS coordinates, advertiser name and phone, full descriptions and deduplicated photo galleries, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.

Why This Scraper?

  • Three markets, one actor. Spain, Italy and Portugal, selected per run in Search mode; URL mode detects the market automatically from each pasted link.
  • 50+ fields on full detail. Price per m2, energy rating, GPS coordinates, advertiser name and phone, construction year, the complete description and up to 40 deduplicated photos.
  • Two ways to search. Build a search from a location, operation and filters, or paste any idealista search URL directly. Multiple URLs and forward pagination are supported.
  • Buy, rent or room listings in every market, with price and bedroom filters that work the same way across Spain, Italy and Portugal in Search mode.
  • Detail enrichment on demand. Turn it off for a fast run with search-result fields only, or on for the full record, one extra page fetch per listing.
  • Built for schedules. Incremental mode returns only new, updated and reappeared listings on recurring runs, and a run that cannot reach the site fails loudly instead of returning an empty dataset.
  • Automatic connection retry. If a connection is refused, the actor retries with a different one before giving up, so a single flaky attempt doesn't end the run.

Use Cases

  • Real estate investors and flippers: track price drops and new listings across three markets to spot deals early.
  • Market researchers and analysts: build historical price-per-m2 and rent datasets by neighborhood and city.
  • Relocation and property agencies: aggregate cross-market listings into one feed for clients comparing Spain, Italy and Portugal.
  • Lead generation teams: capture advertiser names and phone numbers from professional listings for outreach.
  • Journalists and academics: monitor housing supply, price trends and listing turnover over time.

Data You Get

Sample shape: values are illustrative placeholders, not from a live listing.

FieldExample
id"00000001"
url"https://www.idealista.com/inmueble/00000001/"
market"ES" (also "IT", "PT")
operation"sale" (also "rent", "room")
title"Sample Flat in Example Street"
propertyType"flat" (inferred from the first word of the title, e.g. "Piso...")
price450000
priceText"450.000 EUR"
pricePerM24736 (when detail pages are fetched)
previousPrice / priceDropped480000 / true
size95.0
rooms3
bathrooms2 (when detail pages are fetched)
floor"3rd floor with lift"
hasLifttrue
condition"Second hand, good condition" (when detail pages are fetched)
constructionYear1985 (when detail pages are fetched)
energyConsumptionRating / energyEmissionsRating"D" / "D" (when detail pages are fetched)
neighborhood / city"Example District" / "Example City" (when detail pages are fetched)
latitude / longitude40.0000 / -3.0000 (when detail pages are fetched)
advertiserName / phone"Sample Agency" / "+34 000 000 000" (when detail pages are fetched)
images / imageCountlist of up to 40 photo URLs / 24 (imageCount is the site's full total, images is capped at 40; both when detail pages are fetched)
tags["price drop"]
scrapedAt"2026-01-01T00:00:00.000000+00:00"
changeType"NEW" (Incremental mode only; also "UPDATED", "UNCHANGED", "REAPPEARED", "EXPIRED")

Feature flags such as hasTerrace, hasGarage, hasStorage, hasGarden, hasPool and hasAC appear only when idealista's own feature list confirms them (always true); their absence means the feature wasn't listed, not that it was confirmed absent. hasVideo, has3DTour, hasFloorPlan and hasHomeStaging, by contrast, are always present as true or false. In Incremental mode, records also carry changedFields (the list of fields that changed), firstSeenAt and lastSeenAt.

How to Use

  1. Pick a mode: Search by Location builds URLs for you, Direct URLs scrapes the idealista search links you paste.
  2. For Search mode, choose a market, an operation (buy, rent or room), one or more location slugs, and any price or bedroom filters. For URL mode, paste one or more idealista search URLs.
  3. Set Max Listings and Max Pages Per Search to control run size and cost, and turn Fetch Detail Pages on or off depending on whether you need the full record.
  4. Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.

Search Spain (Madrid), buy, lean run:

{
"mode": "search",
"market": "es",
"operation": "sale",
"locations": ["madrid-madrid"],
"maxListings": 50,
"fetchDetails": false
}

Search with price and bedroom filters, full detail:

{
"mode": "search",
"market": "es",
"operation": "sale",
"locations": ["barcelona-barcelona"],
"minPrice": 200000,
"maxPrice": 500000,
"minBedrooms": 3,
"fetchDetails": true
}

Search Italy (rent in Rome):

{
"mode": "search",
"market": "it",
"operation": "rent",
"locations": ["roma-roma"],
"maxListings": 100
}

URL mode (paste idealista search links, multiple supported):

{
"mode": "url",
"urls": [
"https://www.idealista.com/venta-viviendas/madrid-madrid/",
"https://www.idealista.pt/comprar-casas/lisboa/"
],
"maxPages": 2,
"fetchDetails": true
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/idealista-scraper").call(run_input={
"mode": "search",
"market": "es",
"operation": "sale",
"locations": ["madrid-madrid"],
"maxListings": 50,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["title"], item["price"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/idealista-scraper').call({
mode: 'search',
market: 'es',
operation: 'sale',
locations: ['madrid-madrid'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Fetch Detail Pages and run limits

Max Pages Per Search and Max Listings bound how much of a search this actor scans, not how many rows are pushed. idealista serves at most about 60 pages (roughly 1,800 listings) per single search. Price and bedroom filters are applied after the results are fetched, not added to the search itself, so setting them in Search mode does not reduce how many pages are read; to pull more than 1,800 listings, split the search across several locations, or paste idealista search URLs (URL mode) that are already filtered by price on the site. Fetch Detail Pages controls whether the actor opens each listing's own page: on, you get the full record described above; off, you get the search-result fields only, for a faster and cheaper run.

If a run is close to its own platform time limit, the actor stops opening new detail pages and pushes the listing fields it already has for the remaining cards, rather than being cut off with nothing returned. The status message reports how many listings were affected this way.

Resume and recurring updates

Two different features, both off by default:

  • resumeFromRunId continues one specific interrupted or very large crawl. Paste a previous run ID or dataset ID and this run skips every listing already collected there, so you don't pay twice.
  • incrementalMode is for scheduling this actor daily or weekly against the same search. The actor remembers the previous run's listings itself, scoped to the search or URL and filter settings, or to a manual stateKey. Each listing gets a changeType of NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED. By default only NEW, UPDATED and REAPPEARED listings are returned; turn on emitUnchanged or emitExpired to also get (and pay for) the rest.

EXPIRED is only produced once a run has fully scanned the tracked search from start to end, with emitExpired on and without resumeFromRunId; a run capped by maxListings or maxPages cannot prove a listing is gone, so it skips expiry detection that run and keeps the previous state as-is. REAPPEARED only ever appears for a listing that was previously marked EXPIRED and is then found again in a later run; with emitExpired left off, a listing never enters the EXPIRED state, so REAPPEARED does not occur either. resumeFromRunId and incrementalMode can be combined to bootstrap a new monitoring campaign from a previous large pull, but only on the first incremental run for a given state key; if that key already has tracked listings, the run fails fast rather than mixing baselines.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch (Search by Location) or url (Direct URLs).
marketstringesMarket for Search mode: es, it, or pt. URL mode infers it per URL.
operationstringsalesale, rent, or room (Search mode only).
locationsarraynone (prefill: ["madrid-madrid"])idealista location slugs (Search mode only). Required if mode is search.
urlsarraynone (prefill: one example idealista search URL)idealista search URLs (URL mode only). Required if mode is url.
minPriceintegernoneMinimum price. Search mode only.
maxPriceintegernoneMaximum price. Search mode only.
minBedroomsintegernoneMinimum rooms. Search mode only.
maxBedroomsintegernoneMaximum rooms. Search mode only.
maxPagesinteger60Pages per search (30 listings per page). 60 is idealista's own ceiling per search; a run is also bounded by Max Listings.
maxListingsinteger100Total listings scanned across all searches. 0 means unlimited.
maxConcurrencyinteger6Parallel detail-page fetches (1 to 12) when Fetch Detail Pages is on.
fetchDetailsbooleantrueOpen each listing's own page for coordinates, advertiser, phone, full description, photos, bathrooms, condition, orientation and heating.
proxyobjectnone (prefill: Apify Proxy, RESIDENTIAL group); the actor applies the same setup when this field is left outConnection settings. Residential proxy in the listing's country works best.
resumeFromRunIdstringnoneContinue one specific interrupted run: paste a previous run or dataset ID.
incrementalModebooleanfalseRecurring monitoring of the same search: only new, updated and reappeared listings are returned on later runs.
stateKeystringnoneName an Incremental mode monitoring campaign, or share state across differently configured runs.
emitUnchangedbooleanfalseIncremental mode: also return unchanged listings (extra rows, extra billing).
emitExpiredbooleanfalseIncremental mode: also return expired listings once a run fully scans the tracked search (extra rows, extra billing).
mcpConnectorsarraynoneOptional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstringnoneNotion connector only: page under which records are created.
maxNotifyListingsinteger50Cap on items written to each connector per run. Does not affect the dataset.

Output Example

Sample shape: values are illustrative placeholders, not from a live listing.

{
"id": "00000001",
"url": "https://www.idealista.com/inmueble/00000001/",
"market": "ES",
"operation": "sale",
"title": "Piso en Calle Ejemplo",
"propertyType": "flat",
"price": 450000,
"priceText": "450.000 EUR",
"pricePerM2": 4737,
"previousPrice": 480000,
"priceDropped": true,
"currency": "EUR",
"size": 95.0,
"rooms": 3,
"bathrooms": 2,
"floor": "3rd floor with lift",
"hasLift": true,
"hasTerrace": true,
"hasHomeStaging": false,
"orientation": "South facing",
"heating": "Central heating",
"condition": "Second hand, good condition",
"constructionYear": 1985,
"energyConsumptionRating": "D",
"energyEmissionsRating": "D",
"reference": "REF-0001",
"lastUpdatedText": "Listing updated on 1 January",
"description": "Full advertiser description text appears here when fetchDetails is on.",
"latitude": 40.0000,
"longitude": -3.0000,
"address": "Example District, Example City",
"neighborhood": "Example District",
"city": "Example City",
"photoCount": 24,
"isBranded": true,
"hasVideo": true,
"has3DTour": false,
"hasFloorPlan": true,
"advertiserName": "Sample Agency",
"advertiserType": "professional",
"phone": "+34 000 000 000",
"features": ["95 m2 construidos", "3 habitaciones", "2 baños", "Terraza"],
"images": ["https://img4.idealista.com/blur/WEB_DETAIL/0/id.pro.es.image.master/00/00/00/000000000.jpg"],
"imageCount": 24,
"tags": ["price drop"],
"source": "www.idealista.com",
"scrapedAt": "2026-01-01T00:00:00.000000+00:00"
}

Plan Requirement

idealista serves full listings only over a residential connection in the listing's country. The default connection setting already selects Apify's Residential proxy group, and the actor automatically retries with a different connection when one is refused. For large or frequent runs, keep Residential selected under Connection; a non-residential connection will return far fewer results, or none at all.

FAQ

How much does it cost?

You pay per record returned to the dataset, plus an optional detail-enrichment charge only for records that were actually enriched with a detail-page fetch and pushed (records suppressed by Incremental mode are never charged for enrichment). The Pricing tab shows the current rates. Use Max Listings to cap the cost of any run.

This actor collects only publicly available listing data. You are responsible for how you use it: follow idealista's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Advertiser names, phone numbers and photos may carry their own rights or privacy considerations, separate from the factual listing data.

Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only NEW, UPDATED and REAPPEARED listings for the same search, and unchanged ones are not billed unless you turn on Emit unchanged. REAPPEARED only ever appears for a listing that was previously marked EXPIRED, and EXPIRED itself only happens when Emit expired listings is on and an earlier run fully scanned the tracked search without a cap or a resume getting in the way.

What's the most common mix-up between the two modes?

Price and bedroom filters (Min Price, Max Price, Min Bedrooms, Max Bedrooms) apply only in Search mode. In URL mode, the pasted URL's own filters apply exactly as idealista built them; the actor does not re-apply the Min/Max fields on top of a pasted URL.

Why did my run fail instead of returning an empty dataset?

If every attempt to read the search results is refused, the run fails outright with a clear message instead of returning zero listings, so "no matches for this search" is never confused with "the site could not be read". If only part of a run was refused, for example one location out of several, the run still succeeds and returns what it found, with a status message noting the run is incomplete. If a run is nearing its own platform time limit, it stops opening new detail pages and returns the listing fields it already has for the remaining listings instead of being cut off with nothing pushed; the status message reports how many listings were affected.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push a summary of each listing into Notion, Linear or Airtable.

🔗 Want more real estate data?

Pair this actor with these related scrapers from the same team:

🏠 Fotocasa.es
From $1/1K. Scrape Spain property listings from fotocasa.es. Get price, surface, rooms...
🏠 Immobiliare.it Scraper
From $1/1K. Extract property listings from Immobiliare.it with clean structured data...
🏠 Immowelt.de Scraper
Scrape detailed property listings from Immowelt.de into clean structured data. Extract...
🏠 Zonaprop Argentina
Scrape Zonaprop.com.ar property listings across Argentina. Extract 140+ fields including...
🏠 iProperty MY Scraper
Scrape property listings from iProperty.com.my for sale or rent: price, PSF, bedrooms...
🏠 Property24
From $1/1K. Extract structured property listings from Property24, South Africa’s largest...

👉 Browse all abotapi scrapers

💬 Support & custom scrapers

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.