# Idealista Scraper - Spain, Italy & Portugal Property Listings (`dami_studio/idealista-scraper`) Actor

Scrape Idealista listings in Spain, Italy and Portugal: price, size m2, rooms, floor, address, neighbourhood, agency or private seller, photos and the listing link. Paste a search URL or use plain filters. No account, no API key and no proxy setup — the run brings the addresses Idealista serves.

- **URL**: https://apify.com/dami\_studio/idealista-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Real estate, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 listing scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Idealista Scraper - Spain, Italy & Portugal Property Listings

Paste an Idealista search URL — or just say country, city and whether you are buying or renting — and get the listings back as a clean table: price, size in m², rooms, floor, address and neighbourhood, whether it is an estate agency or a private seller, the photos and the link. Covers idealista.com (Spain), idealista.it (Italy) and idealista.pt (Portugal). No account and no API key.

- All three Idealista countries in one Actor, with the same columns for each — Spain, Italy and Portugal.
- Take a search URL straight from your browser, filters and all, or build one from country, city, operation, price, size and rooms.
- Pagination is automatic: ask for 500 listings and it walks the result pages until it has them.
- Every row says whether the advertiser is an estate agency (with its name) or a private seller.
- Optional detail pass adds the bathroom count, the full description and the complete photo set.
- Nothing to configure and no proxy servers to supply — the run buys the addresses Idealista will actually serve, in the country you are searching.
- Runs with empty input return a labelled sample row, free, so you can see the shape before you spend anything.

### Price

**$1.20 per 1,000 listings**, plus a **$0.06 start fee per run** (the platform bills a start fee per gigabyte of run memory, at $0.03 per gigabyte; this Actor runs a browser and needs 2 GB, so one run starts at the figure above).

This is a flat rate on every plan, free or paid. There are no volume tiers, no minimum spend, no subscription and no add-on fees. What you read here is what you pay on day one and on day four hundred.

| Listings | Total cost |
|---|---|
| 100 | $0.18 |
| 1,000 | $1.26 |
| 10,000 | $12.06 |
| 100,000 | $120.06 |

#### What is actually charged

- **One `listing-scraped` event per listing row written to the dataset.** Nothing else is metered per row.
- **Free:** the sample row an empty run returns, and every diagnostic row — a blocked target, a dead URL, a search that matched nothing. Those rows all carry `"charged": false`.
- **The start fee is charged once per run, not once per search.** Twenty search URLs in one run pay it once. It is the same whether the run returns 3 listings or 3,000, so batching your searches is the single biggest thing you can do to lower your bill.
- `includeDetails` does not change the price. It opens an extra page per listing, so the run takes far longer, but you are billed the same per listing either way.
- Listings already returned earlier in the same run are dropped before they are charged, so a property that appears in two of your searches is billed once.
- Advert slots and promoted blocks that are not real listings are discarded and never charged.
- Pages the site refuses are reported as free diagnostic rows — you are not charged for a page that returned nothing.
- A run that finds nothing costs the start fee and nothing more.
- Rows never leave the dataset without a charge, and are never charged without a row. The billed event is a named one, so there is no price quietly attached to `apify-default-dataset-item` — the trick that makes some scrapers bill you for their own error messages.

### Input

```json
{
  "searchUrls": [
    "https://www.idealista.com/venta-viviendas/madrid-madrid/",
    "https://www.idealista.it/affitto-case/milano-milano/"
  ],
  "maxItems": 100,
  "includeDetails": false
}
```

