Skip to main content

Validate, parse, format, mask, and generate Icelandic national identification numbers (kennitala / kennitölur)

Project description

ice-ken

Release CI

A Python library for validating, parsing, formatting, masking, and generating Icelandic national identification numbers (kennitala / kennitölur). Built for developers working with Icelandic identity systems, government registries, KYC/AML flows, or any application that handles Icelandic personal and company IDs.

Kennitala (plural: kennitölur) is Iceland's national ID system, issued by Registers Iceland (Þjóðskrá Íslands). It serves a similar role to SSN (US), personnummer (Nordics), or national ID numbers in other countries. Every individual and legal entity in Iceland has one.

Why ice-ken?

  • Zero dependencies — pure Python, nothing to install beyond the package itself.
  • Python 3.9–3.13 — tested across all supported versions.
  • 2026-ready — handles the Feb 2026 policy change where Registers Iceland may issue kennitalas without valid Modulus 11 checksums. Dual validation modes (strict and relaxed) let you choose.
  • Individuals and companies — validates and distinguishes both personal IDs (kennitala einstaklinga) and company/legal entity IDs (kennitala lögaðila) using the day+40 rule.
  • Generation for testing — create realistic, structurally valid kennitalas for tests, fixtures, and seed data without using real IDs.
  • Safe masking — redact kennitalas for logs, UIs, and reports while preserving the format.
  • Typed — ships with py.typed and full type annotations for mypy/pyright.

Overview

Kennitala is a 10-digit identifier typically written as DDMMYY-NNNX:

  • Digits 1–6: day (DD), month (MM), year (YY, two digits)
  • Digits 7–8: sequence number
  • Digit 9: Modulus 11 check digit (policy exception from Feb 2026)
  • Digit 10: century indicator (8=1800s, 9=1900s, 0=2000s)

Companies and legal entities encode the day as DD = actual_day + 40 (range 41–71). When resolving a date, subtract 40 from the day for company IDs.

See the full background and rules in docs/about-kennitala.md.

Install

python3 -m pip install ice-ken

For local development:

python3 -m pip install -e .

Quick Start

from ice_ken import normalize, format_kennitala, is_valid, parse, mask, is_company, is_personal

raw = "120174-3399"
digits = normalize(raw)              # "1201743399"
print(format_kennitala(digits))      # "120174-3399"

print(is_valid(raw))                 # relaxed (default since 2.0)
print(is_valid(raw, enforce_checksum=True))   # strict (checksum enforced)

info = parse(raw)                    # raises on invalid (relaxed by default)
print(info.birth_date, info.entity_type)

print(mask(raw))                     # "******-3399"
print(is_company(raw), is_personal(raw))

API Overview

  • normalize(value): return digits-only string.
  • format_kennitala(value): format as DDMMYY-NNNX.
  • is_valid(value, enforce_checksum=False): structural + date validation; optionally enforce checksum.
  • parse(value, enforce_checksum=False): return ParsedKennitala with digits, formatted, birth_date, entity_type, century_indicator.
  • mask(value, visible_tail=4): masked display keeping last digits.
  • is_company(value) / is_personal(value): entity detection.
  • is_dataset_id(value): test-only helper for synthetic dataset marker (14/15 in digits 7–8).
  • generate_personal(birth_date=None, ...): generate a personal kennitala, optionally for a specific date.
  • generate_company(reg_date=None, ...): generate a company kennitala, optionally for a specific date.
  • generate_kennitala(kind, birth_date=None, ...): unified generator for either type.
  • generate_batch(count, kind, ...): generate multiple kennitölur at once.
  • get_birth_date(value, enforce_checksum=False): resolve the birth/registration date.
  • Additional aliases: generate_personal_for_date, generate_company_for_date, random_personal, random_company.

Validation Modes

  • Relaxed (default): validates structure, date, and century indicator. Skips checksum.
  • Strict: additionally enforces Modulus 11 checksum (9th digit).
from ice_ken import is_valid

print(is_valid("120160-3389"))                          # True (relaxed, default)
print(is_valid("120160-3379"))                          # True (relaxed, bad checksum ok)
print(is_valid("120160-3379", enforce_checksum=True))   # False (strict, fails checksum)

Since February 18, 2026, Registers Iceland issues kennitalas without a computed checksum. The default relaxed mode accepts these IDs. Use enforce_checksum=True only when you need to verify the checksum for pre-2026 IDs. Details in docs/about-kennitala.md.

