A comprehensive Python library for validating and generating Italian fiscal identification documents:
- Codice Fiscale (CF): Italian personal tax identification code
- Partita IVA (P.IVA): Italian VAT registration number
✅ Codice Fiscale Validation
- Format validation with omocodia handling
- Check digit verification
- Birthdate, age, and gender extraction
- Birth place lookup (municipality name and province)
- Minimum age verification (18+ by default)
✅ Codice Fiscale Generation
- Generate CF from personal data (name, surname, birthdate, gender, birth place)
- Automatic check digit calculation
- Municipality code lookup by name
✅ Partita IVA Validation
- Format and check digit verification (Italian Luhn algorithm)
- Temporary VAT number detection (starts with 99)
- Provincial office code extraction
✅ Municipality Database
- ~200 major Italian municipalities with cadastral codes
- Foreign country codes
- Search by name or code
✅ Command-Line Interface
- Validate CF and P.IVA from terminal
- Generate CF from command line
- Search municipality codes
✅ Developer Friendly
- Simple, intuitive API
- Type hints for IDE support
- Zero external dependencies
- Python 3.9+
pip install italian-tax-validatorsfrom italian_tax_validators import validate_codice_fiscale
# Basic validation
result = validate_codice_fiscale("RSSMRA85M01H501Q")
print(result.is_valid) # True
print(result.birthdate) # 1985-08-01
print(result.age) # 40
print(result.gender) # "M"
print(result.birth_place_name) # "ROMA"
print(result.birth_place_province) # "RM"
# With age verification
result = validate_codice_fiscale("RSSMRA85M01H501Q", check_adult=True)
print(result.is_valid) # True (person is 18+)
# With custom minimum age
result = validate_codice_fiscale("RSSMRA85M01H501Q", check_adult=True, minimum_age=21)from datetime import date
from italian_tax_validators import generate_codice_fiscale
result = generate_codice_fiscale(
surname="Rossi",
name="Mario",
birthdate=date(1985, 8, 1),
gender="M",
birth_place_code="H501" # Rome
)
print(result.codice_fiscale) # "RSSMRA85M01H501Q"from italian_tax_validators import validate_partita_iva
result = validate_partita_iva("12345678903")
print(result.is_valid) # True
print(result.province_code) # "890"
print(result.is_temporary) # False
# Flexible input handling
result = validate_partita_iva("IT 123 456 78903") # Works with spaces and prefixfrom italian_tax_validators import (
get_municipality_info,
get_cadastral_code,
search_municipality
)
# Get info from cadastral code
info = get_municipality_info("H501")
print(info) # ("ROMA", "RM")
# Get cadastral code from name
code = get_cadastral_code("MILANO")
print(code) # "F205"
# Search by partial name
results = search_municipality("ROMA")
# [("H501", "ROMA", "RM"), ("Z124", "ROMANIA", "EE")]The package includes a CLI tool for quick validations:
# Validate Codice Fiscale
italian-tax-validators validate-cf RSSMRA85M01H501Q
# Validate with age check
italian-tax-validators validate-cf RSSMRA85M01H501Q --check-adult --minimum-age 21
# Validate Partita IVA
italian-tax-validators validate-piva 12345678903
# Generate Codice Fiscale
italian-tax-validators generate-cf \
--surname Rossi \
--name Mario \
--birthdate 1985-08-01 \
--gender M \
--birth-place-code H501
# Generate using municipality name
italian-tax-validators generate-cf \
--surname Rossi \
--name Mario \
--birthdate 1985-08-01 \
--gender M \
--birth-place ROMA
# Search municipality codes
italian-tax-validators search-municipality MILANSee API.md for complete API documentation.
| Function | Description |
|---|---|
validate_codice_fiscale(value, check_adult, minimum_age) |
Validate a Codice Fiscale |
validate_partita_iva(value) |
Validate a Partita IVA |
generate_codice_fiscale(surname, name, birthdate, gender, birth_place_code) |
Generate a Codice Fiscale |
get_municipality_info(code) |
Get municipality name and province from cadastral code |
get_cadastral_code(name) |
Get cadastral code from municipality name |
search_municipality(query) |
Search municipalities by partial name |
is_foreign_country(code) |
Check if cadastral code is a foreign country |
The Italian Codice Fiscale is a 16-character alphanumeric code:
RSSMRA85M01H501Q
├─ RSS → Surname (first 3 consonants)
├─ MRA → Name (first 3 consonants, or 1st+3rd+4th if 4+ consonants)
├─ 85 → Birth year (1985)
├─ M → Birth month (M = August)
├─ 01 → Birth day (01), +40 for females (e.g., 41 = day 1, female)
├─ H501 → Birth place cadastral code (H501 = Rome)
└─ Q → Check digit
| Code | Month | Code | Month |
|---|---|---|---|
| A | January | L | July |
| B | February | M | August |
| C | March | P | September |
| D | April | R | October |
| E | May | S | November |
| H | June | T | December |
When multiple people share the same CF, digits can be replaced with letters:
- L=0, M=1, N=2, P=3, Q=4, R=5, S=6, T=7, U=8, V=9
The library automatically handles omocodia substitutions during validation.
The Italian Partita IVA is an 11-digit number:
12345678903
├─ 1234567 → Company registration number (matricola)
├─ 890 → Provincial office code
└─ 3 → Check digit (Luhn algorithm variant)
Note: VAT numbers starting with 99 are temporary numbers.
# Run tests with pytest
pytest tests/
# Run with coverage
pytest tests/ --cov=italian_tax_validators
# Run with unittest
python -m unittest discover tests/from django.core.exceptions import ValidationError
from italian_tax_validators import validate_codice_fiscale
def validate_cf(value):
result = validate_codice_fiscale(value, check_adult=True)
if not result.is_valid:
raise ValidationError(f"Invalid CF: {result.error_code}")
class Person(models.Model):
codice_fiscale = models.CharField(max_length=16, validators=[validate_cf])from pydantic import BaseModel, field_validator
from italian_tax_validators import validate_codice_fiscale
class PersonForm(BaseModel):
codice_fiscale: str
@field_validator('codice_fiscale')
@classmethod
def validate_cf(cls, v):
result = validate_codice_fiscale(v, check_adult=True)
if not result.is_valid:
raise ValueError(f"Invalid Codice Fiscale: {result.error_code}")
return result.formatted_valuefrom fastapi import FastAPI, HTTPException
from italian_tax_validators import validate_codice_fiscale, validate_partita_iva
app = FastAPI()
@app.get("/validate/cf/{value}")
def validate_cf(value: str, check_adult: bool = False):
result = validate_codice_fiscale(value, check_adult=check_adult)
if not result.is_valid:
raise HTTPException(400, detail=result.error_code)
return {
"codice_fiscale": result.formatted_value,
"birthdate": str(result.birthdate),
"age": result.age,
"gender": result.gender,
"birth_place": result.birth_place_name,
}MIT License - See LICENSE.md for details.
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
- ✨ Added Codice Fiscale generation
- ✨ Added gender extraction from CF
- ✨ Added birth place lookup (municipality database)
- ✨ Added temporary VAT number detection
- ✨ Added provincial office code extraction from P.IVA
- ✨ Added command-line interface (CLI)
- 📚 Added comprehensive API documentation
- Initial release with CF and P.IVA validation
- Agenzia delle Entrate - Official Italian Tax Agency
- Codice Fiscale Format - Wikipedia
- Partita IVA Format - Wikipedia