| Field | What it does |
|---|---|
| `searchUrls` | One or more Idealista search URLs, copied from your browser. Up to 20 per run. Any of the three sites works, and any filters already in the URL are kept. This is the most precise way to ask, because you can set the filters on the site itself and check the result count before you run anything. |
| `country` | Used only when you are not passing `searchUrls`: `es` for Spain, `it` for Italy, `pt` for Portugal. Default `es`. |
| `operation` | `buy` or `rent`. Default `buy`. |
| `location` | The location slug Idealista itself uses, for example `madrid-madrid`, `barcelona-barcelona`, `milano-milano` or `lisboa`. Take it from the address bar of a search on the site. |
| `propertyType` | `homes` (default), or for Spain also `premises`, `garages` and `land`. |
| `minPrice / maxPrice` | Price range in euros. Whole numbers. |
| `minSize / maxSize` | Floor area range in m². |
| `minRooms` | Minimum bedrooms, 1 to 4, where 4 means "4 or more". Spain and Portugal only — see the limitations. |
| `maxItems` | Total listings to return across all searches. The budget is shared evenly between them, so two searches and 100 rows gives you 50 of each. Default 50, hard ceiling 3,000. Keep it low while testing — you pay per listing. |
| `includeDetails` | Off by default. Turn it on to open each listing page as well as the search page, which adds the bathroom count, the untruncated description and every photo. It costs one extra request per listing, so a run takes roughly ten times longer. The price per listing does not change. |
| `proxyUrls` | Leave empty. The run buys its own residential addresses in the country you are searching and that is what it is built and measured on. Fill this in only if you already pay for residential or mobile proxy servers and would rather the traffic left through those — give them as `http://user:pass@host:port` and they are used first, exactly as supplied. Note that this does not reduce what you are billed here; it only changes whose addresses the traffic uses. |

Run it with **empty input** and you get one clearly labelled sample row, free, so you can see the output shape before you spend anything.

### Output

One row per listing. A real row from a real run:

```json
{
  "ok": true,
  "charged": true,
  "recordType": "listing",
  "listingId": "111543305",
  "title": "Flat / apartment in Calle de Toledo, 14, Sol, Madrid",
  "price": 1090000,
  "currency": "EUR",
  "priceLabel": "total",
  "pricePerM2": 8516,
  "sizeM2": 128,
  "rooms": 2,
  "bathrooms": null,
  "floor": "1st floor exterior with lift",
  "hasLift": true,
  "address": "Calle de Toledo, 14, Sol, Madrid",
  "neighbourhood": "Sol",
  "city": "Madrid",
  "country": "Spain",
  "operation": "buy",
  "propertyType": "Flat / apartment",
  "advertiserType": "agency",
  "agencyName": "Savills Madrid",
  "description": "Savills exclusively presents this property in the heart of Madrid, just steps from the Plaza Mayor. Located on the emblematic Calle de Toledo, this magnificent property occupies the first floor of a stately building dating back to 1860.",
  "features": [],
  "tags": [],
  "images": [
    "https://img4.idealista.com/blur/480_360_mq/0/id.pro.es.image.master/af/05/a0/1439972957.jpg"
  ],
  "imageCount": 1,
  "listingUrl": "https://www.idealista.com/inmueble/111543305/",
  "searchUrl": "https://www.idealista.com/venta-viviendas/madrid-madrid/",
  "updatedText": null,
  "scrapedAt": "2026-08-16T20:00:21.530Z"
}
```

#### Field notes

- `price` — a number with no separators or symbol. Check `priceLabel` to know what it means: `total` for a sale price, `per month` for a rental.
- `pricePerM2` — as published by Idealista on the card. Null when the site does not show it for that listing.
- `sizeM2` — built area in square metres, as shown on the listing card.
- `rooms` — bedrooms. Portuguese listings use the local T1/T2/T3 typology and it is converted to a number for you.
- `bathrooms` — null unless you set `includeDetails`, because Idealista does not put the bathroom count on the search card.
- `floor` — the floor description as published, e.g. `1st floor exterior with lift` or `Ground floor without lift`. `hasLift` is pulled out of it as a true/false where the text says so, and is null where it does not.
- `address` — the location line as Idealista publishes it — usually street and number, then district, then city. Idealista deliberately does not publish an exact street number for every property, so this is as precise as the source is.
- `neighbourhood / city` — split out of the address line. On a listing published without a street, the address may be just district and city.
- `advertiserType` — `agency` or `private`, taken from how the advert itself is registered.
- `agencyName` — the estate agency’s display name where the advert carries its branding; null for private sellers and for agencies that do not brand the card.
- `description` — the description shown on the search card, which the site truncates. Set `includeDetails` for the full text.
- `images` — photo URLs, deduplicated so each photo appears once rather than once per image format. A search card carries the cover photo (and on some sites the first few); `includeDetails` returns the whole gallery.
- `listingUrl` — the canonical link to the property on Idealista, safe to open or share.
- `updatedText` — the "last updated" line where Idealista publishes one. See the limitations — it very often does not.
- `scrapedAt` — when the row was read, ISO 8601 in UTC.

Every real row carries `"charged": true`. Sample rows carry `"_sample": true` and diagnostic rows carry `"_diagnostic": true` with an `errorCode` you can filter on, and neither is ever billed.

