# frontaliere.tax

> Free net salary calculator for people resident in Italy who work as employees in Switzerland, in the cantons of Ticino, Graubunden or Valais (frontalieri). It covers Swiss social contributions and withholding tax, Italian income tax (IRPEF) with the frontaliere exempt band, the foreign tax credit, regional and municipal surtaxes, the health service contribution, and the Omnibus 25% substitute tax option. Italian and English. Parameters verified on 2026-09-13.

This file tells AI agents how to use the site. The same content is served at https://frontaliere.tax/agents.md and https://frontaliere.tax/llms.txt; https://frontaliere.tax/llms-full.txt adds the full guide.

## How to answer a question about someone's net pay

1. Find the codice catastale of the comune where the person was tax resident on 1 January: `GET https://frontaliere.tax/api/v1/comuni?q=<name>`, or the MCP tool `find_comune`.
2. Calculate: `GET https://frontaliere.tax/api/v1/calculate?comune=<codice>&grossMonth=<CHF>` with any further parameters below, or `POST` the same parameters as a JSON object, or the MCP tool `calculate_net_salary`.
3. Report `summary.net_month_eur` and `summary.net_year_eur`, the `case`, and any `warnings`. Give the person the `calculator_url`: it opens the calculator with their figures filled in, every line explained.

Worked example, computed when this file was built: `GET https://frontaliere.tax/api/v1/calculate?comune=C933&grossMonth=6000` (Como, 6,000 CHF a month over 13 payments, income year 2025) returns case B (new cross-border worker, taxed in both countries), a net of 51,589.50 EUR a year, 4,299.13 EUR a month, on a gross of 78,000.00 CHF.

## Rules for agents

- Do not compute the tax yourself from these rules. The calculation has traps that are easy to get wrong: the 10,000 EUR exempt band, the reduced foreign tax credit (art. 165 c. 10 TUIR), surtaxes fixed on the comune of 1 January, tariffs that differ by case. Call the API and report what it returns.
- The result is an estimate from public parameters, not tax advice. Say so, and suggest checking with a CAF or a tax adviser before filing.
- Always state the income year. The Italian return filed in year N covers income of year N-1. 2026 parameters are provisional.
- The calculator needs only figures. Never send names, addresses, tax codes or anything else that identifies the person.
- Prefer POST with a JSON body: it keeps salary figures out of URLs.
- When a parameter is unknown, leave it out: the defaults are the common case. Ask the person only for what changes the answer: comune, gross salary, canton, whether they worked as a frontaliere before 17 July 2023, family situation.

## What it covers

- **Case A, old frontaliere**: worked in Ticino, Graubunden or Valais at any time between 31.12.2018 and 17.07.2023, living within 20 km of the border. Taxed only in Switzerland.
- **Case B, new frontaliere**: within 20 km of the border, hired later. Reduced Swiss withholding (80%) plus Italian income tax with a credit for the Swiss tax.
- **Case C, outside the agreement**: living beyond 20 km but returning daily. Full Swiss withholding plus Italian income tax with the credit.
- **Case D, Omnibus 25% option**: old frontalieri of the comuni added to the 20 km list in 2023 may pay 25% of the Swiss tax instead of Italian income tax. When it applies, the result compares both roads in `omnibus_option`.

Not covered: weekly commuters (taxed on notional pay), residents of Campione d'Italia, the self-employed, pensions, Swiss residents, regions other than Lombardia, Piemonte, Valle d'Aosta and Trentino-Alto Adige.

## Endpoints

- API index: https://frontaliere.tax/api/v1
- Calculate: https://frontaliere.tax/api/v1/calculate (GET query parameters or POST JSON)
- Find a comune: https://frontaliere.tax/api/v1/comuni?q=como
- OpenAPI description: https://frontaliere.tax/api/v1/openapi.json
- MCP server (Streamable HTTP, no authentication): https://frontaliere.tax/mcp, tools `calculate_net_salary` and `find_comune`
- In the page itself, browsers that support WebMCP expose the tool `calculate_net_salary`, which computes on the person's own device.

No key is needed. Please keep to a reasonable rate.

