{
  "openapi": "3.0.1",
  "info": {
    "title": "Fotocasa Spain Scraper - Properties, Prices & Agents",
    "description": "Scrape Fotocasa.es property listings for sale and rent across Spain. Extract 140+ fields including prices, floor areas, bedrooms, bathrooms, addresses, GPS coordinates, agencies, phone numbers, energy ratings and photos. Covers all regions and property types.",
    "version": "1.1",
    "x-build-id": "0i9mRDhxCwcnMg9mw"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~fotocasa-es-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-fotocasa-es-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/abotapi~fotocasa-es-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-fotocasa-es-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/abotapi~fotocasa-es-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-fotocasa-es-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "Search by location/filters, or scrape a list of direct page URLs.",
            "default": "search"
          },
          "locations": {
            "title": "Locations",
            "type": "array",
            "description": "Place names or location slugs (Search mode only). Type a place such as 'Valencia' or 'Alcalá de Henares' and it is resolved on fotocasa.es (the run stops with a clear error if nothing matches), or use a slug such as 'madrid-capital', 'valencia-provincia' or 'madrid-capital/centro'. Leave empty (or use 'espana') for all of Spain.",
            "items": {
              "type": "string"
            }
          },
          "operation": {
            "title": "Operation",
            "enum": [
              "comprar",
              "alquiler",
              "compartir",
              "opcion-compra",
              "traspaso"
            ],
            "type": "string",
            "description": "Buy, rent, share, rent with option to buy, or business transfer (Search mode only). Share, rent-to-buy and transfer cover homes (share, rent-to-buy) and premises (transfer); other property types fall back to that default.",
            "default": "comprar"
          },
          "propertyType": {
            "title": "Property Type",
            "enum": [
              "viviendas",
              "pisos",
              "casas",
              "duplex",
              "aticos",
              "estudios",
              "lofts",
              "garajes",
              "trasteros",
              "locales",
              "oficinas",
              "naves",
              "terrenos",
              "edificios"
            ],
            "type": "string",
            "description": "Property category (Search mode only).",
            "default": "viviendas"
          },
          "sortBy": {
            "title": "Sort By",
            "enum": [
              "relevance",
              "newest",
              "price_asc",
              "price_desc",
              "surface_asc",
              "surface_desc"
            ],
            "type": "string",
            "description": "Result order (Search mode only).",
            "default": "relevance"
          },
          "minPrice": {
            "title": "Min Price (EUR)",
            "minimum": 0,
            "type": "integer",
            "description": "Minimum price filter. Leave empty for no minimum."
          },
          "maxPrice": {
            "title": "Max Price (EUR)",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum price filter. Leave empty for no maximum."
          },
          "minRooms": {
            "title": "Min Rooms",
            "minimum": 0,
            "maximum": 20,
            "type": "integer",
            "description": "Minimum number of rooms."
          },
          "maxRooms": {
            "title": "Max Rooms",
            "minimum": 0,
            "maximum": 20,
            "type": "integer",
            "description": "Maximum number of rooms."
          },
          "minBaths": {
            "title": "Min Bathrooms",
            "minimum": 0,
            "maximum": 20,
            "type": "integer",
            "description": "Minimum number of bathrooms."
          },
          "maxBaths": {
            "title": "Max Bathrooms",
            "minimum": 0,
            "maximum": 20,
            "type": "integer",
            "description": "Maximum number of bathrooms."
          },
          "minSurface": {
            "title": "Min Surface (m²)",
            "minimum": 0,
            "type": "integer",
            "description": "Minimum surface in square metres."
          },
          "maxSurface": {
            "title": "Max Surface (m²)",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum surface in square metres."
          },
          "publicationDate": {
            "title": "Published within",
            "enum": [
              "",
              "last48h",
              "lastWeek",
              "lastMonth"
            ],
            "type": "string",
            "description": "Keep only listings published within the window (Search mode only). Applied to the scraped rows, so combine with Sort By = Newest for the fullest coverage.",
            "default": ""
          },
          "latitude": {
            "title": "Radius centre latitude",
            "minimum": -90,
            "maximum": 90,
            "type": "number",
            "description": "With longitude, keep only listings within Radius (km) of this point (Search mode only)."
          },
          "longitude": {
            "title": "Radius centre longitude",
            "minimum": -180,
            "maximum": 180,
            "type": "number",
            "description": "Longitude of the radius centre."
          },
          "distanceKm": {
            "title": "Radius (km)",
            "minimum": 1,
            "type": "integer",
            "description": "Radius around the centre point; 20 km when a centre is set and this is empty."
          },
          "rentalTypes": {
            "title": "Rental types",
            "type": "array",
            "description": "Rent only: long-term and/or temporary rentals. Empty or both = no restriction.",
            "items": {
              "type": "string",
              "enum": [
                "longTerm",
                "temporary"
              ],
              "enumTitles": [
                "Long term",
                "Temporary"
              ]
            }
          },
          "urls": {
            "title": "Search URLs",
            "type": "array",
            "description": "fotocasa.es pages to scrape (URL mode only; filter fields are ignored, the URL's own sort and filters apply on every page). Supported: search pages (city, zone, street area, province, nationwide, rent, rent-to-buy, shared rooms, new build, any property category, /l/N pages, sort and filter query strings, the /en/ and /ca/ language versions), agency pages (/es/pro/<agency>, one page, and legacy inmobiliaria links) and single listing pages ending in /d. A listing page is fetched once. Unsupported URLs (m.fotocasa.es, paths without /es/, /en/ or /ca/, other obra-nueva forms) are skipped with a warning in the log. The default lists one example of every supported shape.",
            "default": [
              "https://www.fotocasa.es/es/comprar/viviendas/madrid-capital/todas-las-zonas/l",
              "https://www.fotocasa.es/es/comprar/viviendas/madrid-capital/todas-las-zonas/l/2",
              "https://www.fotocasa.es/es/alquiler/viviendas/madrid-capital/todas-las-zonas/l",
              "https://www.fotocasa.es/es/comprar/viviendas/madrid-capital/arganzuela/l",
              "https://www.fotocasa.es/es/comprar/viviendas/madrid-provincia/todas-las-zonas/l",
              "https://www.fotocasa.es/es/comprar/viviendas/area/calle-tropico-madrid-capital/l",
              "https://www.fotocasa.es/es/comprar/pisos/madrid-capital/todas-las-zonas/banco/l",
              "https://www.fotocasa.es/es/comprar/viviendas/espana/todas-las-zonas/obra-nueva/l",
              "https://www.fotocasa.es/es/alquiler-con-opcion-a-compra/viviendas/madrid-capital/todas-las-zonas/l",
              "https://www.fotocasa.es/es/compartir/viviendas/madrid-capital/todas-las-zonas/l",
              "https://www.fotocasa.es/es/comprar/viviendas/barcelona-capital/todas-las-zonas/l?sortType=price&sortOrderDesc=false",
              "https://www.fotocasa.es/es/comprar/viviendas/madrid-capital/todas-las-zonas/l?maxPrice=300000&minRooms=2",
              "https://www.fotocasa.es/es/comprar/viviendas/madrid-capital/todas-las-zonas/l?latitude=40.4&longitude=-3.7&combinedLocationIds=724,14,28,173,0,28079,0,0,0",
              "https://www.fotocasa.es/en/buy/homes/madrid-capital/all-zones/l",
              "https://www.fotocasa.es/ca/comprar/habitatges/madrid-capital/totes-les-zones/l",
              "https://www.fotocasa.es/es/comprar/vivienda/madrid-capital/aire-acondicionado-calefaccion-zona-comunitaria-ascensor-amueblado/189471770/d",
              "https://www.fotocasa.es/es/pro/espigul-immobiliaria/"
            ],
            "items": {
              "type": "string"
            }
          },
          "fetchDetails": {
            "title": "Fetch full details",
            "type": "boolean",
            "description": "Adds energy certificate, full feature list, reference, agent/contact name and email from the listing detail page. Slower and increases cost per listing.",
            "default": false
          },
          "maxListings": {
            "title": "Max items",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum total listings to scrape. This is the run cap. Set 0 for unlimited.",
            "default": 20
          },
          "maxPages": {
            "title": "Max Pages Per Search",
            "minimum": 0,
            "type": "integer",
            "description": "Optional safety limit on result pages walked per search (~31 listings/page). This does NOT cap the run; leave empty (or 0) for unlimited and let Max items decide when to stop. Only set a value to hard-stop pagination earlier than Max items."
          },
          "proxy": {
            "title": "Proxy Configuration",
            "type": "object",
            "description": "Proxy used for all requests. Residential proxy with a Spanish (ES) exit is enabled by default, which fotocasa.es requires for reliable access.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ],
              "apifyProxyCountry": "ES"
            }
          },
          "residentialCountries": {
            "title": "Residential fallback countries",
            "type": "array",
            "description": "Country codes used for the residential proxy. fotocasa.es requires a Spanish (ES) exit; change only if you have a specific reason.",
            "default": [
              "ES"
            ],
            "items": {
              "type": "string"
            }
          },
          "maxResidentialRequests": {
            "title": "Residential request budget",
            "minimum": 0,
            "type": "integer",
            "description": "Caps how many requests may use the residential proxy in one run, to control cost. Once spent, the run continues on the standard Apify pool. Set 0 to disable the residential tier entirely.",
            "default": 10000
          },
          "backupProxyUrl": {
            "title": "Backup proxy URL",
            "type": "string",
            "description": "Optional. A full proxy URL used as a last-resort failover when the Apify proxy is unavailable (for example on a restricted plan). Leave blank to use the built-in default gateway."
          },
          "resumeFromRunId": {
            "title": "Resume from run ID",
            "type": "string",
            "description": "Optional: paste a previous run ID (or its dataset ID) to continue that run. Listings already saved there are skipped, so this run only adds new ones. For recurring daily/weekly monitoring of the same search, use Incremental mode below instead."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn this on for daily or recurring monitoring. The first run returns all matching listings as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED listings. Compared between runs: price, reduced price, surface, rooms, bathrooms, location, title, description, features, availability flags and agency/contact summary fields (changedFields names what moved). Never compared (but still returned): photo/media URLs (multimedia, images, imageUrl, previewImage, photoUrls), per-session visited/favourite flags and the listing-age object (date) and the daily age counter in dateOriginal (diff, unit), the derived zipCode and publicationDate, the raw agency profile object, plus anything you add in Ignore fields. Turn on \"Emit unchanged\" or \"Emit expired\" only when you also want those listings returned (and billed). State is kept separately for each search/URL and filter/detail setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from run ID above.",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional, incremental mode only)",
            "type": "string",
            "description": "Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the search/URL and filter/detail settings — different searches then never mix state with each other."
          },
          "emitUnchanged": {
            "title": "Emit unchanged listings (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return listings that have not changed since the last run, marked UNCHANGED. This returns — and bills — extra rows you already have, so leave it off unless you specifically want the full snapshot every run.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired listings (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return listings that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search — not when Max items capped it or when Resume was used. This returns — and bills — extra synthetic rows, so leave it off unless you need expiry tracking.",
            "default": false
          },
          "changeScope": {
            "title": "What counts as a change (incremental mode only)",
            "enum": [
              "all",
              "priceAndStock"
            ],
            "type": "string",
            "description": "All fields (default): any compared field moving makes a listing UPDATED. Price and availability only: only price, reduced price, price per m2, price type and occupied/discarded flags count; every other edit (description, photos, agency) leaves the listing UNCHANGED, so a price monitor is not billed for them. Listings are still returned in full unless Compact updates is on.",
            "default": "all"
          },
          "compactUpdates": {
            "title": "Compact UPDATED/EXPIRED rows (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. When on, UPDATED and EXPIRED rows carry only ids, url, title, current price and a priceChanges object with old and new values. NEW rows stay complete. Compact rows carry no detail-page data, so the detail enrichment charge is not applied to them.",
            "default": false
          },
          "expireAfterMissedScans": {
            "title": "Expire after N missed scans (incremental mode only)",
            "minimum": 1,
            "type": "integer",
            "description": "Default 1: a listing missing from one complete scan is marked EXPIRED (when Emit expired is on). Raise it to wait for N consecutive complete scans before expiring. EXPIRED means the listing was not found in the search results, not proof that it was delisted or sold.",
            "default": 1
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "Optional. Field names (dotted paths such as address.city are supported) that must never make a listing UPDATED or appear in changedFields. The fields are still returned. Photo URLs, visited/favourite flags and the daily listing-age counters are already ignored by default.",
            "items": {
              "type": "string"
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON. The complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com)."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on items written to each connector per run. Does not affect the dataset.",
            "default": 50
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}