IndiaID 🇮🇳
IndiaID is a high-performance, zero-dependency Python library for validating, parsing, and masking Indian government IDs, identity numbers, and document codes.
Designed specifically for FinTechs, KYC onboarding pipelines, HRMS, and modern web applications.
✨ Features
- ⚡ Zero Runtime Dependencies: Built entirely on standard Python 3.9+.
- 🧮 Algorithmic Validation: Verhoeff checksum for Aadhaar, Luhn mod-36 for GSTIN.
- 🎭 Privacy & Masking: UIDAI-compliant Aadhaar masking (
XXXXXXXX1234) and PAN/Phone masking. - 🧩 Rich Metadata Extraction: Parse state, entity type (PAN), issue year (DL), and postal circles.
- 🔌 Framework Integrations: First-class optional support for Pydantic v2 and Django / DRF.
- 🛡️ Strictly Typed: PEP 561 compliant (
py.typed) with full static type checking (mypy --strict). - 🚀 Automated CI/CD: Seamless GitHub Actions workflow for testing and auto-deploying to PyPI on push to
main.
📦 Installation
pip install indiaid
Optional Integrations
# With Pydantic v2 support
pip install "indiaid[pydantic]"
# With Django / DRF support
pip install "indiaid[django]"
# With all integrations
pip install "indiaid[all]"
🚀 Quickstart
1. Direct Document Imports (Recommended)
Import validators directly for maximum speed and IDE autocompletion:
from indiaid import pan, aadhaar, gstin, vehicle
# Simple boolean check
pan.is_valid("ABCPE1234F") # True
aadhaar.is_valid("3675 9834 6211") # True (Verhoeff checksum validated)
# Callable shortcut syntax
if pan("ABCPE1234F"):
print("Valid PAN format!")
# Mask for privacy / compliance
pan.mask("ABCPE1234F") # "ABXXXXXX4F"
aadhaar.mask("3675 9834 6211") # "XXXXXXXX6211"
2. Universal Registry
If you are accepting dynamic document types (e.g., from an API parameter):
import indiaid
# Dynamic validation by document key or alias
is_valid = indiaid.is_valid("pan", "ABCPE1234F")
masked = indiaid.mask("aadhaar", "3675 9834 6211")
3. Rich Validation & Metadata Extraction
Validation returns a ValidationResult dataclass with cleaned values, validation state, and parsed metadata:
from indiaid import pan, gstin, vehicle, pincode
# PAN entity & surname breakdown
res = pan.validate("ABCPE1234F")
if res.is_valid:
print(res.cleaned_value) # "ABCPE1234F"
print(res.get("entity_type")) # "Individual / Person"
print(res.get("surname_initial")) # "E"
# GSTIN state and embedded PAN
res = gstin.validate("27AAPFU0939F1ZV")
if res.is_valid:
print(res.get("state_name")) # "Maharashtra"
print(res.get("state_code")) # "27"
print(res.get("pan")) # "AAPFU0939F"
# Vehicle RC lookup (standard & Bharat 'BH' series)
res = vehicle.validate("MH01A2925")
print(res.get("state_name")) # "Maharashtra"
# Direct state query helper
print(vehicle.state("MH01A2925")) # "Maharashtra"
print(vehicle.state("22BH1234AA")) # "Bharat Series (All India)"
# Pincode zone inspection
res = pincode.validate("400001")
print(res.get("zone_info")) # "Western Zone (Maharashtra, Goa, Madhya Pradesh, Chhattisgarh)"
4. Exception-Based Workflow (raise_if_invalid)
If your application prefers raising exceptions over checking boolean return values:
from indiaid import vehicle, ValidationError
try:
res = vehicle.validate("ZZ01A2925").raise_if_invalid()
except ValidationError as exc:
print(f"Validation failed: {exc}")
# Output: Validation failed: Invalid state code 'ZZ' in vehicle registration number.
📑 Supported Documents
For in-depth format definitions and regex rules, see docs/supported_documents.md.
| Document | Direct Import | Dynamic Keys / Aliases | Validation Rules | Masking |
|---|---|---|---|---|
| Aadhaar | aadhaar |
"aadhaar", "uidai" |
Verhoeff $D_5$ checksum, non-0/1 start | ✅ XXXXXXXX1234 |
| PAN Card | pan |
"pan", "pan_card" |
10-char format, entity code, checksum | ✅ ABXXXXXX4F |
| GSTIN | gstin |
"gstin", "gst" |
State code, embedded PAN, Luhn mod-36 | ✅ 27XXXXXXXXXX1ZV |
| Passport | passport |
"passport" |
8-character Indian passport format | ✅ X******1 |
| Driving Licence | driving_licence |
"driving_licence", "dl" |
State RTO code, year boundary (1900–curr) | ❌ |
| Voter ID (EPIC) | voter_id |
"voter_id", "epic" |
Standard 3-alpha/7-digit & legacy formats | ✅ XXXXXXX123 |
| Vehicle RC | vehicle |
"vehicle", "rc" |
State RTO series + Bharat Series (BH) |
❌ |
| Bank IFSC | ifsc |
"ifsc" |
RBI 11-char alphanumeric format | ❌ |
| Mobile Phone | phone |
"phone", "mobile" |
Indian 10-digit (+91/0 prefix handled) | ✅ XXXXXX1234 |
| Pincode | pincode |
"pincode", "pin" |
6-digit postal circle validation | ❌ |
🛠️ Framework Integrations
Pydantic v2
from pydantic import BaseModel
from indiaid.integrations.pydantic import AadhaarStr, PanStr, GstinStr
class OnboardingRequest(BaseModel):
name: str
pan: PanStr
aadhaar: AadhaarStr
gstin: GstinStr
Django Models & DRF Serializers
from django.db import models
from indiaid.integrations.django import validate_pan, validate_aadhaar
class Customer(models.Model):
name = models.CharField(max_length=100)
pan = models.CharField(max_length=10, validators=[validate_pan])
aadhaar = models.CharField(max_length=12, validators=[validate_aadhaar])
🧪 Interactive Demo & Testing
Try the interactive demonstration script with complete examples:
python demo.py
Run test suite:
pytest
🚀 Auto-Deploy to PyPI (CI/CD)
This repository includes automated GitHub Actions workflows:
-
Continuous Testing (
.github/workflows/tests.yml): Runs tests, linting (ruff), and type checking (mypy) against Python 3.9, 3.10, 3.11, 3.12, and 3.13 on every push and pull request. -
Auto-Deploy on Push to
main(.github/workflows/publish.yml): Whenever a commit is pushed to themainbranch (or a release is published):- GitHub Actions runs the entire test suite.
- Builds source distribution (
sdist) and binary wheel (wheel). - Verifies package distribution integrity using
twine. - Automatically publishes to PyPI using Trusted Publishing (OIDC) or PyPI API Token.
skip-existing: trueensures that commits without a version bump won't break your pipeline.
Configuring PyPI Deployment
Option A: PyPI Trusted Publishing (Recommended - Zero Secrets)
- Go to pypi.org/manage/account/publishing/.
- Add a new publisher:
- PyPI Project Name:
indiaid - Owner:
Shailesh-2128 - Repository name:
indiaid_library - Workflow name:
publish.yml - Environment name:
pypi
- PyPI Project Name:
- Push to
main! GitHub Actions will authenticate directly with PyPI via OpenID Connect (OIDC).
Option B: PyPI API Token Secret
- Create an API token on pypi.org.
- In your GitHub repository, navigate to Settings > Secrets and variables > Actions.
- Add a secret named
PYPI_API_TOKENwith your token value.
👨💻 Author & Credits
Created and maintained by Shailesh Jiwana.
Contributions and suggestions are always welcome! Feel free to open an issue or pull request on GitHub.
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License
Copyright (c) 2026 Shailesh Jiwana
Metadata
Release files for indiaid 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| indiaid-0.1.1.tar.gz | 27.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| indiaid-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 52.8 kB
Release files / indiaid-0.1.1.tar.gz
| Download URL | indiaid-0.1.1.tar.gz |
|---|---|
| Size | 27.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
96b5075651568192d3ef4ea643893a72a4ae34362ef6ca00102431962ef0c6e2
|
|
BLAKE2b-256 checksum How to use checksums |
556346a5d4dfbc1a19a5d6148fbfb5aa158f6e06a2b7b5934c4adabc4ebb288c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / indiaid-0.1.1-py3-none-any.whl
| Download URL | indiaid-0.1.1-py3-none-any.whl |
|---|---|
| Size | 25.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b79777a34ffa3e9d30dfb034499552ce24feb3d526f065afb4325fa84d83e560
|
|
BLAKE2b-256 checksum How to use checksums |
5353c6b01598234e791556345dbb26ceac49b098b4688129c8a4596d5f11b997
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for indiaid 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.