Iranian National ID Validation
The verifyIranianNationalId utility validates Iranian national identification numbers using the official checksum algorithm and format requirements.
Basic Usage
import { verifyIranianNationalId } from '@persian-tools/persian-tools' ;
Simple Validation
verifyIranianNationalId ( "0499370899" ); // true
verifyIranianNationalId ( "0684159415" ); // true
verifyIranianNationalId ( "1234567890" ); // false
verifyIranianNationalId ( "0000000000" ); // false
Validation Rules
The function validates Iranian national IDs based on:
Uses modulo-11 checksum validation - Last digit serves as check digit - Implements official Iranian algorithm
All zeros: 0000000000
All same digits: 1111111111, 2222222222, etc.
Sequential patterns in some cases
The function accepts various input formats:
// Standard numeric string
verifyIranianNationalId ( "0499370899" ); // true
// With Persian digits
verifyIranianNationalId ( "۰۴۹۹۳۷۰۸۹۹" ); // true
// With Arabic digits
verifyIranianNationalId ( "٠٤٩٩٣٧٠٨٩٩" ); // true
// Number input
verifyIranianNationalId ( 499370899 ); // true (auto-padded to 10 digits)
Advanced Examples
interface UserForm {
nationalId : string ;
name : string ;
phone : string ;
}
function validateUserForm ( form : UserForm ) {
const errors : string [] = [];
// Validate National ID
if ( ! verifyIranianNationalId ( form . nationalId )) {
errors . push ( "کد ملی معتبر نیست" );
}
return {
isValid: errors . length === 0 ,
errors ,
normalizedNationalId: digitsFaToEn ( digitsArToEn ( form . nationalId )),
};
}
Batch Validation
function validateNationalIdBatch ( ids : string []) {
return ids . map (( id ) => ({
original: id ,
normalized: digitsFaToEn ( digitsArToEn ( id )),
isValid: verifyIranianNationalId ( id ),
location: verifyIranianNationalId ( id ) ? getPlaceByIranNationalId ( id ) : null ,
}));
}
const results = validateNationalIdBatch ([ "0499370899" , "۰۶۸۴۱۵۹۴۱۵" , "1234567890" ]);
Database Integration
class UserService {
async createUser ( userData : { nationalId : string ; name : string }) {
// Normalize and validate National ID
const normalizedId = digitsFaToEn ( digitsArToEn ( userData . nationalId ));
if ( ! verifyIranianNationalId ( normalizedId )) {
throw new Error ( "کد ملی معتبر نیست" );
}
// Check for existing user
const existingUser = await this . findByNationalId ( normalizedId );
if ( existingUser ) {
throw new Error ( "کاربر با این کد ملی قبلاً ثبتنام کرده است" );
}
// Create user with normalized ID
return this . save ({
... userData ,
nationalId: normalizedId ,
});
}
}
Valid National ID Examples
Here are some valid Iranian national IDs for testing:
const validIds = [
"0499370899" , // خمین
"0684159415" , // شیراز
"0076229645" , // تهران
"0013542419" , // تهران
"0012016467" , // تهران
"0010859657" , // تهران
];
validIds . forEach (( id ) => {
console . log ( ` ${ id } : ${ verifyIranianNationalId ( id ) } ` ); // all true
});
Edge Cases
verifyIranianNationalId ( "" ); // false
verifyIranianNationalId ( "123" ); // false (too short)
verifyIranianNationalId ( "12345678901" ); // false (too long)
verifyIranianNationalId ( "abcd123456" ); // false (contains letters)
verifyIranianNationalId ( null ); // false
verifyIranianNationalId ( undefined ); // false
Special Invalid Patterns
verifyIranianNationalId ( "0000000000" ); // false (all zeros)
verifyIranianNationalId ( "1111111111" ); // false (all same digit)
verifyIranianNationalId ( "2222222222" ); // false (all same digit)
verifyIranianNationalId ( "9999999999" ); // false (all same digit)
Checksum Failures
verifyIranianNationalId ( "1234567890" ); // false (invalid checksum)
verifyIranianNationalId ( "0123456789" ); // false (invalid checksum)
verifyIranianNationalId ( "9876543210" ); // false (invalid checksum)
Algorithm Details
The validation follows these steps:
Format Check : Ensure exactly 10 digits
Pattern Check : Reject all-same-digit patterns
Checksum Calculation : Apply modulo-11 algorithm
Check Digit Verification : Compare with last digit
// Simplified algorithm illustration
function nationalIdChecksum ( id : string ) : boolean {
const digits = id . split ( "" ). map ( Number );
const checkDigit = digits [ 9 ];
let sum = 0 ;
for ( let i = 0 ; i < 9 ; i ++ ) {
sum += digits [ i ] * ( 10 - i );
}
const remainder = sum % 11 ;
const expectedCheck = remainder < 2 ? remainder : 11 - remainder ;
return checkDigit === expectedCheck ;
}
1,000 validations : ~50ms
10,000 validations : ~500ms
100,000 validations : ~5s
TypeScript Support
import { verifyIranianNationalId } from "persian-tools" ;
// Type-safe validation
const isValid : boolean = verifyIranianNationalId ( "0499370899" );
// Custom validation function with typing
function validateNationalId ( id : string | number ) : {
isValid : boolean ;
normalized : string ;
} {
const normalized = digitsFaToEn ( digitsArToEn ( id . toString ()));
return {
isValid: verifyIranianNationalId ( normalized ),
normalized ,
};
}
Integration Patterns
React Hook
import { useState , useEffect } from "react" ;
function useNationalIdValidation ( id : string ) {
const [ validation , setValidation ] = useState ({
isValid: false ,
isChecking: false ,
error: null ,
});
useEffect (() => {
if ( ! id ) {
setValidation ({ isValid: false , isChecking: false , error: null });
return ;
}
setValidation (( prev ) => ({ ... prev , isChecking: true }));
const timeoutId = setTimeout (() => {
const isValid = verifyIranianNationalId ( id );
setValidation ({
isValid ,
isChecking: false ,
error: isValid ? null : "کد ملی معتبر نیست" ,
});
}, 300 ); // Debounce
return () => clearTimeout ( timeoutId );
}, [ id ]);
return validation ;
}
Express.js Middleware
import { Request , Response , NextFunction } from "express" ;
function validateNationalId ( req : Request , res : Response , next : NextFunction ) {
const { nationalId } = req . body ;
if ( ! nationalId ) {
return res . status ( 400 ). json ({ error: "کد ملی الزامی است" });
}
if ( ! verifyIranianNationalId ( nationalId )) {
return res . status ( 400 ). json ({ error: "کد ملی معتبر نیست" });
}
// Normalize and attach to request
req . body . nationalId = digitsFaToEn ( digitsArToEn ( nationalId ));
next ();
}
Security Considerations
National ID validation should be used alongside other verification methods. A valid checksum doesn’t guarantee the ID
belongs to the person claiming it.
// Good practice: Combined validation
interface UserVerification {
nationalId : string ;
phone : string ;
name : string ;
}
function verifyUser ( data : UserVerification ) : boolean {
return (
verifyIranianNationalId ( data . nationalId ) &&
verifyIranianNationalId ( data . phone ) && // additional checks
data . name . length > 0
);
}