# Pisos.com Property Scraper — Spain Real Estate (`sian.agency/pisos-property-scraper`) Actor

Pull Spanish property adverts from pisos.com by place: asking price, floor area, rooms, agency, phone, coordinates and the energy certificate. No search URL to paste.

- **URL**: https://apify.com/sian.agency/pisos-property-scraper.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** Real estate, Business, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.79 / 1,000 property searches

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Pisos.com Scraper — Spain Property Listings, Prices & Energy Certificates 🚀

[![Store SIÁN Agency](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Store Fotocasa Scraper](https://img.shields.io/badge/Store-Fotocasa%20Scraper-00A0A0)](https://apify.com/sian.agency/fotocasa-property-scraper?fpr=sian) [![Store Idealista Scraper](https://img.shields.io/badge/Store-Idealista%20Scraper-E60023)](https://apify.com/sian.agency/smart-idealista-scraper?fpr=sian) [![Store Imovirtual Scraper](https://img.shields.io/badge/Store-Imovirtual%20Scraper-1AE392)](https://apify.com/sian.agency/imovirtual-property-scraper?fpr=sian)

#### 🎉 Pick a place in Spain from a list and press start. 30 adverts per page request, energy certificate included

##### Built for property analysts, valuers, agencies and anyone building a Spanish housing dataset

### 🔎 What is the Pisos.com Spain Property Scraper — and when should you use it?

The **Pisos.com Spain Property Scraper** turns public pisos.com property adverts from anywhere in Spain into clean, structured rows you can filter, export and feed straight into a spreadsheet, database or AI agent. No account, no portal API key, no browser automation to maintain.

**Use it when you need:** Spanish sale, rental and new-development adverts as rows. Each carries the asking price or monthly rent in euros, the price per square metre, built floor area, bedrooms, bathrooms and floor. Each also carries the neighbourhood, district and municipality, GPS coordinates, the national INE municipality code, the complete advert text, the photos, and the listing agency with its contact number. Switch on the detail pass and every row gains the Spanish energy certificate: consumption and emissions ratings with the kWh/m² and kg CO₂/m² figures behind them. The detail pass also adds usable floor area as distinct from built, condition, orientation, heating, air conditioning, property age, the monthly community charge, the agency's name and its own reference code, and the date the agency last touched the advert.

**Use something else when:** the property is not on pisos.com. Use [Fotocasa Scraper](https://apify.com/sian.agency/fotocasa-property-scraper?fpr=sian) for the other big Spanish portal; measured overlap with pisos.com is only about 45%, so most Spanish datasets want both. Use [Idealista Scraper](https://apify.com/sian.agency/smart-idealista-scraper?fpr=sian) for Spain, Italy and Portugal, by search URL, map polygon or agency page. Use [Imovirtual Scraper](https://apify.com/sian.agency/imovirtual-property-scraper?fpr=sian) for Portugal, next door and the same shape of data. This actor reads the property surfaces pisos.com publishes to any visitor. That means flats, houses, penthouses, duplexes, studios, lofts and country estates, plus garages, retail units, offices, industrial units, land, whole buildings and storage rooms. Each of those comes for sale, for long-term rent, or as a new development. Seasonal and holiday lets are deliberately out of scope because the portal asks crawlers to leave that path alone. Sold prices and price history are not published by pisos.com at all, and neither is the cadastral reference.

### 🤖 Use with AI agents

Already connected to the [Apify MCP server](https://mcp.apify.com)? Just ask for this Actor by name: sian.agency/pisos-property-scraper

**Your agent can pay for its own runs.** This Actor is eligible for [agentic payments](https://docs.apify.com/platform/actors/publishing/monetize), so an agent can discover it, run it and settle the bill over [x402](https://www.x402.org/) (USDC on Base) or [Skyfire](https://www.skyfire.xyz/) — without an Apify account or API token of its own. Billing is the same either way: per successful row, never for errors.

Otherwise copy this prompt into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```text
I want Spanish property adverts and asking prices from pisos.com using the Apify Actor `sian.agency/pisos-property-scraper`.

Use it when I need: Spanish sale, rental and new-development adverts as rows. Each carries the asking price or monthly rent in euros, the price per square metre, built floor area, bedrooms, bathrooms and floor. Each also carries the neighbourhood, district and municipality, GPS coordinates, the national INE municipality code, the complete advert text, the photos, and the listing agency with its contact number. Switch on the detail pass and every row gains the Spanish energy certificate: consumption and emissions ratings with the kWh/m² and kg CO₂/m² figures behind them. The detail pass also adds usable floor area as distinct from built, condition, orientation, heating, air conditioning, property age, the monthly community charge, the agency's name and its own reference code, and the date the agency last touched the advert.

Don't use it when: the property is not on pisos.com — use fotocasa-property-scraper or smart-idealista-scraper or imovirtual-property-scraper instead.

How to call it: give `location` a place from pisos.com's own list (`madrid_capital_zona_urbana`, `barcelona_capital`, `valencia_capital_zona_urbana`, `getafe`; the picker carries the portal's provinces, comarcas, municipalities and city districts with the live advert count beside each) and set `market` to `sale`, `rent` or `newDevelopment`. `propertyType` picks one of fourteen surfaces, from `pisos` (flats, where almost all the stock is) to `locales`, `oficinas`, `garajes` and `naves`. Narrow with `minPrice`, `minRooms`, `minBathrooms` and `minAreaM2`, which go to the portal's own filter segments; `maxPrice` and `maxAreaM2` are applied to the rows instead, because pisos.com silently drops a maximum once a minimum is set, and anything a filter excludes is never saved and never billed. `sortBy` takes the portal's own orderings, which matters because one search stops at 3,000 adverts: running the same place cheapest-first and dearest-first reaches twice as far into a market bigger than that. `includeDetails` opens each advert for its energy certificate and spec sheet, one extra page request per advert. Operation `detail` takes `listingUrls` instead and returns the same detail row for adverts you already have..

Start with this input:
{
  "operation": "search",
  "location": "madrid_capital_zona_urbana",
  "market": "sale",
  "propertyType": "pisos",
  "sortBy": "fecharecientedesde-desc",
  "maxResults": 100
}

Ask me which Spanish town, province or city district you want, and whether you are after sale or rent, then run the Actor and summarise the results as a table.
```

**Things you can ask your agent for:**

- *Pull flats for sale in Salamanca, Madrid between €400,000 and €900,000 and rank the streets by median price per square metre.*
- *Find this week's new rentals in Valencia under €1,200 a month, with a phone number for each agency.*
- *Which Madrid flats on sale publish an energy rating of C or better? Include the consumption figure in kWh/m².*

Machine-readable API, MCP config and OpenAPI definition for this Actor are published at [apify.com/sian.agency/pisos-property-scraper.md](https://apify.com/sian.agency/pisos-property-scraper.md).

### 📋 Overview

**Spain's property market, read straight off pisos.com.** Asking prices, floor areas, agencies and energy certificates, for any town, district or neighbourhood the portal covers.

**What you get:**

- ✅ **A place list, not a URL box**: every entry comes from pisos.com's own geography, with the live advert count beside it. You can see what a run is worth before you start it.
- ⚡ **30 adverts per page request**: the portal renders results server-side, so one request already carries the price, the area, the agency, the coordinates and the complete advert text.
- 🎯 **Never billed twice for the same advert**: past the end of a result set pisos.com keeps answering with the same thirty adverts. This actor stops on advert IDs, not on the status code.
- 💰 **$0.90 per 1,000 adverts**: below every other pisos.com actor on the Store, which run from $1.00 to $5.00 per thousand.
- 💎 **The energy certificate**: consumption and emissions ratings, with the kWh/m² and kg CO₂/m² figures behind them. Spanish law requires it and most property scrapers never touch it.
- ✨ **Fourteen property types**: flats and houses, and also retail units, offices, garages, land, industrial units and whole buildings, each a separate market on the portal.

### ✨ Features

- 📍 **Place-first input**: pick a province, comarca, municipality or city district from the list. No browsing, no pasting.
- 🤝 **Three markets**: for sale, long-term rent, and new developments (*promociones*).
- 🏘️ **Fourteen property types**: from studios to industrial units, each with its own live stock.
- ⚡ **Energy certificates**: rating letters plus the consumption and emissions figures behind them.
- 📐 **Built area and usable area kept separate**: two different numbers on a Spanish advert, never merged into one.
- 🧭 **Coordinates and the INE municipality code**: join the rows to census, cadastral or GIS data without geocoding them yourself.
- 📞 **Agency and contact number on every advert**: build an agency list for a city from one run.
- 📝 **The complete advert text**: the full description, not a truncated preview.
- ↕️ **The portal's own orderings**: cheapest first, largest first, most bedrooms, newest advert.
- 🔗 **Paste a search link instead**: already have a pisos.com search open? The actor will walk it exactly as it stands.

### 🎬 Quick Start

Pick a place, pick sale or rent, press Start. The first adverts land in a few seconds, and the dataset exports to CSV, JSON or Excel. Everything below is optional.

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~pisos-property-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"operation":"search","location":"madrid_capital_zona_urbana","market":"sale","propertyType":"pisos","maxResults":100}'
```

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Choose where

Open the **Where in Spain** list and pick a province, a town or a city district. The number beside each name is how many adverts pisos.com had there when the list was built.

#### Step 2: Choose what

Set **Sale, rent or new build** and the **Property type**. Add a minimum price, bedroom count or floor area if you want to narrow it.

#### Step 3: Press Start

Adverts arrive as the actor walks the result pages. Turn on **Add the energy certificate and spec sheet** if you also want each advert's certificate, usable area, condition and age.

**That's it! In under a minute, you'll have:**

- Every live advert for that place, with its asking price and price per square metre
- The listing agency and a contact number for each one
- A CSV, JSON or Excel export ready for a spreadsheet or a model

### 📥 Input Configuration

| Field | Type | Required | Description |
|---|---|---|---|
| `operation` | string | No | `search` to walk a place, `detail` to open adverts you already have. Defaults to `search`. |
| `location` | string | No | A place from pisos.com's own list, e.g. `madrid_capital_zona_urbana`. |
| `market` | string | No | `sale`, `rent` or `newDevelopment`. |
| `propertyType` | string | No | `pisos`, `casas`, `aticos`, `duplexs`, `estudios`, `lofts`, `fincas_rusticas`, `garajes`, `locales`, `oficinas`, `naves`, `terrenos`, `edificios`, `trasteros`. |
| `maxResults` | integer | No | How many adverts to collect, up to the portal's own 3,000 ceiling. |
| `sortBy` | string | No | `relevance`, `asc`, `desc`, `m2-asc`, `m2-desc`, `hab-asc`, `hab-desc`, `fecharecientedesde-desc`. |
| `minPrice` / `maxPrice` | integer | No | Euros. `0` means no limit. |
| `minRooms` / `minBathrooms` | integer | No | `0` means any. |
| `minAreaM2` / `maxAreaM2` | integer | No | Built area in square metres. `0` means no limit. |
| `includeDetails` | boolean | No | Open every advert found for its energy certificate and spec sheet. |
| `listingUrls` | array | No | For `detail`: pisos.com advert links. |
| `searchUrls` | array | No | Paste a pisos.com search page and it is walked exactly as it stands. |

**Example:**

```json
{
  "operation": "search",
  "location": "madrid_capital_salamanca",
  "market": "sale",
  "propertyType": "pisos",
  "minPrice": 400000,
  "minRooms": 3,
  "maxResults": 200
}
```

**Open specific adverts:**

```json
{
  "operation": "detail",
  "listingUrls": [
    "https://www.pisos.com/comprar/piso-gaztambide-65098413759_100500/",
    "https://www.pisos.com/comprar/piso-abrantes-67504151344_101800/"
  ]
}
```

### 📤 Output

Results are saved to the Apify dataset with **55+ fields**. The most useful:

| Field | Type | Description |
|---|---|---|
| `listingId` | string | The advert key, `advertId.agencyId` |
| `url` | string | The advert on pisos.com |
| `propertyTitle` | string | The advert headline, usually the street |
| `price` | integer | Asking price, or monthly rent for rentals, in euros |
| `pricePerM2` | number | Price divided by built area |
| `builtAreaM2` | integer | Built area in square metres |
| `usableAreaM2` | integer | Usable area — a different, smaller number (detail pass) |
| `rooms` / `bathrooms` | integer | As the advert states them |
| `floorLabel` | string | Floor, e.g. `2ª planta`, `Bajo`, `Ático` |
| `neighbourhood` / `district` / `municipality` / `province` | string | The location trail |
| `municipalityCode` | string | The national INE municipality code, e.g. `28079` |
| `latitude` / `longitude` | number | Coordinates |
| `description` | string | The complete advert text |
| `agencyName` / `agencyUrl` / `contactPhone` | string | The listing agency (name on the detail pass) |
| `energyStatus` | string | `Disponible`, `En trámite` or `Pendiente de completar` |
| `energyConsumptionRating` / `energyConsumption` | string / number | Rating letter and kWh/m² per year |
| `energyEmissionsRating` / `energyEmissions` | string / number | Rating letter and kg CO₂/m² per year |
| `condition` / `orientation` / `heating` / `ageLabel` | string | From the spec sheet (detail pass) |
| `lastUpdated` | string | When the agency last touched the advert (detail pass) |
| `images` | array | Photo URLs |
| `resultTotal` | integer | How many adverts the portal declared for the whole search |

**Example:**

```json
{
  "operation": "search",
  "status": "success",
  "listingId": "67504151344.101800",
  "url": "https://www.pisos.com/comprar/piso-abrantes-67504151344_101800/",
  "propertyTitle": "Piso en calle del Pelícano",
  "market": "sale",
  "propertyType": "pisos",
  "price": 230000,
  "priceLabel": "230.000 €",
  "currency": "EUR",
  "pricePerM2": 3285.71,
  "rooms": 3,
  "bathrooms": 1,
  "builtAreaM2": 70,
  "floorLabel": "2ª planta",
  "neighbourhood": "Abrantes",
  "district": "Carabanchel",
  "municipality": "Madrid Capital",
  "province": "Madrid",
  "municipalityCode": "28079",
  "latitude": 40.3837543,
  "longitude": -3.7275486,
  "contactPhone": "919386606",
  "photoCount": 19,
  "resultTotal": 8366
}
```

### 💼 Use Cases & Examples

#### 1. Price a neighbourhood before you buy

**A private buyer or a valuer wants every asking price on one street or in one barrio, today.**

**Input:** One district, sorted cheapest first.
**Output:** Every live advert with its price, built area and €/m².
**Use:** Work out what the flat you are looking at should cost, with the comparables in a spreadsheet rather than in twenty browser tabs.

#### 2. Build a Spanish housing price series

**A research team needs asking prices tracked over time, which nobody publishes.**

**Input:** The same places on a weekly schedule.
**Output:** A dated snapshot of the market each run.
**Use:** Derive your own index, and see how long individual adverts sit before the price moves.

#### 3. Find the stock with a real energy certificate

**An energy-retrofit or ESG team needs the ratings themselves, alongside the addresses.**

**Input:** A city, with the detail pass switched on.
**Output:** Consumption and emissions ratings with the kWh/m² and kg CO₂/m² behind them.
**Use:** Size the retrofit opportunity in a district, or filter for stock that already meets a threshold. Around a third of adverts publish a rating. The rest report the certificate as in progress, and the status comes back either way.

#### 4. Build an agency list for a city

**An agency, a proptech or a supplier wants to know who is actually working a market.**

**Input:** One municipality, flats for sale.
**Output:** Every advert with its listing agency, the agency page and a contact number.
**Use:** Rank agencies by how much stock each is holding, and call the ones that matter.

#### 5. Watch new stock the day it appears

**A buying agent needs to see new listings before the weekend viewings fill up.**

**Input:** Newest advert first, a few hundred rows, on a daily schedule.
**Output:** What has appeared since the last run.
**Use:** Alert on anything matching a client brief, without re-reading the whole market each time.

#### 6. Analyse the commercial market

**An investor or a franchise wants retail units, offices or industrial space, not flats.**

**Input:** `propertyType: "locales"` or `"oficinas"` or `"naves"`.
**Output:** The same row shape, for a market residential scrapers ignore. Madrid Capital carries 1,056 retail units and 739 garages for sale.
**Use:** Compare asking rents and prices across districts before you commit to a pitch.

#### 7. Feed a valuation or mortgage model

**A data team needs thousands of clean comparables with no cleaning step.**

**Input:** A province split by district or price band.
**Output:** Coordinates, built and usable area, rooms, floor, condition, age and asking price.
**Use:** Train or back-test a valuation model on live asking prices rather than on stale public records.

### 🔗 Integration Examples

#### JavaScript/Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });

const run = await client.actor('sian.agency/pisos-property-scraper').call({
  operation: 'search',
  location: 'valencia_capital_zona_urbana',
  market: 'sale',
  propertyType: 'pisos',
  maxResults: 200,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')

run = client.actor('sian.agency/pisos-property-scraper').call(
    run_input={
        'operation': 'search',
        'location': 'barcelona_capital',
        'market': 'rent',
        'propertyType': 'pisos',
        'maxResults': 200,
    }
)

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item['price'], item['builtAreaM2'], item['url'])
```

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~pisos-property-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"operation":"search","location":"sevilla_capital","market":"sale","propertyType":"pisos","maxResults":200}'
```

#### Automation Workflows (N8N / Zapier / Make)

1. **Trigger**: a daily schedule, or a webhook from your own system
2. **HTTP Request**: call the actor's run-sync endpoint with the place you care about
3. **Process**: filter the JSON on price, area or energy rating
4. **Action**: append to a sheet, write to a database, or send an alert

### 📊 Performance & Pricing

#### FREE Tier (Try It Now)

- **25 adverts** per run — every field, every operation, same quality
- No credit card required
- Enough to see the data shape before you commit

#### PAID Tier (Production Ready)

- **Unlimited** adverts per run, up to pisos.com's own ceiling of 3,000 per search
- Pay per advert returned: an advert that fails, a search that matched nothing and anything dropped by a filter all cost you nothing

💰 **Below every rival on the board.** $0.90 per 1,000 adverts, against $1.00 to $5.00 per 1,000 for the other pisos.com actors on the Store.

🔗 [View current pricing](https://apify.com/sian.agency/pisos-property-scraper?fpr=sian)

### ❓ Frequently Asked Questions

**Q: Do I need to paste a pisos.com URL?**
A: No. Pick a place from the list and press start. You can paste a search URL if you already have one open, but nothing requires it.

**Q: How many adverts can one run return?**
A: Up to 3,000 for a single search. That is pisos.com's own limit, not ours: it stops at 100 result pages. Madrid Capital alone lists 8,369 flats for sale, so a whole-city sweep needs splitting by district, property type, price band or sort order. The run log says when you have reached it.

**Q: Will I be charged twice for the same advert?**
A: No. Past the end of a result set pisos.com keeps serving the same thirty adverts with a normal 200 response instead of stopping, so a scraper that watches the status code quietly collects duplicates. This one tracks advert IDs and stops the moment a page adds nothing new.

**Q: Which fields need the detail pass?**
A: The energy certificate, usable floor area, condition, orientation, heating, air conditioning, built-in wardrobes, property age, the community charge, the agency name and its own reference code. Everything else is already on the search row: price, built area, rooms, bathrooms, floor, coordinates, agency link, phone, photos and the full advert text.

**Q: Does every advert have an energy certificate?**
A: No. On a thirty-advert Getafe sample, 37% published a rating with its consumption and emissions figures and the rest showed the certificate as in progress. The status comes back either way, so you can tell the difference.

**Q: Are holiday and seasonal lets included?**
A: No. The portal keeps those under a path its robots.txt asks crawlers not to read, so they are deliberately out of scope. Long-term rentals are included.

**Q: How fresh is the data?**
A: It is read live at the moment the run executes. Nothing is cached and nothing is stored between runs. Schedule the actor if you want a history.

**Q: Can I get sold prices or a price history?**
A: No. pisos.com publishes live asking prices only. A history is something you build by running this on a schedule.

**Q: What output formats are available?**
A: JSON, CSV and Excel, exported directly from the Apify dataset.

### 🐛 Troubleshooting

**The run returned no adverts**

- A district holds far less stock than its city. Try the municipality instead.
- Check the property type. Madrid Capital has 8,369 flats for sale but only 2 country estates.
- Clear the price and area limits and run again.

**I asked for a price range and got everything above the minimum**

- pisos.com ignores a maximum price once a minimum is set. The actor applies that maximum itself and drops the adverts above it before they are saved or charged. The run log says so when it happens.

**I expected more than 3,000 adverts**

- That is the portal's ceiling for a single search. Split the run: by district, by property type, by price band, or run the same place twice with opposite sort orders.

**An advert link returns nothing**

- It has been sold, let or withdrawn since you collected it. Run a search over the same place for what is live today.

**The photo count is higher than the number of image URLs on a search row**

- A result page shows the first few photos of each advert and states the full count. The detail pass returns the whole gallery.

### ⚖️ Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the **GDPR** in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

pisos.com is a trademark of its owner. This actor is an independent tool, is not affiliated with or endorsed by the portal, and reads only pages that are public to any visitor.

### 🤝 Support

**Join our active support community**

- For issues or questions, open an issue in the actor's repository
- Check [SIÁN Agency Store](https://apify.com/sian.agency?fpr=sian) for more automation tools
- 📧 <apify@sian-agency.online>

***

**Built by [SIÁN Agency](https://www.sian-agency.online)** | **[More Tools](https://apify.com/sian.agency?fpr=sian)**

# Changelog

This Actor's version history is a separate document: https://apify.com/sian.agency/pisos-property-scraper/changelog.md

# Actor input Schema

## `operation` (type: `string`):

Two ways in. **Property search** takes a Spanish place from the portal's own index, a market (sale, rent or new development) and a property type, then walks the result pages and returns every advert with its price, area, rooms, agency, phone, coordinates and full advert text. **Property detail** opens one advert on its own page and adds the parts a result card leaves out: usable floor area as well as built area, the energy certificate, condition, orientation, heating, age, the community charge…

## `location` (type: `string`):

Pick from pisos.com's own place list — provinces, comarcas, municipalities and the districts of the big cities. The number beside each name is how many adverts the portal had there when this list was built, so you can see what a run will be worth before you start it. A picked place always exists; a typed one does not, which is why this is a list and not a text box.

## `market` (type: `string`):

For sale and long-term rent are the two big markets. New developments are the promociones the portal lists separately — whole projects rather than individual flats. Seasonal and holiday lets are deliberately not offered: they sit behind a path the portal asks crawlers to leave alone.

## `propertyType` (type: `string`):

Flats is where almost all the stock is — 8,369 of Madrid Capital's adverts against 364 houses — but the commercial types are real markets too: the same city carries 1,056 retail units, 739 garages and 169 offices. Each type is a separate search on the portal, so pick the one you want rather than filtering afterwards.

## `maxResults` (type: `integer`):

Stops the run once this many adverts have been collected. The portal itself will not go past 3,000 for one search no matter what you ask, so that is the ceiling here too — for a place with more stock than that, split the run by district, property type or price band. Thirty adverts arrive per page request.

## `minPrice` (type: `integer`):

Leave at 0 for no minimum. Monthly rent for the rent market, asking price for sale.

## `maxPrice` (type: `integer`):

Leave at 0 for no maximum. Useful for splitting a search that would otherwise hit the portal's 3,000-advert ceiling.

## `minRooms` (type: `integer`):

Leave at 0 to take any. Counts bedrooms as the advert states them, so a studio reports 0.

## `minBathrooms` (type: `integer`):

Leave at 0 to take any.

## `minAreaM2` (type: `integer`):

Built area in square metres, as the advert states it. Leave at 0 to take any.

## `maxAreaM2` (type: `integer`):

Leave at 0 to take any.

## `sortBy` (type: `string`):

The portal's own orderings. Worth more than it looks: because one search stops at 3,000 adverts, running the same place twice — once cheapest-first and once dearest-first — reaches twice as far into a market that is bigger than the ceiling.

## `includeDetails` (type: `boolean`):

Opens every advert the search found on its own page and adds the energy certificate, usable floor area, condition, orientation, heating, age, community charge and the agency's reference. One extra page request per advert, billed as a detail row, so turn it on when you need those fields and leave it off when you do not.

## `listingUrls` (type: `array`):

For the detail operation: pisos.com advert links, for example https://www.pisos.com/comprar/piso-gaztambide-65098413759\_100500/. Paste them, upload a CSV or point at a Google Sheet.

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

Already have a pisos.com search open in your browser? Paste the address here and the actor will walk it exactly as it stands, filters and all. Anything pasted here is used instead of the place and filters above.

## Actor input object example

```json
{
  "operation": "search",
  "location": "madrid_capital_zona_urbana",
  "market": "sale",
  "propertyType": "pisos",
  "maxResults": 300,
  "minPrice": 0,
  "maxPrice": 0,
  "minRooms": 0,
  "minBathrooms": 0,
  "minAreaM2": 0,
  "maxAreaM2": 0,
  "sortBy": "relevance",
  "includeDetails": false,
  "listingUrls": [],
  "searchUrls": []
}
```

# Actor output Schema

## `pisosComAdvert` (type: `string`):

Every advert this run returned.

## `scrapingSummary` (type: `string`):

HTML summary showing successful and failed results with key metrics

# 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 = {
    "operation": "search",
    "location": "madrid_capital_zona_urbana",
    "market": "sale",
    "propertyType": "pisos",
    "maxResults": 300,
    "minPrice": 0,
    "maxPrice": 0,
    "minRooms": 0,
    "minBathrooms": 0,
    "minAreaM2": 0,
    "maxAreaM2": 0,
    "sortBy": "relevance",
    "includeDetails": false,
    "listingUrls": [],
    "searchUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/pisos-property-scraper").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 = {
    "operation": "search",
    "location": "madrid_capital_zona_urbana",
    "market": "sale",
    "propertyType": "pisos",
    "maxResults": 300,
    "minPrice": 0,
    "maxPrice": 0,
    "minRooms": 0,
    "minBathrooms": 0,
    "minAreaM2": 0,
    "maxAreaM2": 0,
    "sortBy": "relevance",
    "includeDetails": False,
    "listingUrls": [],
    "searchUrls": [],
}

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/pisos-property-scraper").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 '{
  "operation": "search",
  "location": "madrid_capital_zona_urbana",
  "market": "sale",
  "propertyType": "pisos",
  "maxResults": 300,
  "minPrice": 0,
  "maxPrice": 0,
  "minRooms": 0,
  "minBathrooms": 0,
  "minAreaM2": 0,
  "maxAreaM2": 0,
  "sortBy": "relevance",
  "includeDetails": false,
  "listingUrls": [],
  "searchUrls": []
}' |
apify call sian.agency/pisos-property-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sian.agency/pisos-property-scraper"
        }
    }
}
```

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/wD7GfJpz56RThwFQR/builds/yVgqKUwEHo8zaAfaG/openapi.json