Companies vs Individuals

  • Personal IDs: DD in 01–31 (calendar day).
  • Company IDs: DD in 41–71 (day + 40).
from ice_ken import is_company, is_personal

print(is_personal("120160-3389"))   # True
print(is_company("520160-3379"))    # True (company: 52 → day 12)

Synthetic Dataset Marker

For test contexts, Registers Iceland’s synthetic dataset (Gervigögn) uses 14 or 15 in digits 7–8:

from ice_ken import is_dataset_id
print(is_dataset_id("120160-1489"))  # True

Do not rely on this marker in production logic.

Generation

Generate structurally valid kennitölur for testing, seeding databases, or any scenario where you need realistic IDs.

from datetime import date
from ice_ken import (
    generate_personal,
    generate_company,
    generate_kennitala,
    generate_batch,
)

# Random personal kennitala (checksum-valid, formatted)
kt = generate_personal()              # e.g. "120585-2389"

# Personal kennitala for a specific birth date
kt = generate_personal(birth_date=date(1990, 5, 20))  # encodes 20-05-90

# Normalized (digits only) output
kt = generate_personal(formatted=False)     # e.g. "1205852389"

# Random company kennitala
kt = generate_company()               # e.g. "520312-2190"

# Company kennitala for a specific registration date
kt = generate_company(reg_date=date(2015, 3, 12))

# Unified entry point
kt = generate_kennitala("personal", target_date=date(1985, 1, 1))
kt = generate_kennitala("company")

# Batch generation — 100 random personal IDs
batch = generate_batch(100)

# Batch of company IDs, all sharing a date
batch = generate_batch(50, "company", target_date=date(2020, 6, 1))

# Relaxed mode: structurally valid but checksum intentionally wrong
kt = generate_personal(enforce_checksum=False)

All generators accept enforce_checksum (default True) and formatted (default True).

Documentation

Development

Requirements: Python 3.9+

# Create and activate a virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate

# Install package and test tools
python3 -m pip install --upgrade pip
python3 -m pip install -e .
python3 -m pip install pytest

# Run tests
python3 -m pytest -q

# Optional: run the XML loader on sample data
python3 -m ice_ken.loaders data/Thjordska-Gervigogn-VartolulausarKennitolur.xml

CI & Release

Contributing

We welcome contributions—bug fixes, improvements, documentation, tests, and new helpers. If something can make working with kennitalas safer or clearer, please propose it.

Guidelines:

  • Keep changes focused and well-tested.
  • Use Conventional Commits for messages.
  • Add/extend tests for new behavior.
  • Update docs when APIs or behavior change.
  • Open a PR to main from a feature branch; CI must be green.

For agent and repository workflow details, see AGENTS.md.

License

MIT License. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ice_ken-2.0.2.tar.gz (23.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ice_ken-2.0.2-py3-none-any.whl (14.0 kB view details)

Uploaded Python 3

File details

Details for the file ice_ken-2.0.2.tar.gz.

File metadata

  • Download URL: ice_ken-2.0.2.tar.gz
  • Upload date:
  • Size: 23.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ice_ken-2.0.2.tar.gz
Algorithm Hash digest
SHA256 a8152504e58d0485b49cd4b7dafde0a6700b4d105d2854211f286bf1857bd1bb
MD5 b22ea23d2511c8875ecd0e295c040a07
BLAKE2b-256 f2446e6d163dafdde1a2184da930bba61466dd1f3dba1a162510c63f698484c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for ice_ken-2.0.2.tar.gz:

Publisher: release.yml on vignirvignir/ice-ken

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ice_ken-2.0.2-py3-none-any.whl.

File metadata

  • Download URL: ice_ken-2.0.2-py3-none-any.whl
  • Upload date:
  • Size: 14.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ice_ken-2.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d1716f7db30e00645fc592347e66bb2624a983a81bc39c2e47da8c9ea3ca830e
MD5 9d64f083feaa8ab23c803f395f8115a9
BLAKE2b-256 29fe98a5beb752ee87cb7582dad7cc74877d6ab80a0adf7b966d532cced80e51

See more details on using hashes here.

Provenance

The following attestation bundles were made for ice_ken-2.0.2-py3-none-any.whl:

Publisher: release.yml on vignirvignir/ice-ken

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page