Skip to content
ListingrailGet an API key

How to get Idealista listings in Python

By the end of this guide you have a CSV of Madrid flats to rent, with size, rooms and the advertiser, from one script you can run again tomorrow. Everything below was run on 15 October 2026; the output table is what it returned.

Why scraping Idealista yourself breaks

  • Idealista has an official search API, but a key is given by hand after you describe your project.
  • The website is protected by DataDome. A plain request from a cloud server gets HTTP 403 before any listing is sent.
  • Results are HTML cards rather than a JSON blob, so a scraper also has to keep up with Idealista's markup.
  • Spain, Italy and Portugal are three separate sites with their own place names.

None of that is impossible, but each point is code you then maintain. The rest of this guide uses Listingrail, which does the reading and hands back clean JSON. The Idealista API page has the official options with sources.

1. Get a key

One request with your email returns a key with 100 free listings. It is shown once, so keep it in an environment variable.

curl -X POST https://listingrail.com/v1/signup \
  -H "content-type: application/json" \
  -d '{"email": "you@example.com"}'

export LISTINGRAIL_KEY=re_...

2. Search and save to CSV

Install requests (pip install requests), then run:

import csv
import os

import requests

r = requests.post(
    "https://listingrail.com/v1/listings/search",
    headers={"Authorization": f"Bearer {os.environ['LISTINGRAIL_KEY']}"},
    json={"source":"idealista","location":"madrid","type":"rent","limit":50},
    timeout=300,
)
r.raise_for_status()
listings = r.json()["listings"]

fields = ["price", "currency", "beds", "baths", "area", "address", "url"]
with open("idealista-madrid.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(fields)
    for home in listings:
        writer.writerow([home[k] for k in fields])

print(len(listings), "listings saved to idealista-madrid.csv")

The request body, on its own:

{
  "source": "idealista",
  "location": "madrid",
  "type": "rent",
  "limit": 50
}

Each listing returned costs one credit. A search that finds nothing, or fails at Idealista, costs nothing. A request can take up to a minute or two, because Idealista is read at that moment.

3. What comes back

The first three rows of the run on 15 October 2026:

AddressPriceSizeAgent
Piso en Calle de Cervantes, 38, Huertas-Cortes, Madrid2,450 EUR / month2 bd · 1 ba · 90 m²Lucía
Piso en Calle de Bocángel, 42, Fuente del Berro, Madrid1,450 EUR / month1 bd · 1 ba · 80 m²Marta
Ático en Calle de Pegaso, 30, Canillas, Madrid1,299 EUR / month0 bd · 1 ba · 45 m²COHABIS LIVING

Every listing has the same keys on all 17 portals, so the code for Idealista reads the others too. Fields Idealista does not show come back as null, and the portal's own record sits in raw. With pandas:

import pandas as pd

df = pd.DataFrame(listings)
df["agent"] = df["agent"].str.get("company")
print(df[["price", "beds", "baths", "area", "address", "agent"]].head())

4. Get new listings and price cuts every day

Running the script on a schedule works, but then you compare the files yourself. A monitor stores the search, checks it once a day, and sends only what changed: new listings and price cuts. The free key holds one monitor.

requests.post(
    "https://listingrail.com/v1/monitors",
    headers={"Authorization": f"Bearer {os.environ['LISTINGRAIL_KEY']}"},
    json={
        "source": "idealista",
        "location": "madrid",
        "filters": {"type":"rent"},
        "webhook_url": "https://example.com/new-listings",
    },
    timeout=30,
)

Changes can also be read with GET /v1/monitors/{id}/changes or downloaded as CSV. Plans and limits are on the monitors page.

Idealista quirks worth knowing

  • Pass a place name: "madrid", "roma, it" or "lisboa, pt". For price filters, pass an Idealista search link as location.
  • beds 0 means a studio. area is in square metres.
  • address starts with the property type in Spanish, as Idealista shows it ("Piso en ...", "Ático en ...").
  • agent.name is the advertiser: an agency name, or a first name when a private person advertises.

Questions

How do I get an Idealista API key?

Apply on Idealista's developer page and describe your project. Keys are approved by hand. Listingrail gives you a key at once by email, with 100 free listings.

Does it work for Italy and Portugal?

Yes. Add the country to the place name, for example "roma, it" or "lisboa, pt".

Why do I get 403 when I scrape Idealista?

Idealista's bot protection refuses most requests that do not come from a normal browser on a home connection.

Get 100 free listingsAPI docsOther guides