Sourced data on Italy's ~7,900 comuni for people relocating or retiring there.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
For one regime slug (from list_tax_regimes) and one 6-digit ISTAT code (from search_comuni): qualifies, does_not_qualify or not_assessable, with a one-sentence reason to quote. not_assessable is never a no. This is about the place only; say so, and never present it as whether a person qualifies or as tax advice.
A regime slug from /tax/regimes, e.g. "regime-7-percent-pensioners".
6-digit ISTAT comune code. Find it with /comuni?q=.
For one regime slug (from list_tax_regimes) and one 6-digit ISTAT code (from search_comuni): qualifies, does_not_qualify or not_assessable, with a one-sentence reason to quote. not_assessable is never a no. This is about the place only; say so, and never present it as whether a person qualifies or as tax advice.
| Argument | Type | Description |
|---|---|---|
| slug* | string | A regime slug from /tax/regimes, e.g. "regime-7-percent-pensioners". |
| comune* | string | 6-digit ISTAT comune code. Find it with /comuni?q=. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slug",
"comune"
],
"properties": {
"slug": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "A regime slug from /tax/regimes, e.g. \"regime-7-percent-pensioners\"."
},
"comune": {
"type": "string",
"pattern": "^\\d{6}$",
"description": "6-digit ISTAT comune code. Find it with /comuni?q=."
}
}
}Which Italian comuni match: region, province, population range, purchase-price and rent ranges (OMI), population change 2019–2025, the eight shortlist filters (January low, days above 30 C, regional hospital-care score, all three care scores at 60, tourist beds per resident, outside seismic zone 1, road time to a hospital with inpatient beds, road time to an airport) and/or the verified comuni of a tax regime. Paged (max 100) and sortable. Healthcare scores are region grain (autonomous-province grain for Bolzano and Trento): every town in the region shares the score. A comune with no price, rent, population-change, climate, healthcare, tourism, seismic or drive-time figure is left out of the filter on it and COUNTED in `missingData` — never treated as cheap, free or stable; say how many were left out. The taxRegime filter lists only comuni on the regime's verified routes: a comune missing from it is NOT a 'no' (the response says so in `taxRegime.note`). Rows carry plain numbers; their source and vintage are in `figures`. Use search_comuni to turn a town name into a code, get_comune for one town's full profile.
| Argument | Type | Description |
|---|---|---|
| q | string | Only comuni whose name contains this (case- and accent-insensitive). |
| sort | string | Sort key. A comune without a figure for the sort key always sorts last. |
| limit | integer | Rows per page, 1–100. Default 25. |
| order | string | Default: desc for population, populationChange, januaryLow and hospitalCareScore; asc for name, purchasePrice, rent, daysAbove30C, bedsPerResident, seismicClass, hospitalDriveMinutes and airportDriveMinutes. |
| offset | integer | Rows to skip, for the next page. |
| region | string | A region name or slug, e.g. "Abruzzo" or "valle-d-aosta". |
| province | string | A province's two-letter code ("AQ") or slug ("l-aquila"). |
| taxRegime | string | A verified geographic regime slug from /tax/regimes. Lists only comuni on the regime's verified routes; a comune missing from the list is NOT a "no" (the rule may admit comuni by routes not yet encoded). |
| maxPopulation | integer | Residents, inclusive. |
| minPopulation | integer | Residents, inclusive. |
| minJanuaryLowC | integer | [UI key jan] Average January daily minimum (ERA5-Land, 2015 to 2024) at least this many degrees C, whole numbers -10 to 12. Town grain. A comune with no figure is left out and counted in missingData. |
One article's full text as Markdown, with its places, datasets and a ready-made citation. Quote figures from the dataset pages it cites, which carry their vintage. Content is free to use provided you credit Expat Living Italy and link to the article.
| Argument | Type | Description |
|---|---|---|
| slug* | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"maxLength": 120,
"minLength": 1
}
}
}One Italian comune's population, foreign residents by citizenship, property purchase/rent price, price-to-rent, verified tax-regime eligibility, its province's rollup, `seismicZone` (the official zona sismica 1-4: a legal classification, not a forecast and not a verdict on any building; quote it with its label and say so — a comune that straddles zones has no single zone, never round it; the zone has nothing to do with tax eligibility, and is not the 7% regime’s “seismic” routes, which depend on the 2009 and 2016-17 earthquake areas), `layers` (climate, air quality, crime, healthcare quality, age, population change and every other Italy-map layer) and `provinceWellbeing` (ISTAT BES indicators, polarity-aware percentiles) — looked up by 6-digit ISTAT code. Each layer's `grain` and `measuredFor` say whose number it is: a province or region value is not a measurement of this comune — say so when you quote it. Every field is wrapped in a provenance envelope (source, vintage, extractedOn, license); repeat the vintage when you state the number, and if a value is null, say why rather than treating it as zero.
| Argument | Type | Description |
|---|---|---|
| istatCode* | string | 6-digit ISTAT comune code, e.g. 075029. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"istatCode"
],
"properties": {
"istatCode": {
"type": "string",
"pattern": "^\\d{6}$",
"description": "6-digit ISTAT comune code, e.g. 075029."
}
}
}For every dataset: how many places it covers, out of how many at its grain, plus the source's own coverage caveat. Pass `dataset` (a slug from list_datasets) to list the places that dataset lacks, with the gaps by region. Use it before telling anyone data does not exist for a place, and to explain a null. Missing means no figure, never a zero. Keys a source publishes that match no current place (a superseded province code) are reported and never mapped onto a current place. Drafts are listed as not served, without counts.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Missing places per page when dataset is given, 1–100. Default 50. |
| offset | integer | Missing places to skip, for the next page. |
| dataset | string | A dataset slug from /datasets. Omit it for the summary of every dataset; pass it to list the places that dataset lacks. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"limit": {
"type": "integer",
"default": 50,
"maximum": 100,
"minimum": 1,
"description": "Missing places per page when dataset is given, 1–100. Default 50."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 10000,
"minimum": 0,
"description": "Missing places to skip, for the next page."
},
"dataset": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "A dataset slug from /datasets. Omit it for the summary of every dataset; pass it to list the places that dataset lacks."
}
}
}For one tracked citizenship (ISO-2 code such as US, GB, DE): the comuni, provinces and regions where its holders concentrate, with counts and shares. It is CITIZENSHIP, not birthplace — foreign-born Italian citizens are not counted — and it carries small-number caveats: the comune ranking skips places under 1,000 residents by default and flags rows under 30 residents (`smallNumber`). A comune with no ISTAT row is left out, not counted as zero, so totals are floors. State those caveats when you quote a ranking; they are in the result's `caveats`. Province and comune lists are different levels of detail — say which.
| Argument | Type | Description |
|---|---|---|
| cc* | string | ISO-2 citizenship code of one of the citizenships this site tracks, e.g. "US". |
| limit | integer | How many comuni and provinces to list, 1–50. Default 10. |
| rankBy | string | share: residents with this citizenship as a fraction of the comune's population. count: absolute numbers. |
| minPopulation | integer | Smallest comune, in residents, that may appear in the comune ranking. Default 1,000: in a village of sixty, four foreign residents is not a finding. Lowering it lets tiny places top the ranking. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"cc"
],
"properties": {
"cc": {
"type": "string",
"pattern": "^[A-Za-z]{2}$",
"description": "ISO-2 citizenship code of one of the citizenships this site tracks, e.g. \"US\"."
},
"limit": {
"type": "integer",
"default": 10,
"maximum": 50,
"minimum": 1,
"description": "How many comuni and provinces to list, 1–50. Default 10."
},
"rankBy": {
"enum": [
"share",
"count"
],
"type": "string",
"default": "share",
"description": "share: residents with this citizenship as a fraction of the comune's population. count: absolute numbers."
},
"minPopulation": {
"type": "integer",
"maximum": 100000,
"minimum": 0,
"description": "Smallest comune, in residents, that may appear in the comune ranking. Default 1,000: in a village of sixty, four foreign residents is not a finding. Lowering it lets tiny places top the ranking."
}
}
}One Italian province (two-letter code such as AQ, or its slug — a comune's `provinceCode`): population, OMI prices, foreign residents by citizenship (citizenship, not birthplace), ALL ISTAT BES well-being indicators with polarity-aware percentiles among provinces (no composite score), every province- and region-grain map layer, `seismicZones` (how many of its comuni sit in each official seismic zone — a count of comuni, never an average, since a province has no zone of its own), and how much of the province meets each verified tax regime (places, not people). Sources use different province lists — Sardinia was reorganized in 2026 — so a section a source lacks is null with a reason and listed in `missingSections`: report it as missing, never substitute another province's figure.
| Argument | Type | Description |
|---|---|---|
| code* | string | A province's two-letter code, e.g. "AQ", or its slug, e.g. "l-aquila". Find it in a comune's `provinceCode`. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"code"
],
"properties": {
"code": {
"type": "string",
"pattern": "^[A-Za-z][A-Za-z0-9-]{1,59}$",
"description": "A province's two-letter code, e.g. \"AQ\", or its slug, e.g. \"l-aquila\". Find it in a comune's `provinceCode`."
}
}
}Dated, sourced reporting on moving to and retiring in Italy, newest first. Filter by topic, by place (a comune's ISTAT code) or by dataset slug. Each entry has its URL, a Markdown URL for the full text, and the places and datasets it cites. Content is free to use provided you credit Expat Living Italy and link to the article.
| Argument | Type | Description |
|---|---|---|
| place | string | A comune's 6-digit ISTAT code (or a province sigla / region slug). |
| topic | string | One of: tax, residency-visas, costs-housing, healthcare, places, daily-life, data-method. |
| dataset | string | A dataset slug from GET /datasets. |
| include | string | Pass `archived` to include archived articles, flagged by `status`. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"place": {
"type": "string",
"description": "A comune's 6-digit ISTAT code (or a province sigla / region slug)."
},
"topic": {
"type": "string",
"description": "One of: tax, residency-visas, costs-housing, healthcare, places, daily-life, data-method."
},
"dataset": {
"type": "string",
"description": "A dataset slug from GET /datasets."
},
"include": {
"enum": [
"archived"
],
"type": "string",
"description": "Pass `archived` to include archived articles, flagged by `status`."
}
}
}The catalog: each dataset's source institution, vintage (the period it describes), geographic grain, license, the expatliving.it page that presents it, and whether it is servable (false = still an unverified draft; never quote its values). Use it to say what data exists and where a reader can see it.
No arguments.
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {}
}Each regime's status (verified or draft), whether it depends on place (geographic) or on the person, its legislation, population ceiling and how many comuni meet its verified criteria. Places, not people: not tax advice.
No arguments.
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {}
}Look up Italian comuni by name (case- and accent-insensitive, partial names work) and get each one's 6-digit ISTAT code, province and region — the code get_comune needs. Returns identifiers only, no figures. Several comuni share a name; check the province before choosing.
| Argument | Type | Description |
|---|---|---|
| q* | string | A comune name or part of one, accents optional — e.g. "Introdacqua" or "reggio". |
| limit | integer | How many matches to return, 1–25. Default 10. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"q"
],
"properties": {
"q": {
"type": "string",
"maxLength": 80,
"minLength": 2,
"description": "A comune name or part of one, accents optional — e.g. \"Introdacqua\" or \"reggio\"."
},
"limit": {
"type": "integer",
"default": 10,
"maximum": 25,
"minimum": 1,
"description": "How many matches to return, 1–25. Default 10."
}
}
}| maxDaysAbove30C | integer | [UI key heat] Average days a year above 30 C (ERA5-Land, 2015 to 2024) at most this many, 0 to 120. Town grain. No figure: left out and counted. |
| maxRentEurM2Month | number | Rent in EUR/m2 per month, inclusive. A comune with no rent figure is left out. |
| minRentEurM2Month | number | Rent in EUR/m2 per month, inclusive. A comune with no rent figure is left out. |
| maxBedsPerResident | number | [UI key beds] Registered tourist beds per resident (ISTAT, 2024) at most this; one of 0.1, 0.5, 1. Town grain. A comune with no figure is left out and counted; a real zero is a figure. |
| excludeSeismicZone1 | any | [UI key seis] true: leave out comuni in official seismic zone 1, the highest hazard class (hazard class 4 in the map layer). A legal classification from the Dipartimento della Protezione Civile (31 May 2025), not a forecast. A comune with no single classification is left out and counted. |
| minHospitalCareScore | integer | [UI key hosp] Ministero della Salute NSG 2024 hospital-care score at least this, 50 to 100; 60 is the official sufficiency line. REGION grain: every comune in a region shares its region's score, except Bolzano-province and Trento-province comuni, which carry their own autonomous province's score. No figure: left out and counted. |
| maxPurchasePriceEurM2 | number | Purchase price in EUR/m2, inclusive. A comune with no price is left out, never treated as cheap. |
| minPurchasePriceEurM2 | number | Purchase price in EUR/m2, inclusive. A comune with no price is left out, never treated as cheap. |
| allCareScoresAtLeast60 | any | [UI key nsg60] true: the NSG prevention, community-care and hospital-care scores must all be at least 60. Region grain (autonomous-province grain for Bolzano and Trento). A comune missing any of the three is left out and counted. |
| maxAirportDriveMinutes | number | [UI key adrive] Minutes by road from the comune's main town to the nearest of the airports where ENAC recorded at least 4,000 passengers in 2025 (it leaves out Taranto-Grottaglie and Brescia-Montichiari, which carried almost none), at most this; one of 60, 90, 120, 180. Town grain, free-flow, approximate; says nothing about flights. No figure: left out and counted. |
| maxPopulationChangePct | number | Population change 2019 to 2025, in percent, inclusive. |
| minPopulationChangePct | number | Population change 2019 to 2025, in percent, inclusive. A negative value means decline. |
| maxHospitalDriveMinutes | number | [UI key hdrive] Minutes by road from the comune's main town to the nearest hospital with inpatient beds (Ministero della Salute 2023 list, OpenStreetMap roads) at most this; one of 15, 30, 45, 60. Town grain, free-flow, approximate. Not necessarily a hospital with an emergency department. A comune with no figure (for example a ferry-only island) is left out and counted. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"q": {
"type": "string",
"maxLength": 80,
"minLength": 2,
"description": "Only comuni whose name contains this (case- and accent-insensitive)."
},
"sort": {
"enum": [
"population",
"name",
"purchasePrice",
"rent",
"populationChange",
"januaryLow",
"daysAbove30C",
"hospitalCareScore",
"bedsPerResident",
"seismicClass",
"hospitalDriveMinutes",
"airportDriveMinutes"
],
"type": "string",
"default": "population",
"description": "Sort key. A comune without a figure for the sort key always sorts last."
},
"limit": {
"type": "integer",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Rows per page, 1–100. Default 25."
},
"order": {
"enum": [
"asc",
"desc"
],
"type": "string",
"description": "Default: desc for population, populationChange, januaryLow and hospitalCareScore; asc for name, purchasePrice, rent, daysAbove30C, bedsPerResident, seismicClass, hospitalDriveMinutes and airportDriveMinutes."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 10000,
"minimum": 0,
"description": "Rows to skip, for the next page."
},
"region": {
"type": "string",
"maxLength": 60,
"minLength": 2,
"description": "A region name or slug, e.g. \"Abruzzo\" or \"valle-d-aosta\"."
},
"province": {
"type": "string",
"maxLength": 60,
"minLength": 2,
"description": "A province's two-letter code (\"AQ\") or slug (\"l-aquila\")."
},
"taxRegime": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "A verified geographic regime slug from /tax/regimes. Lists only comuni on the regime's verified routes; a comune missing from the list is NOT a \"no\" (the rule may admit comuni by routes not yet encoded)."
},
"maxPopulation": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Residents, inclusive."
},
"minPopulation": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Residents, inclusive."
},
"minJanuaryLowC": {
"type": "integer",
"maximum": 12,
"minimum": -10,
"description": "[UI key jan] Average January daily minimum (ERA5-Land, 2015 to 2024) at least this many degrees C, whole numbers -10 to 12. Town grain. A comune with no figure is left out and counted in missingData."
},
"maxDaysAbove30C": {
"type": "integer",
"maximum": 120,
"minimum": 0,
"description": "[UI key heat] Average days a year above 30 C (ERA5-Land, 2015 to 2024) at most this many, 0 to 120. Town grain. No figure: left out and counted."
},
"maxRentEurM2Month": {
"type": "number",
"minimum": 0,
"description": "Rent in EUR/m2 per month, inclusive. A comune with no rent figure is left out."
},
"minRentEurM2Month": {
"type": "number",
"minimum": 0,
"description": "Rent in EUR/m2 per month, inclusive. A comune with no rent figure is left out."
},
"maxBedsPerResident": {
"type": "number",
"description": "[UI key beds] Registered tourist beds per resident (ISTAT, 2024) at most this; one of 0.1, 0.5, 1. Town grain. A comune with no figure is left out and counted; a real zero is a figure."
},
"excludeSeismicZone1": {
"anyOf": [
{
"type": "boolean"
},
{
"enum": [
"true",
"false"
],
"type": "string"
}
],
"description": "[UI key seis] true: leave out comuni in official seismic zone 1, the highest hazard class (hazard class 4 in the map layer). A legal classification from the Dipartimento della Protezione Civile (31 May 2025), not a forecast. A comune with no single classification is left out and counted."
},
"minHospitalCareScore": {
"type": "integer",
"maximum": 100,
"minimum": 50,
"description": "[UI key hosp] Ministero della Salute NSG 2024 hospital-care score at least this, 50 to 100; 60 is the official sufficiency line. REGION grain: every comune in a region shares its region's score, except Bolzano-province and Trento-province comuni, which carry their own autonomous province's score. No figure: left out and counted."
},
"maxPurchasePriceEurM2": {
"type": "number",
"minimum": 0,
"description": "Purchase price in EUR/m2, inclusive. A comune with no price is left out, never treated as cheap."
},
"minPurchasePriceEurM2": {
"type": "number",
"minimum": 0,
"description": "Purchase price in EUR/m2, inclusive. A comune with no price is left out, never treated as cheap."
},
"allCareScoresAtLeast60": {
"anyOf": [
{
"type": "boolean"
},
{
"enum": [
"true",
"false"
],
"type": "string"
}
],
"description": "[UI key nsg60] true: the NSG prevention, community-care and hospital-care scores must all be at least 60. Region grain (autonomous-province grain for Bolzano and Trento). A comune missing any of the three is left out and counted."
},
"maxAirportDriveMinutes": {
"type": "number",
"description": "[UI key adrive] Minutes by road from the comune's main town to the nearest of the airports where ENAC recorded at least 4,000 passengers in 2025 (it leaves out Taranto-Grottaglie and Brescia-Montichiari, which carried almost none), at most this; one of 60, 90, 120, 180. Town grain, free-flow, approximate; says nothing about flights. No figure: left out and counted."
},
"maxPopulationChangePct": {
"type": "number",
"description": "Population change 2019 to 2025, in percent, inclusive."
},
"minPopulationChangePct": {
"type": "number",
"description": "Population change 2019 to 2025, in percent, inclusive. A negative value means decline."
},
"maxHospitalDriveMinutes": {
"type": "number",
"description": "[UI key hdrive] Minutes by road from the comune's main town to the nearest hospital with inpatient beds (Ministero della Salute 2023 list, OpenStreetMap roads) at most this; one of 15, 30, 45, 60. Town grain, free-flow, approximate. Not necessarily a hospital with an emergency department. A comune with no figure (for example a ferry-only island) is left out and counted."
}
}
}