# Idealista Scrape- LowCost | HiQuality (ES/PT/IT) (`scraper_gump/idealista-scraper`) Actor

▎ Reliable Idealista data, at a fair price.
▎ We built the most efficient scraper for Idealista because we believe quality data shouldn't cost a fortune. No captchas, no browser overhead — just
▎ clean, structured data that works.
▎ Questions or ideas? → info@inmocalc.com

- **URL**: https://apify.com/scraper\_gump/idealista-scraper.md
- **Developed by:** [SMY](https://apify.com/scraper_gump) (community)
- **Categories:** Real estate, MCP servers, Integrations
- **Stats:** 3 total users, 1 monthly users, 0.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

Extract property listings from Idealista — no browser, no captchas, clean JSON in seconds.

> 👋 **Hola equipo** — este scraper es para vosotros, usadlo con cariño.
> 👋 **Ciao team** — questo scraper è per voi, usatelo con cura.
> 👋 **Olá equipa** — este scraper é para vocês, usem-no com carinho.
>
> Questions or issues? Reach us at **info@inmocalc.com**

---

### What it does

Three modes in one actor:

| Mode | When to use it |
|---|---|
| **Search** | Get all listings in an area (up to 1,800 per run) |
| **Fetch by Property ID** | Get full details for specific listings you already know |
| **Find Location ID** | Look up the area code you need before searching |

Each mode is a separate section in the input form. Fill in one, leave the others empty.

---

### Why this one?

Most Idealista scrapers are slow, fragile, or expensive. We've built the most efficient scraping technology available for Idealista, and we're making it accessible because we want to help our users and friends get their work done — without paying a premium for it.

No captchas, no browser overhead, just clean data at a price that makes sense.

---

### Mode 1 — Search

Get all listings in an area matching your filters.

#### How to use it

**Step 1 — Fill in the required fields**

| Field | What to enter |
|---|---|
| **Country** | `🇪🇸 Spain`, `🇵🇹 Portugal` or `🇮🇹 Italy` |
| **Operation** | `Sale` (buy/sell) or `Rent` |
| **Property Type** | Type of property — `Homes` for flats and houses |
| **Location ID** | The code for the area you want to scrape — see below |

**Step 2 — Hit Start**

The scraper runs page by page and saves results to the dataset as it goes. You can see data coming in before it finishes.

**Step 3 — Download your results**

When done, go to **Storage → Dataset** and export as CSV, JSON or Excel.

#### How to find a Location ID

**Option A — use the built-in lookup (easiest)**
Fill in the **Search term** field in the "📍 Find Location ID" section (see Mode 3 below), run the actor, and copy the `locationId` you need.

**Option B — from the Idealista URL**
Search your area on the relevant site ([idealista.com](https://www.idealista.com) for Spain, [idealista.pt](https://www.idealista.pt) for Portugal, [idealista.it](https://www.idealista.it) for Italy). Once you're on the results page, look at the URL — the Location ID follows the `0-EU-XX-...` pattern.

**Option C — use a known ID**

🇪🇸 Spain

| Area | Location ID |
|---|---|
| Madrid city | `0-EU-ES-28-07-001-079` |
| Madrid province | `0-EU-ES-28` |
| Barcelona city | `0-EU-ES-08-13-001-019` |
| Soria province | `0-EU-ES-42` |

🇵🇹 Portugal

| Area | Location ID |
|---|---|
| Lisboa (Distrito) | `0-EU-PT-11` |
| Lisboa (Concelho) | `0-EU-PT-11-06` |
| Cascais (Concelho) | `0-EU-PT-11-05` |

🇮🇹 Italy — use **Option A** (built-in lookup) to find your area code. The pattern is `0-EU-IT-XX-...`.

#### Output fields

Each listing includes:

| Field | Description |
|---|---|
| `id` | Idealista listing ID |
| `url` | Direct link to the listing |
| `address` | Full address |
| `municipality` / `district` | City and neighbourhood |
| `latitude` / `longitude` | Coordinates for mapping |
| `price` | Price in € |
| `price_by_area` | €/m² |
| `size` | Built area in m² |
| `rooms` / `bathrooms` | Bedrooms and bathrooms |
| `floor` | Floor number |
| `exterior` | Whether it faces the street |
| `has_lift` | Lift in the building |
| `status` | Property condition |
| `description` | Full listing description |
| `num_photos` | Number of photos |
| `location_id` | Exact sub-area code (neighbourhood level) |
| `photos` | List of photo URLs (requires **Fetch full details**) |
| `contact_phone` | Agent or owner phone number (requires **Fetch full details**) |
| `contact_name` | Agent or owner name (requires **Fetch full details**) |
| `contact_user_type` | Account type: `professional`, `private`, etc. (requires **Fetch full details**) |
| `energy_certification` | Energy performance rating (requires **Fetch full details**) |
| `allows_remote_visit` | Whether a remote visit is available (requires **Fetch full details**) |
| `allows_counter_offers` | Whether counter-offers are accepted (requires **Fetch full details**) |

#### Full details (photos, contact, energy)

The **Fetch full details** toggle (enabled by default) makes the scraper retrieve the complete property record for each listing — adding photos, agent contact info, energy certification and remote visit availability.

**Trade-off:** each listing requires one extra request, so a full 60-page run takes roughly twice as long and uses more proxy bandwidth. Disable it if you only need basic listing data and want faster runs.

> ⚠️ Photo URLs are signed and expire after approximately 24 hours — download images promptly if you need them.

#### Limits

- **Max 1,800 listings per run** — Idealista caps results at 60 pages × 30 listings. For large cities like Madrid or Barcelona, run separate searches per district.
- **All filters are optional** — price, size, rooms and the amenity toggles can all be left blank.

---

### Mode 2 — Fetch by Property ID

Get full details for specific listings — active or closed.

**When to use this:**
- You have a list of IDs from a previous run and want the full detail (contact info, photos, full description).
- You want to monitor specific properties over time.
- A listing disappeared from search and you want to know why and at what price.

**How to use it:** fill in the **Property IDs** field (one ID per line). The Search section is ignored.

#### Output for active listings

| Field | Description |
|---|---|
| `property_id` | The ID you requested |
| `status` | `active` |
| `_details` | Full detail response — contact info, photos, all characteristics |

#### Output for closed listings

| Field | Description |
|---|---|
| `property_id` | The ID you requested |
| `status` | `closed` |
| `deactivation_reason` | Why it was removed: `user` (likely sold/rented), `quality`, `fraud`, `pending` |
| `last_deactivation_date` | Timestamp (ms) when it was taken down |
| `price_at_close` | Last known price — a proxy for the transaction price |
| `rooms` / `size` | Basic info retained after closure |

#### Run stats

When **Include Run Stats** is enabled (default), a summary record is added at the end of the dataset:

```json
{
  "_type": "run_stats",
  "_stats": {
    "total": 10,
    "active": 7,
    "closed": 2,
    "errors": 1,
    "duration_s": 42.3
  }
}
````

***

### Mode 3 — Find Location ID

Not sure what Location ID to use for your search? Run this mode first.

**How to use it:** fill in the **Search term** field under "📍 Find Location ID". Country, Property Type and Operation must be set too (the defaults work fine). Leave everything else empty.

**Tip:** be specific — "mad" returns Madrid but also Madrigal, Madrigueras and others. "madrid" returns only areas called Madrid.

#### Output

| Field | Description |
|---|---|
| `locationId` | The code to copy into the Search section |
| `name` | Human-readable area name (e.g. `Madrid`) |
| `subTypeText` | Area type (e.g. `Municipio`, `Provincia`, `Barrio`) |
| `total` | Active listings in that area for your selected property type and operation |

***

### Tips

- **Each run creates a new dataset** — results from each execution are saved separately in Apify Storage, so you can always compare previous runs.
- **Don't change Items Per Page** — the default (30) is the most efficient setting.
- **Mode priority:** if you fill in multiple sections, the actor uses only one — Find Location ID takes priority, then Fetch by Property ID, then Search.

# Actor input Schema

## `location_prefix` (type: `string`):

Type a city, neighbourhood or area name (e.g. "madrid", "seville", "eixample"). The scraper will return all matching Location IDs — copy the one you need into the Search section.

⚠️ When this field is filled in, all other sections (Search, Fetch by Property ID) are ignored.

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

Are you looking to buy/sell or to rent?

## `property_type` (type: `string`):

The kind of property you want to search.

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

Idealista operates in Spain, Portugal and Italy. Make sure the Location ID matches the country you pick.

## `location_id` (type: `string`):

The internal Idealista code for the area you want to scrape. It always starts with 0-EU-.

📍 Common Spanish locations:
• Madrid city → 0-EU-ES-28-07-001-079
• Madrid province → 0-EU-ES-28
• Barcelona city → 0-EU-ES-08-13-001-019
• Soria province → 0-EU-ES-42

💡 To find any other ID: search your area on idealista.com and copy the code from the URL. It follows the 0-EU-XX-... pattern.

## `enrich_details` (type: `boolean`):

When enabled, the scraper fetches the full property detail for each result — adding photos, contact info (phone, agent name), energy certification and remote visit availability.

⚠️ This makes each run significantly slower and uses more proxy bandwidth (one extra request per listing). Disable if you only need basic listing data.

## `max_pages` (type: `integer`):

Idealista caps results at 60 pages per search — that's up to 1,800 listings. Each page takes a few seconds, so a full 60-page run takes about 5 minutes.

💡 To get more than 1,800 listings from a large city, run separate searches per district.

## `max_items_per_page` (type: `integer`):

How many listings to request per page. Leave at 30 — changing this only makes the scraper less efficient without adding any benefit.

## `order` (type: `string`):

Which field to sort results by.

## `sort` (type: `string`):

Ascending or descending order.

## `min_price` (type: `integer`):

Only show properties at or above this price. Leave empty for no lower bound.

## `max_price` (type: `integer`):

Only show properties at or below this price. Leave empty for no upper bound.

## `min_size` (type: `integer`):

Only show properties with at least this many square metres. Leave empty for no lower bound.

## `max_size` (type: `integer`):

Only show properties up to this size. Leave empty for no upper bound.

## `bedrooms` (type: `integer`):

Filter by exact number of bedrooms. Leave empty to include all.

## `bathrooms` (type: `integer`):

Filter by exact number of bathrooms. Leave empty to include all.

## `air_conditioning` (type: `boolean`):

Only return properties that have air conditioning.

## `elevator` (type: `boolean`):

Only return properties in buildings with a lift.

## `terrace` (type: `boolean`):

Only return properties with a terrace.

## `pool` (type: `boolean`):

Only return properties with a pool.

## `garage` (type: `boolean`):

Only return properties with a garage.

## `garden` (type: `boolean`):

Only return properties with a garden.

## `property_ids` (type: `array`):

List of Idealista property IDs to fetch directly. When set, the Search section above is ignored — each ID is looked up individually via the detail endpoint.

Useful for monitoring specific listings or fetching full details (including contact info and photos) after a search run.

Closed listings return their deactivation reason and closing price.

## `fetch_stats` (type: `boolean`):

When enabled, a summary record is added at the end of the dataset with the total number of properties fetched, how many were active vs. closed, any errors, and total run time.

## `bearer_token` (type: `string`):

The actor generates a fresh OAuth token automatically on each run. If token generation fails (Idealista occasionally tightens TLS requirements), paste a manually captured token here.

To capture one: run `./scraper_gump.sh --debug` on the local machine — it launches the Android emulator, opens the Idealista app, and saves the token to `.token`. Copy its contents here. Tokens expire after ~12 hours.

## Actor input object example

```json
{
  "operation": "rent",
  "property_type": "homes",
  "country": "es",
  "location_id": "0-EU-ES-28-07-001-079",
  "enrich_details": true,
  "max_pages": 60,
  "max_items_per_page": 30,
  "order": "publicationDate",
  "sort": "desc",
  "air_conditioning": false,
  "elevator": false,
  "terrace": false,
  "pool": false,
  "garage": false,
  "garden": false,
  "fetch_stats": true
}
```

# Actor output Schema

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

Dataset items — search listings, property details, or location IDs.

# 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_id": "0-EU-ES-28-07-001-079"
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraper_gump/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 = { "location_id": "0-EU-ES-28-07-001-079" }

# Run the Actor and wait for it to finish
run = client.actor("scraper_gump/idealista-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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_id": "0-EU-ES-28-07-001-079"
}' |
apify call scraper_gump/idealista-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=scraper_gump/idealista-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Idealista Scrape- LowCost | HiQuality (ES/PT/IT)",
        "description": "▎ Reliable Idealista data, at a fair price.\n  ▎ We built the most efficient scraper for Idealista because we believe quality data shouldn't cost a fortune. No captchas, no browser overhead — just \n  ▎ clean, structured data that works.\n  ▎ Questions or ideas? → info@inmocalc.com",
        "version": "0.0",
        "x-build-id": "GqhOk6ilMHVeRTWR0"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/scraper_gump~idealista-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-scraper_gump-idealista-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/scraper_gump~idealista-scraper/runs": {
            "post": {
                "operationId": "runs-sync-scraper_gump-idealista-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/scraper_gump~idealista-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-scraper_gump-idealista-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "country"
                ],
                "properties": {
                    "location_prefix": {
                        "title": "Search term",
                        "type": "string",
                        "description": "Type a city, neighbourhood or area name (e.g. \"madrid\", \"seville\", \"eixample\"). The scraper will return all matching Location IDs — copy the one you need into the Search section.\n\n⚠️ When this field is filled in, all other sections (Search, Fetch by Property ID) are ignored."
                    },
                    "operation": {
                        "title": "Operation",
                        "enum": [
                            "sale",
                            "rent"
                        ],
                        "type": "string",
                        "description": "Are you looking to buy/sell or to rent?",
                        "default": "rent"
                    },
                    "property_type": {
                        "title": "Property Type",
                        "enum": [
                            "homes",
                            "offices",
                            "premises",
                            "garages",
                            "bedrooms",
                            "lands",
                            "storage-rooms",
                            "buildings",
                            "new-developments"
                        ],
                        "type": "string",
                        "description": "The kind of property you want to search.",
                        "default": "homes"
                    },
                    "country": {
                        "title": "Country",
                        "enum": [
                            "es",
                            "pt",
                            "it"
                        ],
                        "type": "string",
                        "description": "Idealista operates in Spain, Portugal and Italy. Make sure the Location ID matches the country you pick.",
                        "default": "es"
                    },
                    "location_id": {
                        "title": "Location ID",
                        "type": "string",
                        "description": "The internal Idealista code for the area you want to scrape. It always starts with 0-EU-.\n\n📍 Common Spanish locations:\n• Madrid city → 0-EU-ES-28-07-001-079\n• Madrid province → 0-EU-ES-28\n• Barcelona city → 0-EU-ES-08-13-001-019\n• Soria province → 0-EU-ES-42\n\n💡 To find any other ID: search your area on idealista.com and copy the code from the URL. It follows the 0-EU-XX-... pattern."
                    },
                    "enrich_details": {
                        "title": "Fetch full details (photos, contact, energy)",
                        "type": "boolean",
                        "description": "When enabled, the scraper fetches the full property detail for each result — adding photos, contact info (phone, agent name), energy certification and remote visit availability.\n\n⚠️ This makes each run significantly slower and uses more proxy bandwidth (one extra request per listing). Disable if you only need basic listing data.",
                        "default": true
                    },
                    "max_pages": {
                        "title": "Max Pages",
                        "minimum": 1,
                        "maximum": 60,
                        "type": "integer",
                        "description": "Idealista caps results at 60 pages per search — that's up to 1,800 listings. Each page takes a few seconds, so a full 60-page run takes about 5 minutes.\n\n💡 To get more than 1,800 listings from a large city, run separate searches per district.",
                        "default": 60
                    },
                    "max_items_per_page": {
                        "title": "Items Per Page",
                        "minimum": 1,
                        "maximum": 40,
                        "type": "integer",
                        "description": "How many listings to request per page. Leave at 30 — changing this only makes the scraper less efficient without adding any benefit.",
                        "default": 30
                    },
                    "order": {
                        "title": "Sort By",
                        "enum": [
                            "publicationDate",
                            "price",
                            "size",
                            "rooms",
                            "weigh"
                        ],
                        "type": "string",
                        "description": "Which field to sort results by.",
                        "default": "publicationDate"
                    },
                    "sort": {
                        "title": "Sort Direction",
                        "enum": [
                            "desc",
                            "asc"
                        ],
                        "type": "string",
                        "description": "Ascending or descending order.",
                        "default": "desc"
                    },
                    "min_price": {
                        "title": "Min Price (€)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only show properties at or above this price. Leave empty for no lower bound."
                    },
                    "max_price": {
                        "title": "Max Price (€)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only show properties at or below this price. Leave empty for no upper bound."
                    },
                    "min_size": {
                        "title": "Min Size (m²)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only show properties with at least this many square metres. Leave empty for no lower bound."
                    },
                    "max_size": {
                        "title": "Max Size (m²)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only show properties up to this size. Leave empty for no upper bound."
                    },
                    "bedrooms": {
                        "title": "Bedrooms",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Filter by exact number of bedrooms. Leave empty to include all."
                    },
                    "bathrooms": {
                        "title": "Bathrooms",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Filter by exact number of bathrooms. Leave empty to include all."
                    },
                    "air_conditioning": {
                        "title": "Air Conditioning",
                        "type": "boolean",
                        "description": "Only return properties that have air conditioning.",
                        "default": false
                    },
                    "elevator": {
                        "title": "Elevator",
                        "type": "boolean",
                        "description": "Only return properties in buildings with a lift.",
                        "default": false
                    },
                    "terrace": {
                        "title": "Terrace",
                        "type": "boolean",
                        "description": "Only return properties with a terrace.",
                        "default": false
                    },
                    "pool": {
                        "title": "Swimming Pool",
                        "type": "boolean",
                        "description": "Only return properties with a pool.",
                        "default": false
                    },
                    "garage": {
                        "title": "Garage",
                        "type": "boolean",
                        "description": "Only return properties with a garage.",
                        "default": false
                    },
                    "garden": {
                        "title": "Garden",
                        "type": "boolean",
                        "description": "Only return properties with a garden.",
                        "default": false
                    },
                    "property_ids": {
                        "title": "Property IDs",
                        "type": "array",
                        "description": "List of Idealista property IDs to fetch directly. When set, the Search section above is ignored — each ID is looked up individually via the detail endpoint.\n\nUseful for monitoring specific listings or fetching full details (including contact info and photos) after a search run.\n\nClosed listings return their deactivation reason and closing price.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "fetch_stats": {
                        "title": "Include Run Stats",
                        "type": "boolean",
                        "description": "When enabled, a summary record is added at the end of the dataset with the total number of properties fetched, how many were active vs. closed, any errors, and total run time.",
                        "default": true
                    },
                    "bearer_token": {
                        "title": "Bearer Token (optional override)",
                        "type": "string",
                        "description": "The actor generates a fresh OAuth token automatically on each run. If token generation fails (Idealista occasionally tightens TLS requirements), paste a manually captured token here.\n\nTo capture one: run `./scraper_gump.sh --debug` on the local machine — it launches the Android emulator, opens the Idealista app, and saves the token to `.token`. Copy its contents here. Tokens expire after ~12 hours."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
