Skip to main content

egypt-nid

PyPI version CI Coverage Typing Python 3.8+ License: MIT

egypt-nid is the definitive Python library for parsing, validating, and extracting structured data from Egyptian National ID numbers (الرقم القومي).


Features

  • ✅ Full 14-digit structural validation (century, birth date, governorate, Luhn checksum)
  • 🔒 Strict mode (raises typed exceptions) and lenient mode (collects warnings)
  • 📊 Bulk parsing, filtering, and aggregate statistics
  • 🌍 Governorate names in English and Arabic with locale support
  • 🎭 Masking for safe display
  • 🖥️ CLI tool (egypt-nid)
  • 🔌 Framework-ready (Django, FastAPI, Pandas — no hard dependencies)
  • 📦 py.typed – PEP 561 compliant, fully typed
  • ⚡ LRU-cached repeated parses

Installation

pip install egypt-nid

Quick Start

from egypt_nid import parse

nid = parse("30105150123456")

print(nid.birth_date)          # datetime.date(2001, 5, 15)
print(nid.age)                 # 23 (depends on current date)
print(nid.gender)              # 'male'
print(nid.governorate_name)    # 'Cairo'
print(nid.governorate_name_ar) # 'القاهرة'
print(nid.is_adult())          # True
print(nid.born_outside_egypt)  # False
print(nid.masked())            # '3** ** ** **** 3456'

Error Handling

Strict mode (default)

from egypt_nid import parse
from egypt_nid.exceptions import (
    LengthError, NonNumericError, CenturyError,
    BirthDateError, GovernorateError, ChecksumError,
)

try:
    nid = parse("bad_input")
except LengthError as e:
    print(f"Wrong length: {e}")
except ChecksumError as e:
    print(f"Typo detected: {e}")
except EgyptNIDError as e:
    print(f"Validation failed: {e}")

Lenient mode

from egypt_nid import parse_lenient

nid, result = parse_lenient("30105150123457")  # bad checksum
if not result.valid:
    for field, warning in result.warnings.items():
        print(f"  [{field}] {warning}")
# nid is still returned if only non-critical checks fail

Serialisation

nid = parse("30105150123456")

# Dictionary
d = nid.to_dict()
d = nid.to_dict(locale="ar", include_birth_date=False)

# JSON
print(nid.to_json())
print(nid.to_json(indent=None))  # compact

Bulk Operations

from egypt_nid import parse_bulk, compute_stats
from egypt_nid import filter_by_gender, filter_by_age_range, filter_adults

ids = ["30105150123456", "29008200201241", ...]

parsed = parse_bulk(ids, skip_errors=True)

males   = filter_by_gender(parsed, "male")
adults  = filter_adults(parsed)
seniors = filter_by_age_range(parsed, 60, 100)

stats = compute_stats(parsed)
print(stats.average_age)             # 34.7
print(stats.gender_distribution)     # {'male': 120, 'female': 80}
print(stats.governorate_distribution) # {'01': 50, '21': 30, ...}

CLI Usage

# Pretty output
egypt-nid 30105150123456

# JSON output
egypt-nid --json 30105150123456

# Lenient mode
egypt-nid --lenient 30105150123457

# Bulk processing from file (one NID per line)
egypt-nid --bulk ids.txt
egypt-nid --bulk ids.txt --json

# Version
egypt-nid --version

Framework Integration

Django

from django.core.exceptions import ValidationError
from egypt_nid import parse
from egypt_nid.exceptions import EgyptNIDError

def validate_egyptian_nid(value):
    try:
        parse(value)
    except EgyptNIDError as exc:
        raise ValidationError(str(exc)) from exc

FastAPI

from fastapi import HTTPException
from egypt_nid import parse, NationalID
from egypt_nid.exceptions import EgyptNIDError

def get_nid(nid_str: str) -> NationalID:
    try:
        return parse(nid_str)
    except EgyptNIDError as exc:
        raise HTTPException(status_code=422, detail=str(exc))

Pandas

import pandas as pd
from egypt_nid import parse
from egypt_nid.exceptions import EgyptNIDError

def safe_parse(val):
    try:
        return parse(val).gender
    except EgyptNIDError:
        return None

df["gender"] = df["nid"].apply(safe_parse)

Custom Governorates

from egypt_nid import parse

custom = {
    "01": ("New Cairo", "القاهرة الجديدة"),
    "88": ("Foreign", "خارج الجمهورية"),
}

nid = parse("30105150123456", custom_governorates=custom)

Governorate Versioning

# Default is "v1"; future versions will be added without breaking changes
nid = parse("30105150123456", version="v1")

Performance Notes

  • Repeated parses of the same NID string are served from an LRU cache (4096 entries).
  • parse_bulk processes a list in a single pass.
  • All derived attributes (age, gender) are computed lazily.
  • For datasets > 100 k rows, consider running in a thread pool executor.

Contributing

Please read CONTRIBUTING.md and open a pull request. All contributions require:

  1. Tests (pytest + Hypothesis)
  2. Type annotations
  3. Google-style docstrings
  4. Passing ruff, black, and mypy --strict

License

MIT

Metadata

Release files for egypt-nid 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for egypt-nid 0.1.1
File Size Uploaded
egypt_nid-0.1.1.tar.gz 26.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for egypt-nid 0.1.1
File Interpreter ABI Platform
egypt_nid-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 49.4 kB

Release files / egypt_nid-0.1.1.tar.gz

Download URL egypt_nid-0.1.1.tar.gz
Size 26.5 kB
Tags Source
SHA-256 checksum
How to use checksums
e19f7d0897c6a0bee93e3552bd0fdb0024d4557867d02fc6d03af21fad337632
BLAKE2b-256 checksum
How to use checksums
d20787306ad3126cb12bdb6384541813a789e185ddbd22e3d80ee6090dc86d99
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.11

Release files / egypt_nid-0.1.1-py3-none-any.whl

Download URL egypt_nid-0.1.1-py3-none-any.whl
Size 22.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d63515e6198e4d79f475e6203e04544bf37cad1997e999ec31e98cfc349231f5
BLAKE2b-256 checksum
How to use checksums
6da53dfe0ab6eff98b4c3c1be003f998bfac26864d9ace92e8fb539dc922d19b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.11

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page