Field reference first, code second. This is an Idealista API built on ScrapingBee for Spanish property listings, and the two tables below are what it returns. Every field was read from live idealista.com pages on 2026-10-29 (Valencia rentals), and each one comes with the selector that produced it, so you can check our work against the page yourself.
search_page() in examples/idealista_listings.py. 30 rows per results page, 75 credits per page.
| Field | Example | Source on the page |
|---|---|---|
id |
112937303 |
article.item[data-element-id], attribute data-element-id |
url |
https://www.idealista.com/en/inmueble/112937303/ |
a.item-link href |
title |
Flat / apartment in Calle d'Ángel Villena, Ciutat de les Arts i de les Ciencies, València |
a.item-link text |
price_eur |
2100 |
span.item-price, digits only |
per_month |
true |
€/month suffix inside the price span (rentals) |
bedrooms |
3 |
span.item-detail chip ending in bed. |
size_m2 |
122 |
span.item-detail chip containing m² |
eur_per_m2 |
17.21 |
computed, price_eur / size_m2 |
floor |
6th floor exterior with lift |
span.item-detail chip containing floor |
parking |
true |
span.item-detail chip Parking included |
extra |
["5 hours"] |
any chip not matched above |
professional |
true |
article attribute data-is-professional-ad |
tags |
["Luxury"] |
span.listing-tags, also seen: Short-term rental |
The detail chips have no labels and no fixed order. One card returned ["Parking included", "3 bed.", "122 m²", "6th floor exterior with lift", "5 hours"], the next ["4 bed.", "180 m²", "6th floor exterior with lift"]. Position based parsing breaks on the first card with a parking chip. _classify() sorts them by wording instead, and anything it does not recognise lands in extra rather than being dropped. That is where the listing age (5 hours) ends up. When a card has no bedroom chip at all, bedrooms is null.
listing(id) in the same file. 75 credits per listing.
| Field | Example | Source on the page |
|---|---|---|
title |
Flat / apartment for rent in Calle del Hospital |
.main-info__title-main |
area |
Sant Francesc, Valencia |
.main-info__title-minor |
price_eur |
3250 |
.info-data-price |
built_m2 |
180 |
feature 180 m² built |
bedrooms / bathrooms |
4 / 2 |
features 4 bedrooms, 2 bathrooms |
energy_kwh_m2_year |
91 |
feature Consumption: 91 kWh/m² year |
emissions_kg_co2_m2_year |
21 |
feature Emissions: 21 kg CO2/m² year |
location_path |
["Calle del Hospital", "Subdistrict Sant Francesc", "District Ciutat Vella", "Valencia", "Valencia"] |
.header-map-list items |
advertiser |
aProperties Real Estate Valencia |
.advertiser-name |
updated |
Listing updated on 29 October |
.stats-text |
features |
the full list, 12 strings for that flat | .details-property_features li |
description |
the advertiser's text | .comment |
The features list mixes the basic block and the building block into one sequence: 180 m² built, 4 bedrooms, 2 bathrooms, Second hand/good condition, Fitted wardrobes, Furnished and with equipped kitchen, Individual heating: Electric, 6th floor exterior, With lift, Air conditioning, then the two energy certificate lines. The numeric fields above are pulled out of it with patterns, and the raw list is kept because the rest varies from listing to listing.
location_path is the most useful field for analysis. It gives street, subdistrict and district as separate, consistently ordered strings, which the search card only offers as a comma joined title.
params = {"url": url, "stealth_proxy": "true", "extract_rules": json.dumps(rules)}
requests.get("https://app.scrapingbee.com/api/v1/", headers={"Authorization": f"Bearer {KEY}"}, params=params)Idealista loads a DataDome script on every page (window.ddjskey sits at the top of the HTML). With mode=auto ScrapingBee tried the cheaper tiers on both page types and settled on the stealth tier each time, so the scripts ask for stealth_proxy=true directly and skip the climb. Stealth runs with JavaScript rendering, at 75 credits per successful request.
Two calls out of about ten failed during testing: ScrapingBee returned 500 with Idealista's 408 once and 520 once. Failed requests are not billed, so both scripts retry a 500 up to three times.
Page 1 is the bare search path. Page N appends pagina-N.htm, the same link Idealista's own pager uses:
https://www.idealista.com/en/alquiler-viviendas/valencia-valencia/
https://www.idealista.com/en/alquiler-viviendas/valencia-valencia/pagina-2.htm
The page heading tells you how far to go. #h1-container__text read 2,077 houses and flats for rent in Valencia, Spain, which at 30 per page is 70 pages, 5,250 credits for a full pass over Valencia rentals. Swap alquiler-viviendas for venta-viviendas for homes for sale.
examples/rent_per_m2.js reads N result pages and groups asking rent per square metre by neighbourhood, taken from the second to last part of the card title. Two pages, 60 listings, 150 credits:
60 listings used, 0 skipped, 150 credits
Russafa 5 23.33 EUR/m2
Gran Vía 4 18.95 EUR/m2
Playa de la Malvarrosa 4 17.65 EUR/m2
El Carme 4 17.35 EUR/m2
Sant Francesc 3 20.94 EUR/m2
Sixty listings out of 2,077 is a demonstration of the pipeline, not a market report. Run it with 70 as the page count for the whole city, and use the location_path from listing pages if you need districts rather than neighbourhood names parsed from titles.
Idealista has an official Search API. Keys are issued on request through its developer site, where you describe your project and wait for a decision. If you qualify and the API covers your use, it is the cleaner route. People reach for an Idealista scraper when they need what the public site shows today, across any search a visitor can run, without that approval step. This repo reads public, logged out pages only.
Tested here: idealista.com, Spain, English pages, rentals. The same markup is likely on the Portuguese and Italian sites, but they were not exercised for this README.
Related ScrapingBee real estate endpoints: Immobiliare scraper, SeLoger scraper, ImmoScout24 scraper, Immoweb scraper, Rightmove scraper, Zoopla scraper, Funda scraper, real estate data API.
Documentation: extraction rules, HTML API and credit costs, pricing. New accounts get 1,000 free credits, enough for 13 Idealista pages.
Public listing and search pages only. Saved searches, favourites, alerts and messaging to advertisers require an account and are out of scope, and scraping under login credentials is prohibited by ScrapingBee's terms of service. Listings contain advertiser names and sometimes agents' details; if you store them, the GDPR applies to you as the controller. Idealista's own terms govern the site.
How do I scrape Idealista without getting blocked? Use ScrapingBee's stealth proxy tier. Classic and premium tiers did not get through in testing; stealth returned every page at 75 credits, and the occasional failure was unbilled.
How many listings does one request return? 30 per search results page.
Can I get the energy certificate? Yes, from the listing page. Consumption and emissions are lines in the features list.
Does the Idealista scraper work for homes for sale?
Use /en/venta-viviendas/<city>/. The card markup is the same; per_month will be false.
Is there an official Idealista API? Yes, the Search API, with keys granted on request.
MIT. See LICENSE.