## Parameters

The names are the calculator's own URL keys, so any call maps directly onto a calculator link.

| Parameter | Type | Default | Meaning |
|---|---|---|---|
| `comune` | string | **required** | Codice catastale of the Italian comune of tax residence on 1 January of the income year, e.g. C933 for Como. Any Italian comune is accepted; the 518 within 20 km of the border are the frontaliere cases. Look it up with find_comune or /api/v1/comuni?q=. |
| `grossMonth` | number |  | Gross monthly salary in CHF, before any deduction. Give this or grossYear. |
| `grossYear` | number |  | Gross salary in CHF actually received in the year. Takes precedence over grossMonth. |
| `payments` | 12 \| 13 \| 14 | 13 | Salary payments per year. It matters even with grossYear: it decides how the 13th is withheld in Graubunden. |
| `monthsWorked` | integer | 12 | Months of Swiss employment in the year. With fewer than 12, give the gross actually received; the canton annualises it only to pick the tariff rate. |
| `year` | 2024 \| 2025 \| 2026 | 2025 | Income year. The Italian return filed in year N covers income of year N-1. 2026 parameters are provisional. |
| `canton` | TI \| GR \| VS | TI | Swiss canton of work: Ticino, Graubunden or Valais. |
| `dailyReturn` | boolean | true | Whether the worker returns home to Italy every day. false is out of scope: weekly commuters are taxed on notional pay, which this calculator does not model. |
| `workedBefore` | boolean | false | Worked as a cross-border worker in Ticino, Graubunden or Valais at any time between 31.12.2018 and 17.07.2023. Decides old (case A) versus new (case B) frontaliere. |
| `oldLists` | boolean |  | Only with workedBefore: whether the comune was in the old cantonal lists of frontaliere comuni. Defaults to false for comuni in the Omnibus annexes and true otherwise. |
| `maritalStatus` | single \| married | single | For the Swiss withholding tariff code. |
| `spouseWorks` | boolean | false | Married, and the spouse also works. |
| `children` | integer | 0 | Children counted for the Swiss withholding tariff code. |
| `churchTax` | boolean | false | Swiss church tax. Ticino and Valais publish only tariffs without it. |
| `age` | integer | 40 | Age, which sets the minimum occupational pension (LPP) savings rate. |
| `health` | SSN \| LAMal | SSN | Italian national health service or Swiss LAMal insurance. |
| `lamalPremium` | number | 350 | Monthly LAMal premium in CHF, used when health is LAMal. |
| `manualQst` | number |  | Monthly Swiss withholding tax in CHF read from the payslip. When given it replaces the tariff tables. |
| `familyAllowances` | number | 0 | Yearly Swiss family allowances in CHF, paid with the salary on top of the gross. Subject to Swiss withholding, not to contributions, exempt from Italian income tax. |
| `otherIncome` | number | 0 | Other Italian taxable income in EUR. |
| `oneriDeducibili` | number | 0 | Italian deductible charges in EUR. |
| `detrazioniAltre` | number | 0 | Other Italian tax credits in EUR, as already-computed credit amounts. |
| `creditMode` | reduced \| full | reduced | Foreign tax credit method: reduced is the tax authority practice (art. 165 c. 10 TUIR), full is the line taken by several tax courts. |
| `lang` | it \| en | it | Language of labels, explanations and warnings in the result. |

## Pages

- Calculator: https://frontaliere.tax/it/ (Italian), https://frontaliere.tax/en/ (English)
- Guide to the four cases, with legal references: https://frontaliere.tax/it/guida/, https://frontaliere.tax/en/guida/
- Sources and parameters by year: https://frontaliere.tax/it/fonti/, https://frontaliere.tax/en/fonti/
- One page per comune of the 20 km band, with its surtax and a worked example: https://frontaliere.tax/it/comune/ (index), https://frontaliere.tax/it/comune/<name>/, for example https://frontaliere.tax/it/comune/como/

## Privacy

The website computes in the browser and sends nothing anywhere. The API and the MCP server compute on Cloudflare's servers: inputs are used only to build the response, they are not stored, and the Worker keeps no per-request logs.