### How it works

- It opens Idealista’s own search pages in a real browser engine and parses the listing cards out of the server-rendered HTML. No account, no API key and no login is involved at any point.
- Listings are read from Idealista’s English-language pages, so a Spanish, Italian and Portuguese search all come back with the same column labels and the same wording in `floor` and `propertyType`.
- Images, fonts, stylesheets, analytics and ad scripts are dropped before they are fetched, which roughly halves the page and the time it takes to read one.
- Idealista only serves home-grade internet connections, so the run buys them: every request leaves through a residential address in the country you are searching, paid for by the Actor, with nothing for you to configure. That traffic is metered by the gigabyte and it is the single reason this Actor costs what it does — see Price.
- Because those addresses cost real money per gigabyte, the run is built to touch as little of the site as possible: it reads the English-language pages, drops everything that is not the listing HTML, and keeps one browser session alive across all your result pages instead of paying for a new one each time.
- Each search is paged until your `maxItems` is reached or the results run out, and listing ids already seen in the run are skipped.
- If the site will not serve a page, the run tries again on a fresh session and then on a different address, and writes an uncharged diagnostic row saying so rather than failing.

### What people use it for

- Market research on asking prices: pull every flat for sale in a city, then group by neighbourhood and compare price per m² without touching the site by hand.
- Lead lists for estate agents and mortgage brokers — filter the rows to `advertiserType: "private"` to find owners selling without an agency.
- Portfolio and market monitoring: schedule the same searches weekly and diff on `listingId` and `price` to see what is new, what has been reduced and what has gone.
- Rental yield modelling: run one search for sale prices and one for rents in the same district and divide the two, with size and rooms already normalised into numbers.
- Relocation and property hunting at scale — combine several cities in one run and sort the whole table by price per m², which the website cannot do across searches.
- Feeding a valuation model or dashboard with a flat, typed table that loads straight into a spreadsheet or database with no cleaning.

### Choosing between a search URL and the filter fields

Both end up at the same place, so use whichever is less work:

- **A search URL** is the precise option. Set the filters on Idealista itself, check the result count it reports, then copy the address bar into `searchUrls`. Everything the URL encodes is kept, including filters this Actor does not expose as fields — condition, energy rating, terrace, lift, new build, and so on.
- **The filter fields** are the convenient option when you are generating runs programmatically: give `country`, `operation`, `location` and any of `minPrice`, `maxPrice`, `minSize`, `maxSize`, `minRooms`, and the search URL is built for you.

If `searchUrls` is filled in, the filter fields are ignored. Mixing countries in one run is fine — pass Spanish, Italian and Portuguese URLs together and the rows come back in one table with a `country` column.

### Reading the output

Every run writes three kinds of row, and they are easy to tell apart:

- **Real rows** carry `"charged": true` and `"recordType": "listing"`. These are the rows you paid for, one billed event each.
- **The sample row** carries `"_sample": true` and `"charged": false`. There is exactly one, it only appears when the input had no search URL and no location, and it exists so you can look at the shape of the output before you spend anything.
- **Diagnostic rows** carry `"_diagnostic": true`, `"charged": false` and an `errorCode` you can switch on: `NO_RESULTS` when a search matched nothing, `NOT_FOUND` when the location slug does not exist on Idealista, `BLOCKED` when the site refused a page even after a fresh session, `BAD_INPUT` when a URL was not an Idealista address, `FILTER_UNSUPPORTED` when a filter does not exist for that country, `NETWORK` when a request could not be completed, and `TIME_BUDGET` when the run ran out of time.

If you only want the data, filter on `charged == true`. The count of those rows always equals the number of events you were billed for, so the dataset is its own invoice.

### Limitations

