# Fotocasa API scraper — Spanish property data: for-sale and rental listings across Spain with the site's own filters (price, rooms, bathrooms, surface, property type, condition, new-build, amenities, keywords, sort), full property detail (price and price per m², rooms, surface, floor, orientation, condition, energy certificate, features, every photo, coordinates and the listing agency), agency profiles with their live stock, and location autocomplete — from fotocasa.es, Spain's #2 property marketplace. No API key, no login.

> Resolve a Spanish place name, district, postcode or street to fotocasa locations. Returns up to ten ranked matches with the combined-location id that `search` takes, the administrative level, and coordinates.
> ReefAPI engine `fotocasa` · 4 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/fotocasa/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed calls are free except verified SHEIN NOT_FOUND on product/detail and price (4 credits).
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http). Send the key as `Authorization: Bearer <key>`, or put it in the URL (`?key=<key>`) when the client has no header field, as ChatGPT does.

## Endpoints

### POST https://api.reefapi.com/fotocasa/v1/location_search — 1 credit
Resolve a Spanish place name, district, postcode or street to fotocasa locations. Returns up to ten ranked matches with the combined-location id that `search` takes, the administrative level, and coordinates.

**Parameters:**
- `query` (string, required) — Place to resolve: a town, district, neighbourhood, province, postcode or street, in Spanish.
- `limit` (integer, optional, default 10) — How many matches to return. Fotocasa always computes ten, so ten is also the ceiling.

**Returns:** matches[]{name, display_name, level (PROVINCE/MUNICIPALITY/DISTRICT/NEIGHBORHOOD/ZIP_CODE/STREET…), location_id (pass to search; null for zip-code and street matches, which fotocasa does not make searchable), location_code, latitude, longitude, has_children, searchable}, count

**Example request body:**
```json
{
  "query": "Madrid"
}
```

### POST https://api.reefapi.com/fotocasa/v1/search — 2 credits
Search Spanish property listings by location — for sale or to rent — with fotocasa's own filters: price range, rooms, bathrooms, surface, property type, state of repair, new-build vs resale, amenities, free text and sort order. Location is mandatory in one of four forms (location, location_slug, location_id or url). 30 listings per page; paginate with page/max_pages.

**Parameters:**
- `location` (string, optional) — Where to search — REQUIRED unless you pass location_slug, location_id or url. Free text in Spanish ('Madrid', 'Chamberí, Madrid', 'Las Rozas de Madrid', 'Bilbao'): it is resolved through fotocasa's own location service and the match that was used is reported in meta.location_resolved. Spain is searched by place, so one of these four location inputs must always be supplied.
- `location_slug` (string, optional) — A fotocasa location slug, used verbatim as the URL segment and therefore the cheapest option (no resolver call). Examples: madrid-capital, barcelona-capital, bilbao, valencia-capital, malaga, las-rozas-de-madrid, espana. Note the pattern: 'madrid' is the PROVINCE and 'madrid-capital' is the city.
- `location_id` (string, optional) — A fotocasa combined-location id, exactly as location_search returns it (nine comma-separated numbers). This targets a province, town, district or neighbourhood precisely. Zip-code and street suggestions do NOT carry one and cannot be used here.
- `zone` (string, optional, default "todas-las-zonas") — District/zone slug inside the location (default todas-las-zonas = the whole town). Only meaningful together with location_slug.
- `transaction` (enum, optional, default "buy") — Sale or rental market. Default buy. [one of: buy, rent, comprar, alquiler, sale, for-sale, to-rent]
- `property_type` (enum, optional, default "viviendas") — Which fotocasa catalogue to search. These are the segments the site itself serves; anything else is rejected rather than quietly returning the wrong catalogue. [one of: viviendas, pisos, aticos, chalets, duplex, estudios, garajes, locales, oficinas, naves-industriales, terrenos, trasteros, edificios, homes, flats, houses, land, offices]
- `price_min` (integer, optional) — Minimum price in EUR (monthly rent when transaction=rent).
- `price_max` (integer, optional) — Maximum price in EUR (monthly rent when transaction=rent).
- `rooms_min` (integer, optional) — Minimum number of rooms (bedrooms).
- `rooms_max` (integer, optional) — Maximum number of rooms (bedrooms).
- `bathrooms_min` (integer, optional) — Minimum number of bathrooms.
- `bathrooms_max` (integer, optional) — Maximum number of bathrooms.
- `surface_min` (integer, optional) — Minimum built surface in m².
- `surface_max` (integer, optional) — Maximum built surface in m².
- `features` (array, optional) — Amenities the property must have — ALL of them (fotocasa intersects them: lift + pool returned 1 170 of 11 979 Madrid listings). Pass a list or a comma-separated string; a raw numeric fotocasa feature id is also accepted. Note that swimming_pool matches a COMMUNAL pool as well as a private one — 26 of the 31 rows on the first filtered page came back with the amenity `community_pool`. [one of: air_conditioning, balcony, furnished, garden, heating, laundry_room, lift, parking, parquet, patio, storage_room, swimming_pool, terrace, wardrobes]
- `condition` (array, optional) — State of repair. Several values may be combined. [one of: almost_new, for_renovation, good, needs_renovation, new_home, refurbished, very_good]
- `construction` (enum, optional) — New build vs resale. On Madrid this split 270 vs 11 713 of 11 984. [one of: new_build, second_hand, any]
- `extras` (array, optional) — Listing-level flags fotocasa filters on: price_drop, bank_owned, with_videos, with_video_or_virtual_tour, quality_seal, subsidised_housing and friends. [one of: bank_owned, finished, price_drop, quality_seal, subsidised_housing, with_building_specs, with_photos, with_video_or_virtual_tour, with_videos]
- `subtypes` (array, optional) — Numeric fotocasa property-subtype ids to include (UNION, unlike features): 2 apartment, 3 house/chalet, 5 semi-detached, 6 penthouse, 7 duplex, 8 loft, 9 rural, 52 ground floor, 54 studio, 14/58/59/60 land. Usually the property_type segment is easier; this exists for combinations the segments cannot express.
- `keywords` (string, optional) — Free-text term matched against the listing (Spanish). 'piscina' cut Madrid from 11 984 to 1 704.
- `sort` (enum, optional) — Result order. These four are the orders fotocasa actually serves — its other sort keys return a server error, so they are not offered. [one of: relevance, newest, price_asc, price_desc]
- `page` (integer, optional, default 1) — First page to fetch (30 listings per page). Fotocasa stops at page 333; beyond that it silently re-serves page 333, so deeper requests are refused here instead.
- `max_pages` (integer, optional, default 1) — How many consecutive pages to fetch in one call (1-20). Each page is one upstream request.
- `include_promoted` (boolean, optional, default true) — Fotocasa injects ONE extra promoted listing above each results page (31 rows where its own page size is 30) and rotates it per request. It is a real property, so it is returned by default flagged `promoted: true` and counted in meta.promoted_count. Set false to receive only the 30 organic rows.
- `url` (string, optional) — Alternatively paste a fotocasa search URL straight from the browser; its path and query are used as-is and page/max_pages still apply.

