# Immobiliare.it Listings Scraper (`nice_dev/immobiliare-listings-scraper`) Actor

Scrape Immobiliare.it (Italy) property listings for sale and rent by city, province, region, map area or search URL: price, size, rooms, GPS, agency and phone, energy class, costs, photos. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/nice\_dev/immobiliare-listings-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** Real estate, Lead generation, MCP servers
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.65 / 1,000 listings

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

### 🏠 What is Immobiliare.it Listings Scraper?

**Immobiliare.it Listings Scraper** extracts **property listings from [Immobiliare.it](https://www.immobiliare.it)**, Italy's largest real estate portal: **price, size, rooms, floor, GPS position, zone, agency name and phone numbers, photos** — and, with one option, the **full description, energy class, condominium fees, publication date, floor plans and videos** of every listing. Homes, rooms, new developments, offices, shops, garages, land: for sale or for rent.

Type a **city, province or region** (`Bologna`, `Provincia di Milano`, `Toscana`), draw a map area, or paste any Immobiliare.it search URL, click **Start**, and download the listings in JSON, CSV or Excel. No login, nothing to set up: the first listings arrive within seconds (30 listings in about 20 seconds in our tests), and about 100 listings a minute with the full listing page (500 in 4 minutes on Apify).

### 📋 What data can you extract from Immobiliare.it?

One item per listing, 101 fields:

| Category | What you get |
| --- | --- |
| 🏷️ **Listing** | title, link, the site's listing number, sale or rent, category and typology (Trilocale, Villa, Attico…) |
| 💰 **Price** | price in euros, price band, price per m², former price and drop when the price was lowered |
| 📐 **Property** | size in m², rooms, bedrooms, bathrooms, floor, elevator, condition, heating, garage, balcony, terrace, garden, cellar, views, every feature listed |
| 📍 **Location** | street, zone, neighbourhood, city, province, region, latitude and longitude |
| 🏢 **Agency and contact** | agency name, page and logo, agent, phone numbers, private seller or agency |
| 📝 **Text and media** | description, all photos with their captions, virtual tours, videos, floor plans |
| ⚡ **Energy and costs** | energy class and performance, condominium fees, heating costs, agency commission, rent deposit |
| 🕒 **Dates** | first publication and last update of the listing |

Every field, with an example, is listed in the **Output** section below.

Fields marked **(details)** in the list of fields under **Output** (full description, dates, energy, costs, floor plans, videos) are filled when **Include listing details** is on. Off (the default), each listing still has its price, size, rooms, position, agency, phones, photos and the first 600 characters of its description.

### ✅ Why use Immobiliare.it Listings Scraper?

- 🎯 **Every filter of the site's search form**: price, size, rooms, bedrooms, bathrooms, floor, garden, garage, heating, condition, ownership, elevator, cellar, pool, furnished, virtual tour, auctions excluded, keyword.
- 🗺️ **Search the way you want**: a city, a province, a region, a neighbourhood, a point with a radius, your own polygon, or any search URL of the site.
- 🧩 **Nothing missed, nothing twice**: the site shows 2,000 listings per search; larger searches are cut into price bands so that every listing is returned, each one once.
- 🗂️ **Several searches in one run**: places × keywords, with a cap per search so that one big city cannot eat the whole budget.
- 📉 **Price drops**: the former price, the drop in euros and in %, and a filter for lowered prices only.
- 🔔 **Monitoring built in**: tick **Only new listings**, schedule the Actor, and each run returns (and charges) only what it has never delivered before.
- 🌍 **7 languages**: titles, typologies and translated descriptions in Italian, English, German, Spanish, French, Portuguese or Greek.
- 🔌 API, scheduling, integrations (Make, Zapier, n8n, Google Sheets…) and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape Immobiliare.it

1. Create a free Apify account.
2. Open **Immobiliare.it Listings Scraper**, choose **For sale** or **For rent** and a **Property type**, and type a **Location** (e.g. `Bologna`).
3. Or paste your own Immobiliare.it URLs into **Start URLs**: any search results page (every filter set on the site is kept, pagination is automatic) or single listing pages.
4. Set **Max listings** (100 by default, 0 = no limit), tick **Include listing details** if you need the full listing page, then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

### 💰 How much does it cost to scrape Immobiliare.it?

This Actor uses **pay per event** pricing: you pay per listing saved, plus a small fee per run start, and a separate price per listing delivered with its full listing page (**Include listing details**, listing URLs and listing numbers). The exact prices are on the **Pricing** tab; higher Apify plans pay less per listing. Platform usage (compute, proxy) is included in the price. A listing filtered out, or already delivered in monitoring mode, is never charged.

### ⚙️ Input

```json
{
    "location": "Bologna",
    "maxItems": 200,
    "includeDetails": true
}
```

Several places and keywords, rentals under a budget, a cap per search, only the listings not delivered before:

```json
{
    "operation": "rent",
    "locations": ["Milano", "Toscana"],
    "searchQueries": ["terrazzo", "giardino"],
    "maxPrice": 1500,
    "minRooms": 2,
    "maxItemsPerQuery": 50,
    "onlyNew": true,
    "stateKey": "milano-rentals"
}
```

Around a point, penthouses only, newest first:

```json
{
    "latitude": 45.4642,
    "longitude": 9.19,
    "radiusKm": 1.5,
    "homeTypes": ["penthouse"],
    "sortBy": "newest"
}
```

Private sellers in Rome who lowered their price:

```json
{
    "location": "Roma",
    "privateSellersOnly": true,
    "onlyPriceDrops": true
}
```

Or with your own URLs:

```json
{
    "startUrls": [
        { "url": "https://www.immobiliare.it/vendita-case/milano/?prezzoMassimo=300000" },
        { "url": "https://www.immobiliare.it/annunci/131456058/" }
    ],
    "listingIds": ["132289610"],
    "maxItems": 500
}
```

| Field | Notes |
| --- | --- |
| `operation` | `sale` (default) or `rent`. |
| `propertyType` | `homes` (default), `newDevelopments`, `rooms` (rent only), `offices`, `commercial`, `garages`, `storageRooms`, `sheds`, `lands`, `buildings`. |
| `homeTypes` | Only some kinds of homes: `apartment`, `penthouse`, `detachedHouse`, `villa`, `loft`. |
| `location`, `locations` | City, province or region as typed on the site (`Bologna`, `Provincia di Milano`, `Toscana`, a neighbourhood such as `Navigli`; a name several towns share with its province: `Samone, Trento`, `Castro (LE)`); `locations` adds more places, one search each (max 500 searches per run). |
| `query`, `searchQueries` | Word that must appear in the listing (`terrazzo`, `vista mare`); `searchQueries` adds more keywords, one search each, times each place. Alone, a keyword searches the whole of Italy. |
| `latitude`, `longitude`, `radiusKm` | Search around a point: `45.4642` with `longitude`, and a radius in km (2 by default). |
| `polygon` | Your own area: corners `latitude,longitude` separated by `;` (`45.47,9.17;45.47,9.21;45.45,9.21;45.45,9.17`). |
| `startUrls` | Search results pages (every filter set on the site is kept, pagination automatic) or listing pages (`https://www.immobiliare.it/annunci/131456058/`). When set, the place, keyword, point and polygon fields are ignored; the filters still apply. Max 1,000 URLs. |
| `listingIds` | Listing numbers, read with their full listing page (`131456058`). Given alone, only these listings are returned. |
| `maxItems` | Stop after this many listings for the whole run (`0` = unlimited). |
| `maxItemsPerQuery` | Cap for EACH search (place × keyword, or search URL). `0` = no per-search cap. |
| `splitLargeSearches` | On (default): a search of more than 2,000 listings is cut into price bands, so that you get all of them. |
| `sortBy` | `relevance` (default), `newest`, `oldest`, `priceLow`, `priceHigh`, `sizeLarge`, `sizeSmall`, `roomsMost`, `roomsLeast`. |
| `language` | `it` (default), `en`, `de`, `es`, `fr`, `pt`, `el`: language of titles, typologies and translated descriptions (an untranslated listing keeps its original text, as its page shows it, with details). Prices, sizes and dates are the same numbers in every language. |
| `includeDetails` | Open each listing page: full description, energy, costs, dates, building year, floor plans, videos, price per m² (charged per listing with details). |
| `minPrice`, `maxPrice`, `minSize`, `maxSize` | Price in euros (monthly rent for rentals) and size in m²: `150000`. |
| `minRooms`, `maxRooms`, `minBedrooms`, `maxBedrooms` | Rooms as the site counts them (locali) and bedrooms, from 1 to 5: `2`. |
| `bathrooms` | Exact number of bathrooms: `1`, `2`, `3`, `4+` (more than 3). |
| `condition` | `new`, `renovated`, `good`, `toRenovate`. |
| `floors` | `ground`, `intermediate`, `top`. |
| `garden` | `private`, `shared`. |
| `garage` | `single`, `double`, `parkingSpace`. |
| `heating` | `independent`, `central`, `airConditioning`. |
| `balconyTerrace` | `balcony`, `terrace`. |
| `ownership` | `full`, `bare`, `partial`, `usufruct`, `timeshare`, `landLease`. |
| `hasElevator`, `hasBasement`, `hasSwimmingPool`, `furnished`, `virtualTourOnly`, `excludeAuctions`, `rentedOnly` | Tick to keep only the listings with an elevator, a cellar, a pool, furnished, with a virtual tour, not at auction, or sold with a tenant. |
| `postedAfter`, `postedBefore` | First publication date range: `2026-09-01`, or a period before now (`7 days`, `2 weeks`, `1 month`, `24 hours`). Needs `includeDetails`. |
| `excludeKeywords` | Drop the listings whose title or description contains one of these words (`asta`; case and accents ignored). |
| `privateSellersOnly`, `agenciesOnly`, `requirePhone`, `excludeNewDevelopments` | Keep only private sellers, or only agencies; only listings with a phone number; leave out the new developments. |
| `onlyPriceDrops`, `minPriceDropPercent` | Only listings whose price was lowered; `minPriceDropPercent` (from 1 to 90) keeps drops of at least that much and switches `onlyPriceDrops` on by itself. |
| `onlyNew`, `stateKey`, `resetState` | Monitoring: only the listings never delivered under this memory key (`milano-rentals`); `resetState` forgets the memory. |
| Advanced | `proxyConfiguration` (Apify proxy by default, included in the price; the residential proxy is not available), `maxConcurrency`, `maxRequestsPerMinute`, `minRequestIntervalMs`, `maxRequestRetries`, `debugLog`. |

### 📦 Output

A listing of a real run with **Include listing details** on (lists and description shortened):

```json
{
    "id": "132052706",
    "uuid": "762df93a-23d4-5c56-97a5-7b4b967e149c",
    "url": "https://www.immobiliare.it/annunci/132052706/",
    "title": "Appartamento Solari 13, Corticella, Bologna",
    "operation": "sale",
    "propertyType": "Residenziale",
    "categoryId": 1,
    "typology": "Appartamento",
    "typologyId": 14,
    "price": 310000,
    "currency": "EUR",
    "priceText": "€ 310.000",
    "priceRange": "300.001 - 500.000 €",
    "maxPrice": null,
    "pricePerM2": 2583,
    "previousPrice": 340000,
    "priceDropValue": 30000,
    "priceDropPercent": 8.8,
    "priceDropDate": "2026-09-23",
    "size": 120,
    "sizeText": "120 m²",
    "surfaceBreakdown": [
        "Abitazione: 105,0 m² (100 %)",
        "Box o garage: 6,0 m² (50 %)"
    ],
    "rooms": 5,
    "roomsText": "5+",
    "bedrooms": 3,
    "bathrooms": 2,
    "floor": "T, 1",
    "floorText": "Piano terra, 1",
    "totalFloors": 3,
    "hasLift": false,
    "condition": "Ottimo / Ristrutturato",
    "heating": "Centralizzato",
    "heatingType": "Centralizzato, a radiatori, alimentato a gas",
    "airConditioning": "Autonomo, freddo/caldo",
    "garage": "1 in box privato/box in garage, 1 posto auto",
    "features": [
        "Armadio a muro",
        "Cancello elettrico"
    ],
    "hasBalcony": true,
    "hasTerrace": false,
    "hasGarden": true,
    "hasCellar": true,
    "views": [],
    "isNew": false,
    "isLuxury": false,
    "isProject": false,
    "unitsCount": null,
    "visibility": "supervetrina",
    "address": "Solari",
    "streetNumber": "13",
    "zone": "Bolognina, Corticella, Pescarola",
    "microzone": "Corticella",
    "city": "Bologna",
    "province": "Bologna",
    "provinceCode": "BO",
    "region": "Emilia Romagna",
    "country": "IT",
    "latitude": 44.5409,
    "longitude": 11.3587,
    "geohash": "srbj6krj",
    "headline": "Tricamere ristrutturato con garage, cantina e posto auto",
    "description": "Proponiamo in esclusiva un ampio tricamere nel cuore del quartiere Corticella, a due passi dalla sorgente linea verde del tram, in un contesto riservato ed e…",
    "descriptionIsFull": true,
    "thumbnail": "https://pwm.im-cdn.it/image/1995745700/xxl.jpg",
    "images": [
        "https://pwm.im-cdn.it/image/1995745700/xxl.jpg",
        "https://pwm.im-cdn.it/image/1995745704/xxl.jpg"
    ],
    "imageCaptions": [
        "Facciata",
        "Corridoio"
    ],
    "imageCount": 43,
    "hasVirtualTour": true,
    "virtualTourUrls": [
        "https://www.casa360.net/virtualtour/60042"
    ],
    "videos": [
        "https://youtube.com/embed/RBhZQeHwBf0",
        "https://youtube.com/embed/ieuhCeylk78"
    ],
    "floorPlans": [
        "https://pic.im-cdn.it/plan/133673120/xxl.jpg"
    ],
    "advertiserType": "agency",
    "advertiserName": "L'Arte di Abitare - Bologna Navile",
    "agencyId": "225902",
    "agencyUrl": "https://www.immobiliare.it/agenzie-immobiliari/225902/arte-di-abitare-bologna/",
    "agencyLogo": "https://pic.im-cdn.it/imagenoresize/1828880671.jpg",
    "agencyIsPaid": true,
    "agencyGuaranteed": false,
    "visitBookable": true,
    "virtualVisitAvailable": false,
    "agentName": "Arte Di Abitare",
    "phone": "+390519527834",
    "phones": [
        "+390519527834"
    ],
    "phoneImageUrl": null,
    "publishedAt": "2026-08-31T13:21:26.000Z",
    "updatedAt": "2026-09-23T09:36:49.000Z",
    "energyClass": "F",
    "energyPerformance": "186.98 kWh/m³ anno",
    "condominiumFees": "€ 90/mese",
    "heatingCosts": "€ 1.080/anno",
    "agencyCommission": null,
    "rentDeposit": null,
    "buildingYear": 1964,
    "availability": "libero",
    "kitchen": "Cucina abitabile",
    "typologyDetails": "Appartamento | Intera proprietà | Classe immobile signorile",
    "reference": "CO-28",
    "hasDetails": true,
    "search": "Bologna",
    "searchUrl": "https://www.immobiliare.it/search-list/?idContratto=1&idCategoria=1&fkRegione=emi&idProvincia=BO&idComune=5890&__lang=it&pag=1",
    "page": 2,
    "positionOnPage": 21,
    "scrapedAt": "2026-09-25T16:00:56.496Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### All 101 fields

Fields marked **(details)** are filled when **Include listing details** is on (and for listing URLs and numbers), `null` otherwise.

| Fields | What you get |
| --- | --- |
| `id`, `uuid`, `url`, `title` | **Listing**: `132289610`, its unique id, the listing page, `Trilocale via Alberto Dallolio, Mazzini - Fossolo, Bologna` |
| `operation`, `propertyType`, `categoryId`, `typology`, `typologyId` | `sale` or `rent`, `Residenziale` (1), `Trilocale` (14) |
| `price`, `currency`, `priceText`, `priceRange`, `maxPrice` | **Price**: `340000`, `EUR`, `€ 340.000`, `300.001 - 500.000 €`; the highest price of a new development with several units |
| `pricePerM2` | `3778` (details) |
| `previousPrice`, `priceDropValue`, `priceDropPercent`, `priceDropDate` | the price before the last drop, the drop in euros and in %, its day — `null` when the price was never lowered |
| `size`, `sizeText`, `surfaceBreakdown` | **Property**: `90`, `90 m²`, the parts of the surface (details) |
| `rooms`, `roomsText`, `bedrooms`, `bathrooms` | `3`, `3` (`5+`, `2 - 4` for a development), `2`, `1` |
| `floor`, `floorText`, `totalFloors`, `hasLift` | `2`, `2°`, floors of the building (details), elevator |
| `condition`, `heating`, `heatingType`, `airConditioning`, `garage` | `Ottimo / Ristrutturato`, `Centralizzato`, the heating and cooling systems (details), `1 posto auto` |
| `features`, `hasBalcony`, `hasTerrace`, `hasGarden`, `hasCellar`, `views` | every feature the site lists, balcony, terrace, garden and cellar as true / false, `panoramica`, `mare`… |
| `isNew`, `isLuxury`, `isProject`, `unitsCount`, `visibility` | flags of the site, a new development and its units, the ad level the agency bought (`supervetrina`) |
| `address`, `streetNumber`, `zone`, `microzone` | **Location**: `Via Alberto Dallolio`, its number (details), `San Vitale, Mazzini`, `Mazzini - Fossolo` |
| `city`, `province`, `provinceCode`, `region`, `country` | `Bologna`, `Bologna`, `BO` (details), `Emilia Romagna`, `IT` |
| `latitude`, `longitude`, `geohash` | `44.4771`, `11.3966`, `srbj52fc` |
| `headline`, `description`, `descriptionIsFull` | **Text**: the advertiser's heading, the description (first 600 characters without details, full text with them), which one it is |
| `thumbnail`, `images`, `imageCaptions`, `imageCount` | **Media**: main photo, every photo in large size, their captions (`Salone`), how many |
| `hasVirtualTour`, `virtualTourUrls`, `videos`, `floorPlans` | virtual tour, its links, videos and floor plans (details) |
| `advertiserType`, `advertiserName`, `agencyId`, `agencyUrl`, `agencyLogo` | **Agency**: `agency`, `builder` or `private`, `Gabetti Franchising Bologna Porta Santo Stefano`, its page and logo |
| `agencyIsPaid`, `agencyGuaranteed`, `visitBookable`, `virtualVisitAvailable`, `agentName` | subscription and guarantee badge of the agency, visits bookable online or by video, the agent in charge |
| `phone`, `phones`, `phoneImageUrl` | **Contact**: `051 952 3290`, every number shown, a private seller's number (shown by the site as a picture) |
| `publishedAt`, `updatedAt` | **Dates** (details): `2026-09-09T11:37:37.000Z`, `2026-09-19T10:05:17.000Z` |
| `energyClass`, `energyPerformance` | **Energy** (details): `B`, `≥ 3,51 kWh/m² anno` |
| `condominiumFees`, `heatingCosts`, `agencyCommission`, `rentDeposit` | **Costs** (details): `€ 30/mese`, heating costs, agency fee, deposit |
| `buildingYear`, `availability`, `kitchen`, `typologyDetails`, `reference` | **Details**: `1950`, `libero`, `Cucina angolo cottura`, the typology in words, the agency's reference |
| `hasDetails`, `search`, `searchUrl`, `page`, `positionOnPage`, `scrapedAt` | **Run**: listing page read or not, the search that found the listing (a URL you can paste back into Start URLs), results page and position, ISO timestamp |

### 💡 Tips

#### How to get more results

The site shows at most 2,000 listings per search. Leave **Get every listing of large searches** on: a larger search (a big city, a region) is cut into price bands, each under that limit, and every listing comes back once. Set `maxItems` to `0` to get the whole search, and use several places and keywords to cover more ground in one run.

#### How to reduce costs

The price is per listing, so the levers are `maxItems`, `maxItemsPerQuery`, the filters (a filtered-out listing is free) and `onlyNew` for recurring runs (you never pay twice for the same listing). Leave **Include listing details** off when price, size, rooms, position, agency and phones are enough: those listings cost less and come much faster.

#### Several searches in one run

Fill `locations` and / or `searchQueries`: the Actor runs one search per place × keyword (3 keywords × 4 cities = 12 searches, up to 500 per run). The single `location` and `query` fields still work and are added to the lists. A point (`latitude`, `longitude`, `radiusKm`) and a `polygon` are places too. A listing found by several searches is saved — and charged — once. Set `maxItemsPerQuery` to give every search its own cap: without it the first searches can use up the whole `maxItems` budget. You can also paste several search URLs into `startUrls`: each one is a search of its own, with the same cap.

#### Monitoring: only the new listings

Tick **Only new listings** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the listings already delivered: they are not saved, not charged, and their page is not even opened. The memory lives in a named key-value store of your account (`immobiliare-listings-scraper-seen`, up to 150,000 listings per key) and is only updated with listings that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey` (two schedules sharing a key would hide each other's listings), and tick `resetState` once to start over. With the default sort, searches are then sorted by newest, and a search stops once it meets 50 listings in a row you already have.

#### Filter by publication date

`postedAfter` and `postedBefore` take a date (`2026-09-01`, the whole day is included, Italian time) or a period before now (`7 days`, `2 weeks`, `1 month`; via the API also `24 hours` or a full ISO date-time). The date is the listing's first publication, given by its listing page: the filter needs **Include listing details**. Filtered-out listings are never charged and do not count in `maxItems`; the run summary tells how many were filtered.

#### Price drops and private sellers

`onlyPriceDrops` keeps the listings whose price was lowered (the former price, the drop and its day come with every listing anyway); `minPriceDropPercent` asks for a minimum drop. `privateSellersOnly` keeps the listings of private owners — their phone number is shown by the site as a picture, given in `phoneImageUrl`.

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### ❓ FAQ

#### Is it legal to scrape Immobiliare.it?

The Actor only reads what Immobiliare.it shows publicly to any anonymous visitor. It logs in to nothing. Results can contain personal data (names and phone numbers of agents and private sellers), which is protected by GDPR: do not store it without a legitimate reason. You are responsible for using the data in compliance with Immobiliare.it's Terms of Use and applicable law. This Actor is not affiliated with Immobiliare.it.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request the site turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds).

#### Is the data safe to open in Excel or to show on a web page?

Titles and descriptions are the advertisers' own words, copied as they are. A text can begin with `-`, `+`, `=` or `@` (a title such as `-20% sul prezzo`): Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number, and phone numbers such as `051 952 3290` lose their leading zero if a column is read as numbers. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. On a web page, escape every field like any text written by a stranger.

#### Known limitations

- Site filters that are not in the input can still be used by pasting a filtered search URL into `startUrls`.
- The full description, the dates, energy, costs, floor plans and videos come from the listing page: they are `null` (or the first 600 characters of the description) when `includeDetails` is off.
- A private seller's phone number is shown by the site as a picture: the Actor gives its link (`phoneImageUrl`), not the digits.
- `onlyNew` remembers listing ids, not their content: a listing whose price changed is not returned again (the price drop fields tell you when it was lowered).
- Two runs sharing the same `stateKey` at the same time may both return the same new listing.

**A run the platform stops without warning** (out of memory, run timeout)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the listings already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved once a minute: resurrect the stopped run and the listings it had saved meanwhile join the memory; leave it stopped for good, and the next run may return up to a minute of them once more.

#### Something doesn't work?

The last line of the log counts the listings saved, filtered out and no longer on Immobiliare.it (removed while the run was reading them), and the requests that failed after every retry. Those requests and the removed listings are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A place the site does not know, or a pasted page that is not a search, is listed there too; a run that saved nothing and had failed requests fails, and its last message gives the cause.

If Immobiliare.it changes its pages, you are told instead of paying for blank rows. A results page that counts listings but gives none the Actor can read is an error (listed in `FAILED_REQUESTS`), never a quiet "No listings found". If the first 20 listings read all lack their title, city or — with `includeDetails` — publication date, the run saves nothing more, stops and fails, and its last message names the missing field: at most those first listings are charged. A listing that `postedAfter` / `postedBefore` drops because it has no date at all counts among those 20.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which URLs failed and why.

# Actor input Schema

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

For sale or for rent. Ignored for pasted URLs (they keep their own).

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

Category searched, as in the site's menu. Ignored for pasted URLs.

## `homeTypes` (type: `array`):

Only these kinds of homes (Property type = Homes). Empty = all.

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

Italian city, province or region, as typed on the site (e.g. `Bologna`, `Provincia di Milano`, `Toscana`). The first match of the site's own suggestions is used; the run log says which one. A name several towns share: add the province (`Samone, Trento` or `Samone (TN)`).

## `locations` (type: `array`):

Several locations in one run: one search per location (times each keyword below, max 500 searches). Added to **Location**.

## `query` (type: `string`):

Word that must appear in the listing (the site's own keyword filter, e.g. `terrazzo`, `vista mare`). Empty = no keyword.

## `searchQueries` (type: `array`):

Several keywords in one run: one search per keyword (times each location). Added to **Keyword**; listings found by several searches are saved once.

## `startUrls` (type: `array`):

Immobiliare.it search-result URLs (every filter set on the site is kept, pagination is automatic, map searches too) or single listing URLs (`https://www.immobiliare.it/annunci/123456789/`). When this list is not empty, Location, Keyword, point and polygon are ignored; the filters below still apply to search URLs. Max 1 000 URLs.

## `listingIds` (type: `array`):

Listing numbers (the digits of `/annunci/<id>/`). Each one is read with its details (charged as a listing plus its details). Given alone, only these listings are returned.

## `latitude` (type: `number`):

Search around a point instead of a location: latitude in decimal degrees, e.g. 45.4642 (Milan). Needs Longitude; Radius sets the distance.

## `longitude` (type: `number`):

Longitude in decimal degrees, e.g. 9.19 (Milan).

## `radiusKm` (type: `number`):

Distance around the point, in kilometres.

## `polygon` (type: `string`):

Draw your own area: corner points as `latitude,longitude` separated by `;` (at least 3, at most 100), e.g. `45.47,9.17;45.47,9.21;45.45,9.21;45.45,9.17`.

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

Maximum number of listings to save for the whole run (after deduplication and filters). 0 = no limit.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (location × keyword, or search URL), so that the first search cannot use up the whole **Max listings** budget. 0 = no per-search cap.

## `splitLargeSearches` (type: `boolean`):

The site shows at most 2 000 listings per search. On: a larger search is cut into price bands, each under that limit, so that every listing is returned (duplicates removed). Off: the first 2 000 only.

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

Order of the results, as on the site. With **Only new listings**, Relevance becomes Newest first, so that a search can stop at the listings already delivered.

## `language` (type: `string`):

Language of titles, typologies and floors, and of the description when the advertiser gave a translation (the site's own translations); otherwise the listing page shows, and the Actor returns with details, the original text. Italian = the site default.

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

Open each listing page for the full description, energy class and performance, condominium and heating costs, publication and update dates, building year, condition, all features, agency reference and price per m². Charged per listing with details (see Pricing). Off = the search-result fields only (price, size, rooms, GPS, zone, agency and phones, 600-character description).

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

Lowest price, in euros (monthly rent for rentals).

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

Highest price, in euros (monthly rent for rentals).

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

Smallest surface, in square metres.

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

Largest surface, in square metres.

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

Fewest rooms, counted like the site (`locali`: bedrooms + living rooms, kitchen excluded).

## `maxRooms` (type: `integer`):

Most rooms (`locali`).

## `minBedrooms` (type: `integer`):

Fewest bedrooms.

## `maxBedrooms` (type: `integer`):

Most bedrooms.

## `bathrooms` (type: `string`):

Exact number of bathrooms, as on the site.

## `condition` (type: `string`):

State of the property.

## `floors` (type: `array`):

Ground floor, intermediate floors and/or top floor. Empty = any.

## `garden` (type: `array`):

Private and/or shared garden. Empty = any.

## `garage` (type: `array`):

Single garage, double garage and/or parking space. Empty = any.

## `heating` (type: `array`):

Independent heating, central heating and/or air conditioning. Empty = any.

## `balconyTerrace` (type: `array`):

With a balcony and/or a terrace. Empty = any.

## `ownership` (type: `string`):

Kind of ownership sold.

## `hasElevator` (type: `boolean`):

Only listings with an elevator.

## `hasBasement` (type: `boolean`):

Only listings with a cellar (cantina).

## `hasSwimmingPool` (type: `boolean`):

Only listings with a swimming pool.

## `furnished` (type: `boolean`):

Only furnished properties.

## `virtualTourOnly` (type: `boolean`):

Only listings with a virtual tour.

## `excludeAuctions` (type: `boolean`):

Leave out properties sold at auction (aste).

## `rentedOnly` (type: `boolean`):

Only properties sold with a tenant in place (a reddito).

## `postedAfter` (type: `string`):

Only listings first published on or after this date (the date the listing page gives, so it needs **Include listing details**): `2026-09-01`, or a period before now such as `7 days`, `2 weeks`, `1 month` (API: `24 hours` and full ISO date-times work too).

## `postedBefore` (type: `string`):

Only listings first published on or before this date (the whole day is included), or older than a period such as `30 days`. Needs **Include listing details**.

## `excludeKeywords` (type: `array`):

Drop the listings whose title or description contains one of these words (case and accents ignored).

## `privateSellersOnly` (type: `boolean`):

Only listings posted by private owners (no agency).

## `agenciesOnly` (type: `boolean`):

Only listings posted by an agency or a builder.

## `requirePhone` (type: `boolean`):

Only listings that show at least one phone number.

## `excludeNewDevelopments` (type: `boolean`):

Leave out the new-build projects that group several units in one listing.

## `onlyPriceDrops` (type: `boolean`):

Only listings whose price was lowered (the site shows the former price).

## `minPriceDropPercent` (type: `integer`):

Only listings whose price dropped by at least this percentage (setting it switches **Price drops only** on by itself).

## `onlyNew` (type: `boolean`):

Skip the listings that a previous run (same **Memory key**) already delivered: they are not saved and not charged. First run = everything is new. Works best with **Sort by** = Newest first.

## `stateKey` (type: `string`):

Name of the memory used by **Only new listings**. Give each schedule / task its own key (e.g. `milano-rentals`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every listing again. Untick it afterwards.

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

Apify Proxy or your own proxies. Keep the default: it is included in the price. The residential Apify proxy is not available in this Actor.

## `maxConcurrency` (type: `integer`):

Maximum number of result pages read in parallel.

## `maxRequestsPerMinute` (type: `integer`):

Budget of requests per minute for the whole run.

## `minRequestIntervalMs` (type: `integer`):

Smallest gap between two requests, in milliseconds. Unlike the per-minute budget, this spreads the requests evenly. 0 = no gap.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed. A request the site turns away is also retried at once on a new proxy session up to 10 times without using up these retries.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "operation": "sale",
  "propertyType": "homes",
  "homeTypes": [],
  "location": "Bologna",
  "locations": [],
  "searchQueries": [],
  "startUrls": [],
  "listingIds": [],
  "radiusKm": 2,
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "splitLargeSearches": true,
  "sortBy": "relevance",
  "language": "it",
  "includeDetails": false,
  "bathrooms": "",
  "condition": "",
  "floors": [],
  "garden": [],
  "garage": [],
  "heating": [],
  "balconyTerrace": [],
  "ownership": "",
  "hasElevator": false,
  "hasBasement": false,
  "hasSwimmingPool": false,
  "furnished": false,
  "virtualTourOnly": false,
  "excludeAuctions": false,
  "rentedOnly": false,
  "excludeKeywords": [],
  "privateSellersOnly": false,
  "agenciesOnly": false,
  "requirePhone": false,
  "excludeNewDevelopments": false,
  "onlyPriceDrops": false,
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 4,
  "maxRequestsPerMinute": 150,
  "minRequestIntervalMs": 300,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# Actor output Schema

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

No description

# 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": "Bologna",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/immobiliare-listings-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": "Bologna",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/immobiliare-listings-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": "Bologna",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/immobiliare-listings-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/immobiliare-listings-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/U5yuNvobXZ3WIgAxC/builds/8wuRkpFCFAmgEOGce/openapi.json