- Idealista does not publish a listing’s publication or last-updated date on its search cards, and on most listing pages it does not publish one either. `updatedText` is filled in only where the site actually shows such a line, so expect it to be null on most rows. There is no way to derive a real date from a page that does not carry one, and inventing one would be worse than leaving it empty.
- The bathroom count is not on the search cards. It arrives only with `includeDetails`, which costs an extra request per listing and makes a run roughly ten times slower.
- Idealista Italy has no bedroom filter in its URLs — it is a form control on the site, not part of the address — so `minRooms` is ignored for Italian searches and you get an uncharged `FILTER_UNSUPPORTED` row saying so. Filter the `rooms` column afterwards, or paste a search URL. Spain and Portugal support it normally.
- `propertyType` values other than `homes` are only available for Spain in the filter fields. For commercial premises, garages or land in Italy or Portugal, paste a search URL from the site instead.
- Idealista stops paginating a search at 60 pages, roughly 1,800 listings. A search with more results than that cannot be read to the end in one pass — narrow it by price, size or district and run the parts, which is what the website expects you to do too.
- Exact street numbers, contact phone numbers and advertiser email addresses are not returned. Idealista hides them behind an interaction on its own site, and this Actor does not attempt to reveal them.
- Prices, sizes and availability are a snapshot at read time. A property can be withdrawn or reduced minutes later.
- `agencyName` is null when an advert does not carry agency branding, which happens on plain agency listings as well as private ones — use `advertiserType` for the reliable agency/private split.
- THIS ACTOR IS NOT THE CHEAPEST WAY TO GET IDEALISTA DATA, AND IT DOES NOT PRETEND TO BE. Idealista runs a device check that only clears from a home-grade internet connection in the country you are searching. The run therefore buys residential addresses for every single request, and those are billed to us by the gigabyte. Almost all of that cost is fixed per run rather than per listing, which is why the start fee is large and the per-listing rate then stays flat. If price per listing is what matters most to you and you have another route to this data, take it. What you are paying for here is that the run comes back with rows at all.
- Because the expensive part is per run and not per listing, small runs are poor value and large ones are good value. One run for 1,000 listings costs a fraction of what twenty runs of 50 listings cost. Batch your searches — up to 20 in a single run — rather than scheduling many small ones.
- Idealista refuses or throttles a share of attempts even from those addresses, and the share goes up if you pull the same search repeatedly in a short window. When that happens the run tries a different address, and if that is also refused it writes a free `BLOCKED` diagnostic row and stops. No diagnostic row is ever billed, so a refused run costs you the start fee and nothing else — but it does cost the start fee, and on this Actor that is not a rounding error. Space repeated pulls of the same search a few minutes apart.
- `includeDetails` is the most expensive thing you can turn on. It opens one extra page per listing, which is roughly ten times the wall-clock time and several times the metered traffic of a plain search. The per-listing price does not change, but the run does get much slower, so leave it off unless you actually need the bathroom count, the full description or the complete photo set.
- The hard ceiling is 3,000 listings and 20 searches per run. For more, split the work across runs.

### Questions

**Which Idealista sites does this cover?**

All three: idealista.com for Spain, idealista.it for Italy and idealista.pt for Portugal. You can mix them in a single run and the rows come back in one table with a `country` column.

**Do I need an Idealista account or an API key?**

No. Nothing in the run logs in, and there is nothing to sign up for. Just give it a search URL.

**I got a BLOCKED row and no listings. What now?**

Run it again in a few minutes. The run already goes out through home-grade addresses in the country you searched — you do not need to supply anything — but Idealista still refuses or rate-limits a share of attempts, and it does so more often when the same search is pulled repeatedly in a short window. Narrowing the search so it needs fewer pages helps too. No listing was charged, though the start fee still applies, so it is worth spacing repeat runs rather than retrying immediately.

**Why does this cost more per listing than other Idealista scrapers?**

Because of how the run has to reach the site. Idealista only serves this kind of container through residential addresses in the country being searched, and that traffic is billed to us by the gigabyte. Most of that cost lands once per run rather than once per listing, which is why the start fee is the big number and the per-listing rate is flat and predictable on top of it. We would rather quote you a price that covers what the data actually costs to fetch than a cheaper one on a run that comes back empty.

**How do I keep the cost down?**

Put more listings in fewer runs. The start fee is charged once per run regardless of how much you ask for, so one run asking for 1,000 listings across several searches is far cheaper than twenty runs of 50. Leave `includeDetails` off unless you need it, keep `maxItems` at what you will actually use, and use a search URL with filters already applied so the run does not page through results you will discard.

**Why is `bathrooms` empty?**

Because Idealista does not print the bathroom count on the search results card. Set `includeDetails: true` and the run opens each listing page as well, which fills in the bathroom count, the full description and the whole photo gallery. It does not change the price per listing, but the run takes considerably longer.

**Can I use the filters I set on the website?**

Yes, and that is the recommended way. Set them up on Idealista, copy the URL out of the address bar into `searchUrls`, and every filter in it is honoured — including ones this Actor does not expose as its own fields.