**Returns:** items[]{property_id, detail_url, promoted, transaction, property_type, property_subtype, price, price_display, price_period, price_per_m2, rooms, bathrooms, surface_m2, floor (+floor_code), orientation, condition, antiquity, amenities[], address{}, latitude, longitude, images[], published_at, days_online, description, agency{}}, count, total_results (fotocasa's own market total), promoted_count, page_size, pages_fetched, location{slug, zone, literal, resolved}, filters_applied, stop_reason

**Example request body:**
```json
{
  "location_slug": "madrid-capital"
}
```

### POST https://api.reefapi.com/fotocasa/v1/property_detail — 2 credits
The full fotocasa listing: price and price per m², rooms, bathrooms, surface and land surface, floor, orientation, state of repair, age band, heating and hot-water type, energy-performance certificate, the agency's own feature list, the whole description, every photo, exact-or-approximate coordinates, breadcrumbs and the listing agency.

**Parameters:**
- `property_id` (string, optional) — Fotocasa property id — the digits before /d in a listing URL, or a search result's property_id.
- `url` (string, optional) — Alternatively the full fotocasa listing URL. Pass this OR property_id.
- `transaction` (enum, optional, default "buy") — Sale or rental market. Default buy. [one of: buy, rent, comprar, alquiler, sale, for-sale, to-rent]
- `property_type` (enum, optional, default "viviendas") — Which fotocasa catalogue to search. These are the segments the site itself serves; anything else is rejected rather than quietly returning the wrong catalogue. [one of: viviendas, pisos, aticos, chalets, duplex, estudios, garajes, locales, oficinas, naves-industriales, terrenos, trasteros, edificios, homes, flats, houses, land, offices]

**Returns:** listing{property_id, title, url, price, price_per_m2, price_period, rooms, bathrooms, surface_m2, land_surface_m2, floor, orientation, condition, antiquity, heating, hot_water, has_lift, furnished, energy_certificate{}, extra_features[], description, reference, published_at, address{}, latitude, longitude, coordinates_are_exact, images[], breadcrumbs[], agency{}}

**Example request body:**
```json
{
  "property_id": "184662317"
}
```

### POST https://api.reefapi.com/fotocasa/v1/agency — 1 credit
An estate agency's fotocasa profile and its live stock: address, town, website, opening hours, quality seal and registration numbers, plus the listings it is advertising (15 per page, same listing shape as search).

**Parameters:**
- `agency` (string, required) — Agency slug as it appears in its fotocasa profile URL (/es/pro/<slug>/), or the full profile URL. Every search result carries it as agency.profile_url.
- `page` (integer, optional, default 1) — Agency listing page (15 listings per page).
- `transaction` (enum, optional, default "buy") — Sale or rental market. Default buy. [one of: buy, rent, comprar, alquiler, sale, for-sale, to-rent]
- `property_type` (enum, optional, default "viviendas") — Which fotocasa catalogue to search. These are the segments the site itself serves; anything else is rejected rather than quietly returning the wrong catalogue. [one of: viviendas, pisos, aticos, chalets, duplex, estudios, garajes, locales, oficinas, naves-industriales, terrenos, trasteros, edificios, homes, flats, houses, land, offices]

**Returns:** agency{name, slug, description, address, town, province, zip_code, website, logo, created_at, has_quality_seal, official_registrations[], business_hours{}, latitude, longitude}, items[] (as search), count, total_listings, page

**Example request body:**
```json
{
  "agency": "olisson-club"
}
```

## At scale
- **Volume:** 5M+ requests a day, measured at 60 requests a second across the fleet with no
  central bottleneck. Per-key limits are raised for high-volume accounts; volume pricing on request.
- **Missing a source:** tell us a site we do not cover and it becomes an engine. A customer asked
  for bestprice.gr on 21 Sep 2026 and it was in the catalog on 22 Sep.
- **Support:** 2 minute median time from a question in the live chat to the first answer. Setup
  help included, no support tier to buy.
- **One key, one credit pool** across every API. No per-site plans, no separate subscriptions.

## More
- Try it live, no code: https://reefapi.com/playground?engine=fotocasa
- Human docs page: https://reefapi.com/docs/fotocasa
- Overview page: https://reefapi.com/fotocasa-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
