# Italy Real Estate Listings: Livability & Risk (`evitalya/italy-real-estate-listing-enrichment`) Actor

Enriches listings scraped from Idealista, Immobiliare.it, Casa.it or any source that carries coordinates: a 0-100 livability score, six category scores (safety, services, mobility, environment, real estate, natural risk), its reliability and the ISTAT comune. You pay only for scored listings.

- **URL**: https://apify.com/evitalya/italy-real-estate-listing-enrichment.md
- **Developed by:** [Francesco Rozzi](https://apify.com/evitalya) (community)
- **Categories:** Real estate, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.00 / 1,000 listing scoreds

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?

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

## Italy Real Estate Listings: Livability & Risk

You scraped Italian property listings. They tell you the price, the size and the photos.
They do not tell you **what the place around them is like**.

This Actor takes the listings you already have and adds a **0-100 livability score**, the
score of **six categories** — safety, services, mobility, environment, real estate,
natural risk — how reliable that score is, and the **ISTAT comune and province** of the
point. The numbers come from 111 indicators built on official Italian sources.

### The next step after your scraper

1. Run a listing scraper — **Idealista**, **Immobiliare.it**, **Casa.it**, or any Actor
   whose items carry coordinates.
2. Copy the **dataset ID** of that run into this Actor's input. No reformatting: it reads
   the items as they are.
3. Get the same listings back, each with one extra field, `evitalya`.

Twelve coordinate field pairs used by the common scrapers are detected automatically
(`latitude`/`longitude`, `lat`/`lng`, `location.lat`, `coordinates.latitude`, `geo.lat`,
`ubication.latitude` and more). For anything else, name the two fields in the input.

### Input

Either a **Dataset ID** from another run, or the **listings** themselves as a JSON array.
`Maximum listings` stops the run early; the two field settings are only for unusual item
shapes.

### Output

```json
{
  "url": "https://www.immobiliare.it/annunci/00000001/",
  "title": "Trilocale, Porta Romana, Milano",
  "price": 495000,
  "latitude": 45.4515,
  "longitude": 9.2003,
  "evitalya": {
    "status": "scored",
    "score": 71.61,
    "reliability": 0.9459,
    "reliability_code": "high",
    "categories": {"safety": 65.62, "services": 89.77, "mobility": 78.48,
                   "enviro": 36.98, "realestate": 72.92, "natural_risk": 85.9},
    "insufficient_data": [],
    "istat": "015146",
    "comune": "Milano",
    "provincia": "Milano"
  }
}
```

`status` is `scored`, `no_coordinates` (the item carries no coordinate pair that falls
inside Italy - a point far from the country is not recognised as a location at all),
`outside_italy` (the coordinates are Italian-looking but sit in no Italian comune: the sea
just off the coast, San Marino, the Vatican, across the border) or `error_<code>`.

### What you pay

**Only listings that are scored are charged.** Items without coordinates, points outside
Italy and errors cost nothing. Apify platform usage is included in the price.

### Where the scores come from

ISTAT (census, crime, road accidents), Ministry of the Interior, ISPRA (flood and
landslide hazard, noise), INGV (seismic classification), the regional environmental
agencies, AGENAS (health), MUR (schools and universities), OMI - Agenzia delle Entrate
(property values), OpenStreetMap and Copernicus. Each score carries its own reliability,
and the categories that lacked data are named in `insufficient_data` instead of being
quietly averaged away.

Method and sources: <https://evitalya.com/api.html>

### Limits

- **Apify free plan: the first 50 listings of a run are scored**, and the run status says
  so. Any paid Apify plan scores them all.
- Italy only. The comune is the one whose ISTAT census section contains the point.
- Listings are processed at about one per second.
- Scores describe the area, not the building: they are area-level indicators from official
  statistics, not an inspection.

### Questions

**Does it work with the output of any scraper?** Yes, as long as each item carries
coordinates. The common field names are recognised; unusual ones you name yourself.

**My listings only have an address, no coordinates.** They come back as
`no_coordinates`, free of charge. This Actor does not geocode addresses.

**What may I do with the scores?** Every score you publish must carry a visible
Evitalya credit and a link to evitalya.com, and the score is a statistical indicator of the
area, never an official valuation. The licence itself is set out in article 21 of the
Evitalya terms: <https://evitalya.com/terms.html>.

**How current are the numbers?** Each source is refreshed on its own official calendar -
yearly for most statistical series, and the hazard layers when the agencies republish them.

# Actor input Schema

## `datasetId` (type: `string`):

The dataset produced by a listing scraper (for example an Idealista or Immobiliare.it Actor run). Each item needs latitude and longitude.

## `listings` (type: `array`):

Alternatively, the listings themselves, as a JSON array of objects with coordinates.

## `latitudeField` (type: `string`):

Only if your items use an unusual field name. Dot paths are allowed, for example location.lat. Common names are detected automatically.

## `longitudeField` (type: `string`):

Only if your items use an unusual field name. Dot paths are allowed.

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

Stop after this many listings. 0 means all.

## Actor input object example

```json
{
  "listings": [
    {
      "url": "https://example.com/listing/1",
      "latitude": 45.452,
      "longitude": 9.169
    }
  ]
}
```

# Actor output Schema

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

The default dataset, one item per listing, in the order they were given.

# 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 = {
    "listings": [
        {
            "url": "https://example.com/listing/1",
            "latitude": 45.452,
            "longitude": 9.169
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("evitalya/italy-real-estate-listing-enrichment").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 = { "listings": [{
            "url": "https://example.com/listing/1",
            "latitude": 45.452,
            "longitude": 9.169,
        }] }

# Run the Actor and wait for it to finish
run = client.actor("evitalya/italy-real-estate-listing-enrichment").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 '{
  "listings": [
    {
      "url": "https://example.com/listing/1",
      "latitude": 45.452,
      "longitude": 9.169
    }
  ]
}' |
apify call evitalya/italy-real-estate-listing-enrichment --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,evitalya/italy-real-estate-listing-enrichment"
        }
    }
}
```

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/hBmKVwpiUM4fRnQ3C/builds/35Uh1r8Nl5WFsku4W/openapi.json
