Read Idealista listings from Spain, Italy and Portugal with one API
The Idealista API returns Spanish and Italian real-estate listings as clean JSON.
3 active endpoints, on 0 and 2 credit tiers.
- POST/idealista/v1/search
- POST/idealista/v1/detail
- POST/idealista/v1/geography
What Idealista endpoints does ReefAPI ship?
3 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.
Idealista API
3 of 3 endpoints, ready to run
The results grid for one city: price in euros, rooms, floor area, the floor and lift note, and the id every other call needs.
{ "ok": true, "meta": { "api": "idealista", "endpoint": "search", "mode": "live", "latency_ms": 1575.4, "record_count": 30, "cache_hit": false }, "data": { "results": [ { "id": "109592362", "url": "https://www.idealista.com/inmueble/109592362/", "title": "Piso en Calle Velázquez, Recoletos, Madrid", "price": 1850000, "currency": "EUR", "rooms": 2, "bathrooms": null, "surface_m2": 125, "floor": "3ª planta exterior con ascensor", "features": [], "thumbnail_url": "https://img4.idealista.com/blur/591_420_mq/0/id.pro.es.image.master/a1/aa/1e/1467639170.jpg" }, { "id": "110413083", "url": "https://www.idealista.com/inmueble/110413083/", "title": "Piso en Calle del Corazón de María, Prosperidad, Madrid", "price": 1050000, "currency": "EUR", "rooms": 3, "bathrooms": null, "surface_m2": 164, "floor": "1ª planta exterior con ascensor", "features": [ "Garaje incluido" ], "thumbnail_url": "https://img4.idealista.com/blur/591_420_mq/0/id.pro.es.image.master/fc/8e/83/1429632100.jpg" }, { "id": "112357554", "url": "https://www.idealista.com/inmueble/112357554/", "title": "Piso en Costillares, Madrid", "price": 925000, "currency": "EUR", "rooms": 3, "bathrooms": null, "surface_m2": 146, "floor": "4ª planta exterior con ascensor", "features": [], "thumbnail_url": "https://img4.idealista.com/blur/591_420_mq/0/id.pro.es.image.master/63/6b/6b/1467376158.jpg" } ], "total": 17061, "count": 30, "page": 1, "country": "es", "slug": "madrid-madrid", "filters_applied": {}, "filters_unsupported": [] } }
How the Idealista API works
Idealista is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.
No OAuth app, no request signing, no per-site account. One key covers all 184 engines.
Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.
Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.
One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.
Size a market before you sweep it
geography is free and tells you how many listings a city actually holds. Running it first turns a blind sweep into a budgeted one.
{"query": "Madrid", "country": "es"}Zero credits. Returns the slug and total_listings — Madrid came back at 17,034 for sale, Rome at 20,660, Lisbon at 5,529 to rent.
{"location": "Madrid", "country": "es", "sort": "newest", "page": 1}2 credits for about 30 rows. Sorting newest and stopping when you reach ids you already have is the cheapest way to keep a city current.
You know the size of the job before you pay for it, and a daily top-up on a 17,000-listing city is a handful of pages rather than a full sweep.
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"}'{
"ok": true,
"data": { … },
"meta": {
"api": "idealista",
"endpoint": "search",
"mode": "live",
"latency_ms": …,
"record_count": …
},
"error": null
}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.
Three countries, one parameter — and four fields that come back empty
Measured on 2026-08-28 on Madrid, Rome and Lisbon, sale and rent. Four of these lines go against us, and one of them is the only recency signal this engine has.
Spain, Italy and Portugal, each its own site and its own id space — the url in every row tells you which (idealista.com, idealista.it, idealista.pt). Measured the same afternoon: Madrid for sale 17,034 listings, Rome for sale 20,660, Lisbon to rent 5,529, Madrid to rent 10,994. An id from one market is not valid in another; pass country with detail.
All three markets are the euro zone and meta echoes currency EUR on every call, alongside the resolved slug and the total. No conversion, no ambiguity.
Against us. With contract=rent the price field is the monthly rent as a plain number — 1,250, 1,900, 1,350 for Madrid flats — but there is no period, frequency or kind field anywhere on the row. You have to remember what you asked for. Store the contract you passed alongside the price.
Against us, and it is the honest answer to the question this batch is about. Idealista here is live inventory only: for sale and to rent. No sold archive, no price history, no new-listings feed. sort=newest plus your own id diff is the only change detection available.
Against us, and specific. On the rent grid, the features array came back as the site's "posted X ago" badge rather than property features: ["44 minutos"], ["1 hora"], ["2 horas"] on the first three rows. It is a relative, localized string parked in a field meant for amenities. On the sale grid the same field holds real features ("Garaje incluido") but only on 8 of 30 rows.
Against us. bathrooms was null on 30 of 30 rows in Madrid and 30 of 30 in Rome. The field is populated on detail — the same listing returned 2 bathrooms when opened. If bathrooms is part of your filter, you are paying 2 credits per listing to get it.
Against us, minor and visible. The detail feature list ends with the bare strings "Consumo:" and "Emisiones:" — the energy-certificate labels with no value attached. Drop any feature that ends in a colon.
About 30 rows a page. Page 30 of a Madrid query returned 30 fresh listings with zero overlap against page one, against a reported total of 17,034 — so roughly 568 pages exist and the ones we probed were real. stop_reason comes back on every call.
Against us. Two idealista calls issued in parallel returned a 429 with RATE_LIMITED and a "warming up" message on the second; the same call on its own succeeded. Serialize per engine — the rest of this batch tolerates two or three at once, this one does not.
geography is free. search and detail are 2 flat credits each, no per-row billing. A 30-row page and a single listing cost the same, so ask for the page.
What people build with Idealista
The jobs this data is most often used for.
endpoints
credits per call
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.
What Idealista data costs
The cheapest call here is 0 credits, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.
Full pricing →- 1,000 free credits on signup, no card
- One key, all 184 APIs, one credit pool
- Failed and blocked calls are never charged
- Credits roll over and never expire
Call it in two lines
Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.
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"])Have a question? We got answers.
The questions people actually ask before wiring up Idealista.
Get a free key →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, and 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.
11 Real Estate APIs on the same key
One key, one credit pool, one response envelope. If you are pulling Idealista, you are one call away from the rest of the category — no second contract, no second integration.
Need something this API does not do?
Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.
Try it on your own data before you pay anything
The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 183 APIs, and the same envelope everywhere.
Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-28.