Idealista Property Scraper
Pricing
Pay per event
Idealista Property Scraper
Scrape normalized property listings from idealista.com (Spain), idealista.it (Italy), and idealista.pt (Portugal) in one run — unified EUR/m² schema, sale or rent, plus agency and lister contact enrichment neither incumbent ships together.
Pricing
Pay per event
Rating
0.0
(0)
Developer
DevilScrapes
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 hours ago
Last modified
Categories
Share
🎯 What this scrapes
Idealista is the shared real-estate platform behind idealista.com (Spain), idealista.it (Italy), and idealista.pt (Portugal) — the #1 property portal in every one of those markets. Cross-border investors and PropTech teams today stitch together three separate scrapes with three different schemas just to compare a Madrid flat to a Lisbon apartment. This Actor wraps all three TLDs into a single run and a single normalized schema — EUR pricing, m² area, a shared property-type taxonomy, and EU energy ratings — so a country field is the only thing that changes between rows. On top, it enriches each listing with agency and lister details (name, phone when publicly exposed, particular vs. professional, agent reference id) that most Idealista scrapers skip entirely.
🔥 What we handle for you
- 🛡️ A real browser engine, not a bare HTTP client — we drive an anti-detection browser through a same-context warm-up sequence so the target sees genuine browser traffic, never a bot signature.
- 🌐 Residential proxy rotation via Apify Proxy, pinned per country — a fresh exit IP on every retry, never the same flagged exit twice.
- 🧱 A geo-splash guard on every response — a mismatched exit can return a different country's listings at a clean 200; we catch and reject that before it ever reaches your dataset.
- 🔁 Automatic retries with a freshly rotated proxy session on any block signal.
- 🧊 Clean, typed dataset rows — Pydantic-validated, ISO-8601 timestamps, stable IDs, JSON / CSV / Excel export straight from the Apify Console.
- 💰 Pay-Per-Event pricing — you only pay for results that hit your dataset. No data, no charge.
💡 Use cases
- Cross-border deal screening — compare sale listings in Madrid, Rome, and Lisbon side by side without normalizing three different scrapers' output yourself.
- Rental market benchmarking — track price-per-m² across ES/IT/PT rental markets in one dataset.
- Agency/lister lead lists — collect agency names, phone numbers (when public), and agent reference codes behind active listings.
- Relocation and expat services — build a unified property feed spanning three Southern European markets for client-facing search tools.
⚙️ How to use it
- Click Try for free at the top of the page.
- Fill in the input form — most fields have sensible defaults.
- Click Start. Output streams into the run's dataset.
- Export from Storage → Dataset as JSON, CSV, or Excel — or fetch via the API.
📥 Input
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
countries | array | no | ['ES'] | Countries to run (ES/IT/PT). Each country runs independently — one blocked country doesn't stop the others. |
searchUrls | array | no | '—' | Direct idealista.com / idealista.it / idealista.pt search URLs to scrape as-is. Country is inferred from the TLD. Up to… |
location | string | no | 'madrid-madrid' | idealista's own two-part search slug — municipality-province, e.g. 'madrid-madrid' (most municipalities do NOT share… |
operation | string | no | 'sale' | Sale vs. rent. Country-agnostic — mapped to the right per-TLD slug internally. |
propertyType | string | no | 'homes' | Shared property-type taxonomy across all three TLDs. |
maxResultsPerCountry | integer | no | 100 | Cap on rows per country; each country's cap is independent. |
enrichAgencyContact | boolean | no | True | Fetch each listing's detail page for agency/agent fields (name, phone when exposed, particular vs. professional, agent… |
proxyCountryMap | object | no | {'ES': 'ES', 'IT': 'IT', 'PT': 'PT'} | Override the proxy exit country per target country. Idealista hard-localizes by IP — a mismatched exit silently returns… |
proxyConfiguration | object | no | {'useApifyProxy': True, 'apifyProxyGroups': ['RESIDENTIAL']} | Mandatory-by-default RESIDENTIAL — country_code is resolved per-request from Proxy country map. |
Example input
{"countries": ["ES"],"location": "madrid-madrid","operation": "sale","propertyType": "homes","maxResultsPerCountry": 3,"enrichAgencyContact": true,"proxyCountryMap": {"ES": "ES","IT": "IT","PT": "PT"},"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"]}}
📤 Output
Every row is one dataset item.
| Field | Type | Notes |
|---|---|---|
listing_id | string | Idealista ID, per-TLD. |
url | string | Canonical detail URL. |
country | string | Normalization key — 'ES', 'IT', or 'PT'. |
operation | string | 'sale' or 'rent', as requested. |
property_type | string | Shared taxonomy value. |
title | string | Listing headline. |
price | ['number', 'null'] | Asking price. |
currency | string | Always 'EUR'. |
price_per_sqm | ['number', 'null'] | Published or computed. |
area_sqm | ['number', 'null'] | Normalized to m². |
rooms | ['integer', 'null'] | Room count. |
bathrooms | ['integer', 'null'] | Bathroom count. |
floor | ['string', 'null'] | Raw label, not normalized (per-market variance). |
energy_rating | ['string', 'null'] | EU EPC letter A–G. |
location_address | ['string', 'null'] | Full address, when public. |
location_neighborhood | ['string', 'null'] | Neighborhood, when public. |
location_city | string | City. |
location_province | ['string', 'null'] | Province/region. |
latitude | ['number', 'null'] | WGS-84 map pin latitude. |
longitude | ['number', 'null'] | WGS-84 map pin longitude. |
agency_name | ['string', 'null'] | Enrichment field. |
agency_phone | ['string', 'null'] | Only if publicly exposed. |
listing_owner_type | ['string', 'null'] | 'particular' or 'professional'. |
agent_reference_id | ['string', 'null'] | Agency's own reference code. |
listed_date | ['string', 'null'] | ISO YYYY-MM-DD. |
updated_date | ['string', 'null'] | ISO YYYY-MM-DD. |
description_snippet | ['string', 'null'] | First ~300 chars. |
image_urls | array | Gallery photos (empty OK). |
scraped_at | string | ISO-8601 UTC row-creation timestamp. |
Example output
{"listing_id": "34567890","url": "https://www.idealista.com/inmueble/34567890/","country": "ES","operation": "sale","property_type": "homes","title": "Piso en Malasa\u00f1a, Madrid","price": 425000.0,"currency": "EUR","price_per_sqm": 5312.5,"area_sqm": 80.0,"rooms": 2,"bathrooms": 1,"floor": "3\u00ba ext","energy_rating": "D","location_address": null,"location_neighborhood": "Malasa\u00f1a-Universidad","location_city": "Madrid","location_province": "Madrid","latitude": 40.4265,"longitude": -3.7038,"agency_name": "Example Inmobiliaria","agency_phone": "+34910000000","listing_owner_type": "professional","agent_reference_id": "REF-8891","listed_date": "2026-07-02","updated_date": "2026-08-05","description_snippet": "Precioso piso reformado a estrenar en pleno barrio...","image_urls": ["https://img.idealista.com/example1.jpg"],"scraped_at": "2026-08-11T12:00:00+00:00"}
💰 Pricing
Pay-Per-Event — you pay only when these events fire:
| Event | USD | What it is |
|---|---|---|
actor-start | $0.2 | One-off warm-up charge per run |
result-row | $0.005 | Per unique dataset item |
Example: 1 000 results at the rates above ≈ $5.20. No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.
🚧 Limitations
v1 covers Spain, Italy, and Portugal only — Idealista doesn't operate in other markets. New-development/promoter microsites, the mortgage calculator, area-guide pages, and saved-search/alert features behind an agency login are out of scope. agency_phone ships verbatim, unverified, only when publicly rendered on the listing. floor stays a raw label — market-specific floor conventions aren't normalized across countries.
❓ FAQ
Do I need an Idealista account or API key?
No. This Actor scrapes Idealista's own publicly listed property data across all three TLDs — no login, no API key.
Why does this default to a residential proxy pinned per country?
Idealista localizes by IP — a mismatched exit can silently return a different country's listings. We default every request to a RESIDENTIAL proxy pinned to the target country so ES/IT/PT runs never cross-contaminate.
Can I mix countries in one run?
Yes — set countries to any combination of ES/IT/PT (or supply direct searchUrls), and each country is fetched independently; one blocked country never stops the others.
Does agency_phone always populate?
Only when enrichAgencyContact is true and the number is publicly exposed on the listing; otherwise it's null.
💬 Your feedback
Spotted a bug, hit a weird edge case, or need a new field? Open an issue on the Actor's Issues tab on Apify Console — we ship fixes weekly and we read every report.