Idealista API & Scraper
The Idealista API returns Spanish and Italian real-estate listings as clean JSON.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
The primary search endpoint returns listings with id, URL, title, price, rooms, bathrooms, surface (m2), floor and features, and you can pull a detail and geography. It is built for real-estate tools and Southern-Europe property analytics that need Idealista data without a scraper. One ReefAPI key, one shared credit pool, the standard envelope.
Idealista country codes, id spaces and what each field actually means
Idealista is three separate portals sharing a brand, and the country parameter picks which one you are calling. The listing id, the URL word and the result set all change with it. Everything below was measured on 2026-08-27 with live search, detail and geography calls against all three markets.
| Input or field | What it is | Measured 2026-08-27 |
|---|---|---|
| country=es | Spain, idealista.com (the default) | Madrid resolves to slug madrid-madrid with 17,049 for-sale listings; ids like 109592362 at /inmueble/<id>/ |
| country=it | Italy, idealista.it | Roma resolves to slug roma-roma with 20,667 listings; ids like 35307271 at /immobile/<id>/ |
| country=pt | Portugal, idealista.pt | Lisboa resolves to slug lisboa with 10,138 listings; ids like 35196628 at /imovel/<id>/ |
| price / currency | Total asking price when contract=sale, monthly rent when contract=rent. Never a per-m2 figure | 1,850,000 EUR for a 125 m2 Madrid flat; 933 EUR per month for an 80 m2 Barcelona rental. currency is EUR in all three markets |
| surface_m2 | Living surface in square metres, integer | 125, 146, 80, 110 |
| rooms | Bedrooms, not total rooms. rooms_min=3 means 3 or more | rooms 2 on a Portuguese listing titled "Apartamento T2" |
| bathrooms | null on every search row; only detail fills it | listing 109592362: null in search, 2 in detail |
| features | Empty array on Spanish search rows and populated on detail; Portuguese search rows do carry short entries | detail returned 11 entries starting "125 m2 construidos"; a Lisbon search row returned ["T2", "sem elevador"] |
| year_built | In the detail schema but frequently null | null on the full detail record for 109592362 |
| home_type | The documented enum is apartment only, but other Idealista type slugs pass through and are applied | home_type=chalet narrowed Madrid from 17,049 to 5,976 and was echoed back in meta.filters_applied |
| meta.filters_applied / filters_unsupported | What the engine used, and what it had to drop | {"contract":"rent","sort":"price_low","price_max":1500,"rooms_min":2,"surface_min":80} on a Barcelona rental search |
Listing ids are per-country, so the same number can exist in two markets and mean two different homes. Always send country together with id on detail. An unrecognized filter value is ignored rather than rejected, which is why meta.filters_applied is worth reading on every response.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/idealista/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"location": "Madrid",
"country": "es"
}
}{
"ok": true,
"meta": {
"api": "idealista",
"endpoint": "search",
"mode": "live",
"latency_ms": 2258.1,
"record_count": 30,
"bytes": 472505,
"cache_hit": false,
"stop_reason": "limit_reached",
"country": "es",
"currency": "EUR",
"total": 18859,
"count": 30,
"page": 1,
"slug": "madrid-madrid",
"filters_applied": {},
"filters_unsupported": null,
"charged_credits": 2,
"version": "1.0.0"
},
"data": {
"results": [
{
"id": "112272495",
"url": "https://www.idealista.com/inmueble/112272495/",
"title": "Piso en Calle de López de Hoyos, Castellana, Madrid",
"price": 2695000,
"currency": "EUR",
"rooms": 3,
"bathrooms": null,
"surface_m2": 284,
"floor": "2ª planta exterior con ascensor",
"features": [
"Garaje incluido"
],
"thumbnail_url": "https://img4.idealista.com/blur/591_420_mq/0/id.pro.es.image.master/8c/c0/b6/1476215285.jpg"
},
{
"id": "111434614",
"url": "https://www.idealista.com/inmueble/111434614/",
"title": "Piso en Calle de la Fuente del Berro, Goya, Madrid",
"price": 1460000,
"currency": "EUR",
"rooms": 3,
"bathrooms": null,
"surface_m2": 150,
"floor": "2ª planta exterior con ascensor",
"features": [],
"thumbnail_url": "https://img4.idealista.com/blur/591_420_mq/0/id.pro.es.image.master/7c/9b/c0/1445769035.jpg"
},
{
"id": "110593979",
"url": "https://www.idealista.com/inmueble/110593979/",
"title": "Piso en Calle de Garcilaso, Trafalgar, Madrid",
"price": 1155000,
"currency": "EUR",
"rooms": 3,
"bathrooms": null,
"surface_m2": 115,
"floor": "5ª planta exterior con ascensor",
"features": [
"Garaje incluido"
],
"thumbnail_url": "https://img4.idealista.com/blur/591_420_mq/0/id.pro.es.image.master/ae/56/30/1476306457.jpg"
}
],
"total": 18859,
"count": 30,
"page": 1,
"country": "es",
"slug": "madrid-madrid",
"filters_applied": {},
"filters_unsupported": []
}
}What the Idealista API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | Search Idealista property listings by location (Spain, Italy or Portugal; for sale or rent) with structured filters: price (EUR), bedrooms, surface (m²), property type and sort. Each result carries id, title, price, rooms, bathrooms, surface, floor, features and thumbnail. Paginate with page. | Real-estate investors call search to search Idealista property listings by location (Spain, Italy or Portugal; for sale or rent) w…. | location, country, contract, sort, home_type, ... |
| detail | Full record for a single listing by its Idealista id (the number in an idealista.com/inmueble/<id>/ URL, or a search result's `id`). Returns title, price, address, bedrooms, bathrooms, surface, year built, the full feature list, description and all gallery image URLs. | Brokerage tools call detail to get full record for a single listing by its Idealista id (the number in an idealista.com/inmueble…. | id, country |
| geography | Resolve a free-text place name to the Idealista location slug + a ready-to-use search preview (the count of active listings there). Use it to confirm a location before searching, or to discover the exact slug a city resolves to. | Property dashboards call geography to resolve a free-text place name to the Idealista location slug + a ready-to-use search preview…. | query, country, contract |
Call search from your stack
curl -X POST https://api.reefapi.com/idealista/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"location":"Madrid","country":"es"}'import requests
r = requests.post(
"https://api.reefapi.com/idealista/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"location": "Madrid",
"country": "es"
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/idealista/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"location": "Madrid",
"country": "es"
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.idealista.search with {"location":"Madrid","country":"es"}.Who uses this API and why
- Investors call search to track listing prices by geography.
- Dashboards use detail and features to enrich a property.
- Analysts use geography to size a Spanish or Italian market.
Questions developers ask before integrating
Which countries does the Idealista API cover?
Three: Spain (country=es, the default), Italy (it) and Portugal (pt). They are separate portals with separate inventory, separate id spaces and separate URL vocabularies: /inmueble/ on idealista.com, /immobile/ on idealista.it and /imovel/ on idealista.pt. The search landing paths differ too, which the geography action exposes: venta-viviendas for Spain, vendita-case for Italy and comprar-casas for Portugal. All three quote money in EUR.
Is the Idealista price a total or a price per square metre?
It is the total, and it changes meaning with contract. For contract=sale it is the full asking price: a Madrid flat on Calle Velazquez came back at 1,850,000 EUR for 125 m2. For contract=rent it is the monthly rent: a Barcelona flat came back at 933 EUR for 80 m2. There is no per-m2 field anywhere in the payload, so if you want price per square metre you divide price by surface_m2 yourself. price_min and price_max follow the same rule, which is why price_max=1500 is sensible for rent and meaningless for sale.
Why is bathrooms null in every Idealista search result?
The search card does not carry it. Measured on 2026-08-27, all 30 Madrid rows and all 14 Barcelona rental rows returned bathrooms: null, while detail for the same listing 109592362 returned bathrooms: 2. The same pattern applies to features, which is an empty array on Spanish search rows and an 11-entry list on the detail record. If your product needs bathroom counts, budget a detail call per listing rather than expecting search to fill it in.
Is an Idealista listing id unique across Spain, Italy and Portugal?
No. Each market has its own id space and the ranges overlap. Measured ids were 109592362 and 112363256 in Spain (nine digits), 35307271 in Italy and 35196628 in Portugal (eight digits each). That is why detail takes country alongside id: calling a Portuguese id against country=es will either miss or resolve to an unrelated Spanish property. Store the country next to every id you cache.
Does the rooms field count bedrooms or all rooms?
Bedrooms. The Spanish source calls them habitaciones and the Portuguese source uses T-notation, which the API surfaces intact: a listing titled "Apartamento T2" comes back with rooms: 2 and a features entry of "T2". The rooms_min filter is a floor rather than an exact match, so rooms_min=3 returns three-bedroom homes and larger. It accepts 1 through 10.
Can I filter by a property type other than apartment?
The published enum for home_type lists apartment only, but other Idealista type slugs pass through and are genuinely applied. Measured on 2026-08-27, home_type=chalet with rooms_min=3 narrowed Madrid from 17,049 total listings to 5,976 and came back echoed in meta.filters_applied as {"home_type":"chalet","rooms_min":3}. Since unrecognized values are ignored rather than rejected, treat anything outside apartment as best-effort and confirm it in meta.filters_applied before relying on it.
How deep does Idealista pagination go?
About 30 listings per page, with meta.total giving the market size for the query. Spain pages cleanly: Madrid page 1 and page 2 both returned 30 rows against the same total of 17,049. Italy did not, on either attempt measured on 2026-08-27: page 2 for roma-roma returned count 0 and total 0 plus an explanatory note field ("no Idealista page for 'roma-roma' with these filters"), even though page 1 of the same query reported 20,667. Check for that note before treating an empty page as the end of the inventory.
What does a RATE_LIMITED "warming up" error mean?
It is a transient, not a quota. The envelope comes back with ok: false, error.code RATE_LIMITED, the message "'idealista' is warming up - retry shortly" and error.retryable: true. It showed up on 2026-08-27 during a burst of back-to-back calls. Wait a few seconds and repeat the identical request. Because retryable is true, this is a case to retry rather than surface to your user as a failure.
What is the Idealista API?
Idealista API is a ReefAPI endpoint group for idealista It returns live JSON through POST requests under /idealista/v1.
Is the Idealista API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Idealista calls use the same shared credit balance as every other ReefAPI engine.
Do I need an Idealista login or account?
No login to Idealista is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Idealista data?
The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Idealista API use?
Idealista actions currently cost 1-2 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.
Can I call Idealista from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call idealista actions with the same key, credit pool and JSON envelope used by normal REST requests.