A comprehensive multi-language implementation of the Iranian National ID (کد ملی) validation algorithm.
یک پیادهسازی جامع چند زبانه از الگوریتم اعتبارسنجی کد ملی ایران.
npm install iranian-national-id-validatorimport { validateIranianNationalId } from 'iranian-national-id-validator';
validateIranianNationalId('0499370899'); // true
validateIranianNationalId('0000000000'); // false📦 View on NPM | 📖 Full Documentation
- Introduction
- Algorithm Explanation
- Language Implementations
- Installation & Usage
- Security & Edge Cases
- Examples
The Iranian National ID (کد ملی) is a unique 10-digit identifier assigned to Iranian citizens. This project provides validation implementations in 7 programming languages, all following the official validation algorithm.
کد ملی ایران یک شناسه یکتای 10 رقمی است که به شهروندان ایرانی اختصاص داده میشود. این پروژه پیادهسازی اعتبارسنجی را در 7 زبان برنامهنویسی ارائه میدهد که همگی از الگوریتم رسمی اعتبارسنجی پیروی میکنند.
- Length: Exactly 10 digits
- Format: Numeric only (0-9)
- Check Digit: The last digit is a control digit calculated from the first 9 digits
- Invalid Patterns: IDs with all identical digits (0000000000, 1111111111, etc.) are invalid
The validation algorithm consists of three stages:
- Verify the input is not null/undefined/empty
- Ensure the input is exactly 10 characters long
- Confirm all characters are numeric digits (0-9)
- Reject IDs where all 10 digits are identical
- Invalid patterns:
0000000000,1111111111,2222222222, ...,9999999999
The official Iranian National ID algorithm:
-
Multiply each of the first 9 digits by their position weight:
- Position 1: weight 10
- Position 2: weight 9
- Position 3: weight 8
- Position 4: weight 7
- Position 5: weight 6
- Position 6: weight 5
- Position 7: weight 4
- Position 8: weight 3
- Position 9: weight 2
-
Calculate the sum of all weighted values
-
Compute the remainder of the sum divided by 11:
remainder = sum % 11 -
Validate the check digit (10th digit):
- If
remainder < 2: check digit must equalremainder - If
remainder >= 2: check digit must equal11 - remainder
- If
sum = Σ(digit[i] × (10 - i)) for i = 0 to 8
remainder = sum mod 11
valid = {
checkDigit == remainder, if remainder < 2
checkDigit == (11 - remainder), if remainder >= 2
}
For National ID: 0499370899
Step 1: Calculate weighted sum
0×10 + 4×9 + 9×8 + 9×7 + 3×6 + 7×5 + 0×4 + 8×3 + 9×2
= 0 + 36 + 72 + 63 + 18 + 35 + 0 + 24 + 18
= 266
Step 2: Calculate remainder
266 % 11 = 2
Step 3: Validate check digit
remainder = 2 (which is >= 2)
Expected check digit = 11 - 2 = 9
Actual check digit = 9
✅ Valid!
✅ Identical validation logic
✅ Comprehensive inline comments (English & Persian)
✅ Usage examples included
✅ No external dependencies
✅ Pure functions (no side effects)
✅ O(1) time and space complexity
Installation:
npm install iranian-national-id-validatorTypeScript Usage:
import { validateIranianNationalId } from 'iranian-national-id-validator';
const isValid = validateIranianNationalId('0499370899');
console.log(isValid); // trueJavaScript (ES Module) Usage:
import { validateIranianNationalId } from 'iranian-national-id-validator';
const isValid = validateIranianNationalId('0499370899');
console.log(isValid); // trueJavaScript (CommonJS) Usage:
const { validateIranianNationalId } = require('iranian-national-id-validator');
const isValid = validateIranianNationalId('0499370899');
console.log(isValid); // trueFeatures:
- ✅ Zero dependencies
- ✅ TypeScript support with full type definitions
- ✅ Dual package (CommonJS + ES Module)
- ✅ Lightweight (< 10KB)
- ✅ 100% test coverage
- ✅ Works in Node.js and browsers
Documentation: NPM Package | GitHub
Installation:
# Copy the file to your project
cp typescript/validateIranianNationalId.ts ./src/Usage:
import validateIranianNationalId from './validateIranianNationalId';
const isValid = validateIranianNationalId('0499370899');
console.log(isValid); // trueInstallation:
# Copy the file to your project
cp javascript/validateIranianNationalId.js ./src/Usage:
import validateIranianNationalId from './validateIranianNationalId.js';
const isValid = validateIranianNationalId('0499370899');
console.log(isValid); // trueInstallation:
# Copy the file to your project
cp python/validate_iranian_national_id.py ./Usage:
from validate_iranian_national_id import validate_iranian_national_id
is_valid = validate_iranian_national_id('0499370899')
print(is_valid) # TrueInstallation:
# Copy the file to your project
cp csharp/IranianNationalIdValidator.cs ./Usage:
using IranianNationalIdValidator;
bool isValid = IranianNationalIdValidator.ValidateIranianNationalId("0499370899");
Console.WriteLine(isValid); // TrueInstallation:
# Copy the file to your project
cp kotlin/IranianNationalIdValidator.kt ./src/main/kotlin/Usage:
import validateIranianNationalId
fun main() {
val isValid = validateIranianNationalId("0499370899")
println(isValid) // true
}Installation:
# Copy the file to your project
cp java/IranianNationalIdValidator.java ./src/main/java/Usage:
import IranianNationalIdValidator;
public class Main {
public static void main(String[] args) {
boolean isValid = IranianNationalIdValidator.validateIranianNationalId("0499370899");
System.out.println(isValid); // true
}
}Installation:
# Copy the file to your project
cp php/IranianNationalIdValidator.php ./Usage:
<?php
require_once 'IranianNationalIdValidator.php';
$isValid = IranianNationalIdValidator::validateIranianNationalId('0499370899');
var_dump($isValid); // bool(true)
?>The validator handles various edge cases:
| Input | Result | Reason |
|---|---|---|
null / undefined / None |
❌ False | Invalid input |
"" (empty string) |
❌ False | Too short |
"123456789" |
❌ False | Only 9 digits |
"12345678901" |
❌ False | 11 digits (too long) |
"123456789a" |
❌ False | Contains non-numeric |
"0000000000" |
❌ False | All digits identical |
"1111111111" |
❌ False | All digits identical |
" 0499370899" |
❌ False | Contains whitespace |
"۰۴۹۹۳۷۰۸۹۹" |
❌ False | Persian numerals (not ASCII) |
"0499370899" |
✅ True | Valid National ID |
-
Format Validation Only: This validator only checks if the ID follows the correct format and algorithm. It does NOT verify if the ID actually exists in government databases.
-
Not for Authentication: Never use this validator alone for user authentication or identity verification.
-
Not for Authorization: A valid ID format doesn't grant any permissions or access rights.
-
Privacy:
- Never log actual National IDs in production
- Treat National IDs as sensitive personal information
- Follow GDPR and local privacy regulations
-
Input Sanitization:
- No automatic trimming of whitespace
- No type coercion (numeric inputs are rejected)
- No normalization of Persian/Arabic numerals
- Time Complexity: O(1) - constant time for all operations
- Space Complexity: O(1) - no dynamic memory allocation
- Pure Function: No side effects, thread-safe
✅ DO:
- Use for client-side validation
- Use for format checking before database queries
- Combine with server-side validation
- Handle validation errors gracefully
❌ DON'T:
- Use as the sole authentication method
- Store National IDs in plain text
- Log National IDs in application logs
- Trust client-side validation alone
0499370899 ✅
0790419904 ✅
0013542419 ✅
0000000000 ❌ (repeated digits)
1111111111 ❌ (repeated digits)
123456789 ❌ (too short)
12345678901 ❌ (too long)
123456789a ❌ (contains letter)
0499370898 ❌ (wrong check digit)
import { validateIranianNationalId } from 'iranian-national-id-validator';
// Form validation
function handleSubmit(formData: { nationalId: string }) {
if (!validateIranianNationalId(formData.nationalId)) {
throw new Error('Invalid National ID format');
}
// Proceed with form submission
submitToServer(formData);
}
// Express.js API endpoint validation
import express from 'express';
const app = express();
app.post('/api/users', (req, res) => {
const { nationalId } = req.body;
if (!validateIranianNationalId(nationalId)) {
return res.status(400).json({
error: 'Invalid National ID format'
});
}
// Process valid request
createUser(req.body);
});
// React form validation
import { useState } from 'react';
import { validateIranianNationalId } from 'iranian-national-id-validator';
function UserForm() {
const [nationalId, setNationalId] = useState('');
const [error, setError] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (!validateIranianNationalId(nationalId)) {
setError('کد ملی نامعتبر است');
return;
}
// Submit form
submitForm({ nationalId });
};
return (
<form onSubmit={handleSubmit}>
<input
value={nationalId}
onChange={(e) => setNationalId(e.target.value)}
placeholder="کد ملی"
/>
{error && <span className="error">{error}</span>}
<button type="submit">ثبت</button>
</form>
);
}from validate_iranian_national_id import validate_iranian_national_id
# Django form validation
from django import forms
class UserForm(forms.Form):
national_id = forms.CharField(max_length=10)
def clean_national_id(self):
national_id = self.cleaned_data['national_id']
if not validate_iranian_national_id(national_id):
raise forms.ValidationError('Invalid National ID format')
return national_id
# Flask API validation
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/api/users', methods=['POST'])
def create_user():
national_id = request.json.get('national_id')
if not validate_iranian_national_id(national_id):
return jsonify({'error': 'Invalid National ID format'}), 400
# Process valid request
return jsonify({'success': True})using IranianNationalIdValidator;
// ASP.NET Core API validation
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
[HttpPost]
public IActionResult CreateUser([FromBody] UserDto user)
{
if (!IranianNationalIdValidator.ValidateIranianNationalId(user.NationalId))
{
return BadRequest(new { error = "Invalid National ID format" });
}
// Process valid request
return Ok(new { success = true });
}
}
// Model validation attribute
public class ValidNationalIdAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext context)
{
var nationalId = value as string;
if (string.IsNullOrEmpty(nationalId) ||
!IranianNationalIdValidator.ValidateIranianNationalId(nationalId))
{
return new ValidationResult("Invalid National ID format");
}
return ValidationResult.Success;
}
}
// Usage in model
public class UserDto
{
[ValidNationalId]
public string NationalId { get; set; }
}- Package: iranian-national-id-validator
- Repository: GitHub
- Documentation: Full API documentation and examples available in the package README
- Bundle Size: < 10KB minified
- Coverage: 100% test coverage
Contributions are welcome! To add a new language implementation:
- Follow the same validation logic
- Include comprehensive comments (English & Persian)
- Add usage examples
- Follow the language's coding conventions
- Update this README with the new implementation
For the NPM package, please visit the package repository for contribution guidelines.
This project is provided as-is for educational and practical use. Feel free to use it in your projects.
Based on the official Iranian National ID validation algorithm used by Iranian government systems.
الگوریتم رسمی اعتبارسنجی کد ملی ایران که توسط سیستمهای دولتی ایران استفاده میشود.
Made with ❤️ for the Iranian developer community
با ❤️ برای جامعه توسعهدهندگان ایرانی ساخته شده است