Skip to content
ListingrailGet an API key

How to get Fotocasa listings in Python

By the end of this guide you have a CSV of Barcelona flats for rent from Fotocasa with rent, bedrooms, size and agency, from one script you can run again tomorrow. Everything below was run on 16 October 2026; the output table is what it returned.

Why scraping Fotocasa yourself breaks

  • Fotocasa's official integration lets agencies publish their own listings with an API key. No official API for searching or reading listings was found.
  • The search results sit as JSON inside each page (window.__INITIAL_PROPS__), one page of results at a time, so a whole city means paging through them.
  • Price filters are part of Fotocasa's own search link, so a place name alone cannot carry them.

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 Fotocasa 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":"fotocasa","location":"barcelona","type":"rent","limit":50},
    timeout=300,
)
r.raise_for_status()
listings = r.json()["listings"]

fields = ["price", "currency", "beds", "baths", "area", "address", "url"]
with open("fotocasa-barcelona.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 fotocasa-barcelona.csv")

The request body, on its own:

{
  "source": "fotocasa",
  "location": "barcelona",
  "type": "rent",
  "limit": 50
}

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

3. What comes back

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

AddressPriceSizeAgent
Pedralbes16,000 EUR / month4 bd · 3 ba · 511 m²aProperties Real Estate Barcelona
Dreta de l'Eixample4,469 EUR / month3 bd · 2 ba · 195 m²MONIKA RÜSCH
Pedralbes4,950 EUR / month4 bd · 3 ba · 191 m²OLLÉ BERTRÁN

Every listing has the same keys on all 17 portals, so the code for Fotocasa reads the others too. Fields Fotocasa 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": "fotocasa",
        "location": "barcelona",
        "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.

Fotocasa quirks worth knowing

  • Pass a Spanish city ("barcelona", "madrid"). For price filters, build the search on fotocasa.es and pass its link as location.
  • address is the neighbourhood ("Pedralbes", "El Raval"), not the street. The coordinates are in lat and lng.
  • area is in square metres as the advertiser typed it, so check for odd values: one row in this run said 1 m².
  • listed_at can be years old: the first row of this run was published in March 2024. agent.company is the agency, and agent.phone is filled when Fotocasa shows a number.

Questions

Does Fotocasa have a public API?

No. Its API is for agencies publishing their own stock to Fotocasa, Habitaclia and Milanuncios.

Does it cover homes for sale?

Yes: use "type": "sale".

Is this the same as Idealista?

No, they are separate portals. Use "source": "idealista" for Idealista; the listing format is the same.

Get 100 free listingsAPI docsOther guides