Skip to main content
The RUT (Rol Único Tributario) is the tax identifier for individuals and companies in Chile. If you’re building a registration form, a KYB flow, or processing Chilean company data, you’ll need to validate it correctly. This guide covers:
  1. Validating the RUT format and check digit
  2. Normalizing different input formats
  3. Enriching company data using the EnrichLATAM API

RUT structure

A Chilean RUT has the form XXXXXXXX-D, where:
  • XXXXXXXX is the numeric part (6 to 8 digits)
  • D is the check digit (09 or K)
Valid examples: 76.354.771-K, 12345678-9, 76354771K

1. Validate the check digit

The check digit is calculated using the Modulo 11 algorithm:
def calculate_dv(number: str) -> str:
    """Calculates the check digit of a Chilean RUT."""
    digits = [int(d) for d in reversed(number)]
    series = [2, 3, 4, 5, 6, 7]
    total = sum(d * series[i % 6] for i, d in enumerate(digits))
    remainder = 11 - (total % 11)
    if remainder == 11:
        return "0"
    if remainder == 10:
        return "K"
    return str(remainder)


def validate_rut(rut: str) -> bool:
    """
    Validates the format and check digit of a Chilean RUT.
    Accepts formats: '76.354.771-K', '76354771-K', '76354771K'
    """
    import re
    rut_clean = re.sub(r"[.\-]", "", rut.strip().upper())

    if len(rut_clean) < 2:
        return False

    number, dv = rut_clean[:-1], rut_clean[-1]

    if not number.isdigit():
        return False

    return calculate_dv(number) == dv


# Examples
print(validate_rut("76.354.771-K"))  # True
print(validate_rut("76.354.771-0"))  # False
print(validate_rut("12345678-9"))    # True

2. Normalize the format

In practice, you’ll receive RUTs in different formats. This function normalizes them to XX.XXX.XXX-D:
import re

def normalize_rut(rut: str) -> str | None:
    """
    Normalizes a RUT to the standard format with dots and dash.
    Returns None if the RUT is invalid.
    """
    rut_clean = re.sub(r"[.\-\s]", "", rut.strip().upper())

    if len(rut_clean) < 2 or not rut_clean[:-1].isdigit():
        return None

    number, dv = rut_clean[:-1], rut_clean[-1]

    if not validate_rut(rut):
        return None

    formatted = "{:,}".format(int(number)).replace(",", ".")
    return f"{formatted}-{dv}"


print(normalize_rut("76354771K"))       # 76.354.771-K
print(normalize_rut("76.354.771-K"))   # 76.354.771-K
print(normalize_rut("  76354771-K "))  # 76.354.771-K
print(normalize_rut("invalid"))        # None

3. Reject personal RUTs

If your application should only process companies (e.g. for KYB or compliance), reject RUTs with a numeric part below 50,000,000. In Chile, companies have RUTs in the 60M–99M range while individuals are always below ~27M.
def is_company(rut: str) -> bool:
    """Returns True if the RUT belongs to a legal entity (company)."""
    rut_clean = re.sub(r"[.\-]", "", rut.strip().upper())
    number = rut_clean[:-1]
    return number.isdigit() and int(number) >= 50_000_000

4. Fetch company data with the API

Once the RUT is validated, you can get the legal name, economic activity, tax status, and more with a single call:
import requests

API_KEY = "your_api_key"

def enrich_company(rut: str) -> dict:
    """Fetches Chilean company data by RUT using EnrichLATAM."""
    response = requests.post(
        "https://api.enrichlatam.com/v1/enrich",
        headers={"X-API-Key": API_KEY},
        json={"identifier": rut, "country": "CL"},
    )
    response.raise_for_status()
    return response.json()


rut = "76.354.771-K"
if validate_rut(rut) and is_company(rut):
    data = enrich_company(rut)
    print(data["company_name"])   # Legal name
    print(data["status"])         # active / inactive
    print(data["activity"])       # Business activity
Example response:
{
  "country": "CL",
  "identifier": "76.354.771-K",
  "company_name": "EXAMPLE COMPANY SpA",
  "status": "active",
  "activity": "Information technology services",
  "region": "Región Metropolitana",
  "source": "sii",
  "data_as_of": "2026-03-01"
}

5. Full flow: validate + enrich

def process_rut(rut: str) -> dict:
    rut_norm = normalize_rut(rut)
    if not rut_norm:
        return {"error": "Invalid RUT"}
    if not is_company(rut_norm):
        return {"error": "Only company RUTs are accepted"}
    try:
        return enrich_company(rut_norm)
    except requests.HTTPError as e:
        return {"error": str(e)}

Data source

Chilean company data is sourced directly from the SII (Servicio de Impuestos Internos), Chile’s tax authority. EnrichLATAM uses the SII’s official public bulk file as the primary layer, with a maximum data latency of 30 days.

Resources