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
);
}
Place by National ID Get location information from National ID
Card Number Validation Validate Iranian bank card numbers
Phone Number Validation Validate Iranian phone numbers
Legal ID Validation Validate Iranian legal entity IDs