**What happens if a search matches nothing?**

You get one uncharged diagnostic row with `errorCode: "NO_RESULTS"` and the run carries on to your other searches. You are never billed for a search that returned nothing.

**Will the run fail if a page is refused?**

No. A refused page produces an uncharged `BLOCKED` diagnostic row and the run still finishes as succeeded. A failed run would still bill you the start fee, which would mean paying to be told something went wrong.

**Can I run this on a schedule?**

Yes. Nothing is held between runs, so the same input is safe to repeat. Use `listingId` to work out which properties are new since last time, and compare `price` to spot reductions.

**How do I get exactly the rows I paid for?**

Filter the dataset on `"charged": true`. Sample and diagnostic rows are always `false`, and the number of charged rows always equals the number of billed events.

# Actor input Schema

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

One or more Idealista search URLs copied from your browser - www.idealista.com (Spain), www.idealista.it (Italy) or www.idealista.pt (Portugal). Up to 20 per run. Any filters already in the URL are kept, so this is the most precise way to ask. If you fill this in, the filter fields below are ignored.

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

Total listings to return across all searches. The budget is shared evenly between them, so two searches and 100 rows gives you 50 of each. Keep it low while you are testing - you pay per listing.

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

Off by default. Turn it on to also open every listing page, which adds the bathroom count, the full untruncated description and the complete photo gallery. It costs one extra request per listing, so the run takes roughly ten times longer. The price per listing is unchanged.

## `country` (type: `string`):

Which Idealista site to search. Used only when you are not passing search URLs.

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

Whether to search properties for sale or for rent.

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

The location slug Idealista itself uses, taken from the address bar of a search on the site - for example madrid-madrid, barcelona-barcelona, valencia-valencia, milano-milano, roma-roma, lisboa or porto.

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

Homes works for all three countries. Commercial premises, garages and land are available for Spain only - for those in Italy or Portugal, paste a search URL instead.

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

Lowest price to include, in euros. Leave empty for no lower bound.

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

Highest price to include, in euros. Leave empty for no upper bound.

## `minSize` (type: `integer`):

Smallest floor area to include, in square metres.

## `maxSize` (type: `integer`):

Largest floor area to include, in square metres.

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

Minimum number of bedrooms, 1 to 4, where 4 means four or more. Spain and Portugal only - Idealista Italy has no bedroom filter in its URLs, so this is ignored there and the run tells you so.

## `proxyUrls` (type: `array`):

Leave this empty. The run brings its own addresses and they cost you nothing per gigabyte. Fill it in only if you specifically want the traffic to leave through proxy servers you already pay for, in the form http://user:pass@host:port.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.idealista.com/venta-viviendas/madrid-madrid/"
  ],
  "maxItems": 50,
  "country": "es",
  "operation": "buy",
  "location": "madrid-madrid",
  "propertyType": "homes"
}
```

# Actor output Schema

## `results` (type: `string`):

Every row in the default dataset: listingId, title, price, currency, priceLabel, pricePerM2, sizeM2, rooms, bathrooms, floor, hasLift, address, neighbourhood, city, country, operation, propertyType, advertiserType, agencyName, description, features, tags, images, imageCount, listingUrl, searchUrl, updatedText, scrapedAt. An empty, blocked or unmatched run returns a single uncharged row explaining what happened instead.

# 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 = {
    "searchUrls": [
        "https://www.idealista.com/venta-viviendas/madrid-madrid/"
    ],
    "maxItems": 50,
    "country": "es",
    "operation": "buy",
    "location": "madrid-madrid",
    "propertyType": "homes"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/idealista-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 = {
    "searchUrls": ["https://www.idealista.com/venta-viviendas/madrid-madrid/"],
    "maxItems": 50,
    "country": "es",
    "operation": "buy",
    "location": "madrid-madrid",
    "propertyType": "homes",
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/idealista-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 '{
  "searchUrls": [
    "https://www.idealista.com/venta-viviendas/madrid-madrid/"
  ],
  "maxItems": 50,
  "country": "es",
  "operation": "buy",
  "location": "madrid-madrid",
  "propertyType": "homes"
}' |
apify call dami_studio/idealista-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/idealista-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/8SaSLuyIbsV0nPLxb/builds/IjSNkHdVPeDl6RTpE/openapi.json
