# Fotocasa Property Listings Extractor (`kawsar/fotocasa-property-listings-extractor`) Actor

Scrape Fotocasa property listings from any search URL and get prices, rooms, size, location, agency contact and images as structured data you can export or pull into your own tools.

- **URL**: https://apify.com/kawsar/fotocasa-property-listings-extractor.md
- **Developed by:** [Kawsar](https://apify.com/kawsar) (community)
- **Categories:** Real estate, Automation, Developer tools
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Fotocasa Property Listings Extractor

Scrape property listings from [Fotocasa.es](https://www.fotocasa.es), one of Spain's largest real estate portals, straight from any search results page. Apply your filters on Fotocasa, paste the URL, and get every listing back as clean, structured data you can export or feed into your own tools.

No browser to babysit, no copy and paste. Give the actor a search URL and it returns each property already parsed into fields: prices, sizes, addresses, agency contacts, and image galleries.

### Table of contents

- [What it does](#what-it-does)
- [Key features](#key-features)
- [Use cases](#use-cases)
- [Input](#input)
- [How to get a Fotocasa search URL](#how-to-get-a-fotocasa-search-url)
- [Output](#output)
- [Output fields](#output-fields)
- [How to run it](#how-to-run-it)
- [Using the data](#using-the-data)
- [Performance and limits](#performance-and-limits)
- [FAQ](#faq)
- [Disclaimer](#disclaimer)

### What it does

Fotocasa shows listings across sales, rentals, and new construction. This actor reads the same data the results page displays and turns it into rows you can work with. Point it at a search for flats in Madrid under 300,000 euros, houses for rent in Valencia, or new builds in Barcelona, and it collects each property on the page: the asking price, price per square meter, room and bathroom counts, floor, surface area, the full address down to the neighborhood, map coordinates, the listing agency and its phone number, how long the listing has been live, the description, and the full image gallery.

It walks through as many result pages as you ask for, handles several searches in one run, and removes duplicate listings automatically so you get a clean dataset.

### Key features

- **Works from any search URL.** Filter on Fotocasa the way you normally would, then paste the URL. Whatever the search returns is what you get.
- **Full listing detail.** Price, price per square meter, rooms, bathrooms, surface, floor, address, coordinates, agency contact, publish date, description, and every image.
- **Multi-page crawling.** Set how many result pages to walk through per search.
- **Batch several searches.** Pass a list of URLs and collect them all in one run.
- **Automatic de-duplication.** Listings that repeat across pages are dropped by listing ID.
- **Resilient runs.** If one page fails to load, the run keeps going with the rest.
- **Clean exports.** Download as JSON, CSV, Excel, or XML, or pull straight from the Apify API.

### Use cases

- **Market research.** Track asking prices and price per square meter across a city or neighborhood over time.
- **Investment analysis.** Build a dataset of active listings to spot undervalued properties or yield opportunities.
- **Competitor and agency monitoring.** See what agencies are listing, at what prices, and how long stock stays on the market.
- **Lead generation.** Collect agency names and phone numbers tied to specific areas or property types.
- **Valuation and comparables.** Gather comparable listings to support pricing decisions.
- **Data pipelines.** Feed listings into a CRM, spreadsheet, database, or dashboard on a schedule.

### Input

The actor takes a few simple fields. Only a search URL is required to start.

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `searchUrl` | string | Yes | - | A Fotocasa search results page URL. Apply filters on Fotocasa first, then paste the URL. |
| `searchUrls` | array | No | `[]` | Optional list of extra search URLs to run in the same job. |
| `maxPages` | integer | No | `1` | How many result pages to walk through per search URL. Each page holds about 30 listings. |
| `maxItems` | integer | No | `100` | Cap on total listings collected per run, across all search URLs. Max 1000. |
| `requestTimeoutSecs` | integer | No | `30` | Per-request timeout in seconds. |

#### Example input

```json
{
    "searchUrl": "https://www.fotocasa.es/es/comprar/viviendas/madrid-capital/todas-las-zonas/l",
    "searchUrls": [
        "https://www.fotocasa.es/es/alquiler/viviendas/valencia-capital/todas-las-zonas/l"
    ],
    "maxPages": 3,
    "maxItems": 200,
    "requestTimeoutSecs": 30
}
```

### How to get a Fotocasa search URL

1. Open [fotocasa.es](https://www.fotocasa.es) in your browser.
2. Search a location and choose buy or rent.
3. Apply the filters you want: price range, number of rooms, property type, features.
4. Copy the URL from the address bar once the results load.
5. Paste it into the `searchUrl` field.

A few real examples:

- Flats for sale in Madrid: `https://www.fotocasa.es/es/comprar/viviendas/madrid-capital/todas-las-zonas/l`
- Homes for rent in Barcelona: `https://www.fotocasa.es/es/alquiler/viviendas/barcelona-capital/todas-las-zonas/l`
- Filtered search with a keyword: `https://www.fotocasa.es/es/comprar/viviendas/espana/todas-las-zonas/l?text=la`

The page number lives in the URL path (`/l` for the first page, `/l/2` for the second, and so on). You do not need to add it yourself. Set `maxPages` and the actor handles paging for you.

### Output

Every listing becomes one dataset record. Here is a real example of a single item:

```json
{
    "id": 190410253,
    "transactionType": "buy",
    "propertyType": "Flat",
    "propertySubtype": "Flat",
    "price": "129.900 €",
    "rawPrice": 129900,
    "pricePerSqm": 2095,
    "reducedPrice": null,
    "rooms": 3,
    "bathrooms": 1,
    "surface": 62,
    "floor": 6,
    "location": "Viñuela - Rescatado",
    "neighborhood": "Viñuela - Rescatado",
    "district": "Levante",
    "municipality": "Córdoba",
    "city": "Córdoba",
    "province": "Córdoba",
    "zipCode": "14007",
    "country": "España",
    "latitude": 37.889176,
    "longitude": -4.763464,
    "agencyName": "INMOSI",
    "clientType": "professional",
    "phone": "+34623720012",
    "isNew": false,
    "isNewConstruction": false,
    "publishedDaysAgo": 14,
    "propertyDescription": "Piso amueblado en una zona con todo tipo de servicios...",
    "primaryImage": "https://static.fotocasa.es/images/ads/c499cb86-...?rule=original",
    "images": [
        "https://static.fotocasa.es/images/ads/c499cb86-...?rule=original",
        "https://static.fotocasa.es/images/ads/ab87447c-...?rule=original"
    ],
    "imageCount": 15,
    "listingUrl": "https://www.fotocasa.es/es/comprar/vivienda/cordoba-capital/.../190410253/d",
    "sourceUrl": "https://www.fotocasa.es/es/comprar/viviendas/cordoba-capital/todas-las-zonas/l",
    "scrapedAt": "2026-08-20T10:00:00+00:00"
}
```

### Output fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Fotocasa listing ID, unique per property. |
| `transactionType` | string | `buy` or `rent`. |
| `propertyType` | string | Building type, for example Flat or House. |
| `propertySubtype` | string | More specific subtype when available. |
| `price` | string | Price as shown on the site, for example `129.900 €`. |
| `rawPrice` | integer | Numeric price with no formatting. |
| `pricePerSqm` | integer | Price per square meter, calculated from price and surface. |
| `reducedPrice` | number | Previous price if the listing shows a drop, otherwise null. |
| `rooms` | integer | Number of rooms. |
| `bathrooms` | integer | Number of bathrooms. |
| `surface` | integer | Living area in square meters. |
| `floor` | integer | Floor number. |
| `location` | string | Short location label shown on the card. |
| `neighborhood` | string | Neighborhood name. |
| `district` | string | District within the municipality. |
| `municipality` | string | Municipality. |
| `city` | string | City. |
| `province` | string | Province. |
| `zipCode` | string | Postal code. |
| `country` | string | Country. |
| `latitude` | number | Map latitude. |
| `longitude` | number | Map longitude. |
| `agencyName` | string | Listing agency or advertiser name. |
| `clientType` | string | Advertiser type, for example professional or private. |
| `phone` | string | Contact phone number when published. |
| `isNew` | boolean | Whether the listing is marked as new. |
| `isNewConstruction` | boolean | Whether it is a new construction property. |
| `publishedDaysAgo` | integer | How many days ago the listing was published. |
| `propertyDescription` | string | Full listing description text. |
| `primaryImage` | string | URL of the main image. |
| `images` | array | URLs of all listing images. |
| `imageCount` | integer | Number of images. |
| `listingUrl` | string | Absolute URL of the full listing page. |
| `sourceUrl` | string | The search page URL this listing came from. |
| `scrapedAt` | string | ISO 8601 timestamp of when the record was collected. |

### How to run it

#### On the Apify platform

1. Open the actor in the Apify Console.
2. Paste a Fotocasa search URL into `searchUrl`.
3. Set `maxPages` and `maxItems` to control how much you collect.
4. Click **Start**.
5. When the run finishes, open the **Dataset** tab to preview or export the results.

### Using the data

- **Export formats.** From the run's Storage tab you can download the dataset as JSON, CSV, Excel, or XML.
- **Scheduling.** Use Apify Schedules to run the actor daily or weekly and build a price history.
- **Integrations.** Push results into Google Sheets, Airtable, a database, or a webhook using Apify integrations.
- **Analysis.** Load the CSV into a spreadsheet or a pandas DataFrame to chart prices, filter by neighborhood, or compute averages.

### Performance and limits

- Each result page carries roughly 30 listings. Raise `maxPages` to collect more from a single search.
- `maxItems` caps the total per run at 1000. Split larger jobs across several runs or several search URLs.
- Duplicate listings across pages are removed by listing ID, so counts reflect unique properties.
- Very deep searches take longer. Start with a small `maxPages` to confirm the output looks right, then scale up.

### FAQ

**Which countries does it cover?**
Fotocasa lists properties in Spain, so the data covers the Spanish market.

**Can I scrape both sales and rentals?**
Yes. Use a `comprar` (buy) URL for sales and an `alquiler` (rent) URL for rentals. The `transactionType` field tells you which is which.

**Does it return individual property pages?**
It reads listing data from search result pages, which already include the core details, images, and the link to each full listing (`listingUrl`).

**How many listings can I get in one run?**
Up to 1000 per run via `maxItems`. For more, run several jobs or pass multiple search URLs.

**Why are some fields empty?**
Not every listing publishes every detail. Fields like phone, reduced price, or floor appear only when the advertiser provides them.

**Can I run it on a schedule?**
Yes. Apify Schedules can trigger the actor at any interval, which is ideal for tracking price changes over time.

### Disclaimer

Use this actor responsibly and in line with Fotocasa's terms of service and applicable laws. It collects publicly visible listing information for research and analysis. You are responsible for how you use the data you collect.

# Actor input Schema

## `searchUrl` (type: `string`):

A Fotocasa search results page URL. Apply any filters you want on Fotocasa (location, price, rooms, property type) and paste the resulting URL here.

## `searchUrls` (type: `array`):

Optional list of extra Fotocasa search page URLs to extract in the same run.

## `maxPages` (type: `integer`):

How many result pages to walk through for each search URL. Each page holds up to about 30 listings.

## `maxItems` (type: `integer`):

Maximum number of listings to collect per run across all search URLs.

## `requestTimeoutSecs` (type: `integer`):

Per-request timeout in seconds.

## Actor input object example

```json
{
  "searchUrl": "https://www.fotocasa.es/es/comprar/viviendas/madrid-capital/todas-las-zonas/l",
  "searchUrls": [
    "https://www.fotocasa.es/es/comprar/viviendas/barcelona-capital/todas-las-zonas/l",
    "https://www.fotocasa.es/es/alquiler/viviendas/valencia-capital/todas-las-zonas/l"
  ],
  "maxPages": 1,
  "maxItems": 100,
  "requestTimeoutSecs": 30
}
```

# Actor output Schema

## `properties` (type: `string`):

Scrape Fotocasa property listings from any search URL: prices, rooms, size, address, agency contact and images as structured data.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchUrl": "https://www.fotocasa.es/es/comprar/viviendas/madrid-capital/todas-las-zonas/l",
    "searchUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("kawsar/fotocasa-property-listings-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchUrl": "https://www.fotocasa.es/es/comprar/viviendas/madrid-capital/todas-las-zonas/l",
    "searchUrls": [],
}

# Run the Actor and wait for it to finish
run = client.actor("kawsar/fotocasa-property-listings-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchUrl": "https://www.fotocasa.es/es/comprar/viviendas/madrid-capital/todas-las-zonas/l",
  "searchUrls": []
}' |
apify call kawsar/fotocasa-property-listings-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kawsar/fotocasa-property-listings-extractor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/0xiar0MYFp4Lwk3N2/builds/IfKgaXS2gfVeSKCpd/openapi.json
