# Pisos.com Scraper - Spain Property Listings · $1.5/1K (`listingworks/pisos-scraper`) Actor

Extract property listings from pisos.com (Spain) by location and property type: price, bedrooms, area, floor, town, agency, URL, newest first.

- **URL**: https://apify.com/listingworks/pisos-scraper.md
- **Developed by:** [Yusuke Suda](https://apify.com/listingworks) (community)
- **Categories:** Real estate, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.75 / 1,000 result items

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 — Spanish homes for sale or rent by province or town

Extract property listings from pisos.com (Spain) by location and property type: price, bedrooms, area, floor, town, agency, URL, newest first.

pisos.com is one of Spain's national property portals. It carries listings from estate agencies and from
private owners in every province. Madrid province alone had more than 16,000 homes for sale on it in September
2026\. This Actor turns the site's lists into a clean table. Each row gives:

- the listing title as the site shows it, e.g. "Piso en calle de la Princesa, 76"
- the price, or the monthly rent
- the number of bedrooms
- the area in square metres, and the floor
- the neighbourhood and district, the town and the province
- the agency marketing it, with the listing's map point
- a photo and the link to the listing

Press Start. The prefilled input returns homes for sale in Madrid province, newest first.

### What a row looks like

```json
{
  "title": "Piso en calle Doctor Esquerdo",
  "property_type": "apartment",
  "listing_type": "sale",
  "price": 1219000,
  "currency": "EUR",
  "bedrooms": 2,
  "living_area_sqm": 121,
  "floor": "6ª planta",
  "address": "Goya (Distrito Barrio de Salamanca. Madrid Capital)",
  "city": "Madrid Capital",
  "state": "Madrid",
  "latitude": 40.4235809,
  "longitude": -3.6690982,
  "agency": "More House",
  "source_url": "https://www.pisos.com/comprar/piso-goya-67528622595_100500/",
  "image_urls": ["https://fotos.imghs.net/mm-wp/1005/3230323630393235/….jpg"],
  "external_id": "67528622595.100500"
}
```

#### The seller and the address

Most listings come from estate agencies. For those:

- `agency` is the agency's name as it appears in its pisos.com profile address, e.g. `/inmobiliaria-princess_homes/`
  becomes "Princess Homes". This is the site's profile name, not necessarily the company's registered name.
- The title is the site's own title, which often names the street.
- `latitude` and `longitude` give the map point the site publishes.

Some listings come from private owners. For those, the Actor publishes no seller at all:

- `agency` is empty. The list shows no owner name, and none is collected.
- The site's title names their street and house number, so the title is cut to the kind of home and the town,
  e.g. "Chalet rústico en Morón de La Frontera".
- There is no map point, because for a private owner that is their home.
- A listing the site does not tag as an agency listing is treated as a private owner's.
- No phone number or e-mail address is collected for anyone. Each card carries a phone number for its "Llamar"
  button, and it is never read. The Actor reads the lists only and never opens a listing page.

#### Bedrooms, area and floor

`bedrooms` is the site's "habs." (habitaciones), which on Spanish portals counts bedrooms. Bathrooms are not
bedrooms and are not published. A listing with no bedroom count has an empty `bedrooms`, not a zero.
`living_area_sqm` is the area the card gives. `floor` is the site's own wording, e.g. "4ª planta" or "Bajo".

#### Property type

With `propertyType` left empty (all homes), each row's `property_type` comes from the listing's own words: a
piso, apartamento, ático, dúplex, estudio or loft is an `apartment`, and a casa, chalet, cortijo or finca is a
`house`. With a single type asked for, every row carries that type.

#### Prices

`price` is the asking price for a sale and the monthly rent for a let, in euros. A listing with no price, or
"a consultar", has an empty `price`, not a zero.

#### No dates

The site's lists show no date for a listing, so rows carry none and `postedAfter` is not offered. The Actor asks
for the site's "Más recientes" order. For a daily feed of what is new, keep the `external_id`s from your last run
and diff against them.

### What people use it for

Price monitoring for Spanish homes by province, comarca or town. Comparing asking prices and rents across Madrid
districts, the Madrid suburbs, Sevilla, Barcelona and the rest of the country. Watching new stock in one town
each day. Tracking which agencies list what, and where.

### Input

| Field | What it does |
|---|---|
| `location` | A province, comarca or town as pisos.com writes it in its URLs: `madrid` (the province), `madrid_capital`, `sevilla`, `barcelona`, `las_rozas_de_madrid`. Spaces, capitals and accents are folded for you, so `Las Rozas de Madrid` and `Cobeña` work. |
| `listingType` | `sale` (the default) or `rent`. |
| `propertyType` | `homes` (all homes), `apartment`, `house`, `penthouse`, `duplex`, `studio` or `loft`. Leave it empty for all homes. Several types give one list each. |
| `maxItems` | Hard stop, so your bill is predictable. |
| `proxyConfiguration` | Off by default. Most runs do not need one. |

If the site does not know the place you give, it answers "not found" and the run fails and tells you.

### Pricing

$1.50 per 1,000 listings, dropping to $0.75 per 1,000 on higher Apify plans, plus $0.005 each time a run
starts. Platform usage is not passed on to you.

You are charged for rows you actually receive. If you set a maximum charge for the run, it stops cleanly at
that limit instead of overshooting it.

### Scope and limits

Public listings only, from the site's lists by type, sale or rent, and place, which pisos.com's robots.txt
allows. The pages it disallows (map pages, `.aspx` pages, the search box, the language versions, holiday lets
and the web services) are never requested. The Actor reads one page every 2 seconds. That makes 30 listings
every 2 seconds, or about 1,000 in under 70 seconds.

The description, bathrooms, energy rating and year built are not collected. New-build developments ("obra
nueva") are listed on separate pages of the site and are not covered. Prices are in euros.

When a search finds nothing, the site shows "No encontramos lo que buscas" together with suggested listings from
other places. The Actor reports an empty result and never delivers those suggestions as rows.

If pisos.com changes its page structure, the run goes red. It does not return zero rows and report success. A
silent scraper is worse than a broken one, because you find out weeks later. The Actor also checks that every
page answers the question it asked (type, sale or rent, place, order and page number) and fails rather than
delivering a page for something else.

A run that is blocked or cut short partway also goes red, even though the rows it did collect are in the
dataset and yours to keep. Red here means "this is not the complete answer", not "you lost the data". On a
schedule, a run that quietly came back short is the thing you most need to hear about.

Every run also publishes the site's own result count next to the rows it delivered, so you can see "100 rows
of 16,164 the site reports" without going back to the site to check. That number is what the site says, not a
promise about what one run returns.

### Same data, other countries

This Actor shares its output shape with the CASA SAPO Scraper (Portugal), the atHome Scraper (Luxembourg), the
Immoweb Scraper (Belgium), the Ohne-Makler Scraper and the Immowelt Scraper (Germany), the Bezrealitky Scraper
(Czech Republic) and the Willhaben Immobilien Scraper (Austria). A parser you write for one keeps working on the
others.

### Support

Open an issue on this Actor with the run ID and your input. Answered within one business day.

# Actor input Schema

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

A province, comarca or town as pisos.com writes it in its URLs: madrid (the province), madrid\_capital, sevilla, barcelona, las\_rozas\_de\_madrid. Spaces and accents are folded for you (Las Rozas de Madrid works). A place the site does not know fails the run.

## `listingType` (type: `string`):

Homes for sale (venta) or for rent (alquiler).

## `propertyType` (type: `array`):

Which lists to walk: homes (all homes), apartment, house, penthouse, duplex, studio, loft. Leave empty for all homes.

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

Stop after this many listings. pisos.com serves 30 per page, one page every 2 seconds.

## `proxyConfiguration` (type: `object`):

Off by default. Turn on (residential, Spain) only if runs start getting blocked with 403/429.

## Actor input object example

```json
{
  "location": "madrid",
  "listingType": "sale",
  "propertyType": [
    "homes"
  ],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

All pisos.com listings from this run: what each home is, what it costs, and where.

## `pricing` (type: `string`):

The same listings reduced to the fields used for price analysis and market monitoring.

## `agencies` (type: `string`):

The same listings focused on the agency marketing them (empty for private owners).

## `runReport` (type: `string`):

Pages read, records delivered, errors, and the verdict (ok, degraded or broken).

# 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 = {
    "location": "madrid",
    "propertyType": [
        "homes"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("listingworks/pisos-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 = {
    "location": "madrid",
    "propertyType": ["homes"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("listingworks/pisos-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 '{
  "location": "madrid",
  "propertyType": [
    "homes"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call listingworks/pisos-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,listingworks/pisos-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/kDpSVImowozuqHeBO/builds/2OFBWYn8kog4FiFQ8/openapi.json
