npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

iran-validation

v0.9.1

Published

Validate Iranian SHEBA (IBAN), national code & legal ID, bank card/BIN/Luhn, postal code, mobile & landline, vehicle plates (car/motorcycle), IMEI, passport, IPv4/IPv6. ESM, data bundled in-package.

Readme

Iran Validation

A JavaScript (ESM) library to validate common Iranian identifiers: SHEBA (IBAN), national code (natural and legal national IDs), bank card, vehicle plate, IMEI, IPv4/IPv6 (optional Iranian-range check for IPv4), mobile (Iran-only subset of Phone), landline / mobile phone (Phone), postal code, passport number, and digit helpers.

Data scope & updates

All metadata and lookup tables ship inside this package. Nothing here calls an external HTTP API at runtime—validation and hints (banks, BINs, area codes, operator prefixes, IPv4 ranges used for Iran, postal routing prefixes, plate/county mappings, national-code issuance regions, etc.) come from embedded data and algorithms.

That means:

  • Figures such as bankInfo, provinceInfo / cityInfo, isIranian for IPv4, or plate geography reflect whatever version of the dataset is bundled in the npm release you installed, not a live national registry or carrier feed.
  • Rules that are purely algorithmic (e.g. Luhn/IMEI/SHEBA check digits, national-code checksums, passport shape) stay stable unless the spec or implementation changes.
  • Tabular real-world assignments change over time—Ranges can be outdated, reorganized banks can share legacy BIN rows, postal or plate tables can lag official updates. Maintainer updates may arrive in future package versions; there is no promise that a given release matches “today” in every domain.
  • For authoritative or legally binding decisions, rely on official sources and processes, not this library alone.

Installation

npm i iran-validation
import {
  ShebaNumber,
  PostalCode,
  validatePostalCode,
  validateBankCard,
  IranPlate,
  validateImei,
  IranMobileNumber,
  toEnglishDigits,
} from "iran-validation";

Subpath imports

Each module can be imported directly (tree‑friendly):

| Symbol / topic | Import path | |-----------------------|------------------------------------------| | ShebaNumber | iran-validation/sheba | | Phone | iran-validation/phone | | NationalCode, IranNationalIdentifier, … | iran-validation/national-code | | National ID façade | iran-validation/national-id | | Bank card | iran-validation/bank-card | | Car / motorcycle plate| iran-validation/car-number | | IMEI | iran-validation/imei | | IP | iran-validation/ip | | Mobile | iran-validation/mobile | | PassportNumber | iran-validation/passport-number | | PostalCode | iran-validation/postal-code | | toEnglishDigits | iran-validation/utils/toEnglishDigits |


Usage

SHEBA (ShebaNumber)

Iranian SHEBA follows ISO 13616 (IBAN check). Expected format for Iran: IR + 24 digits (26 characters total).

import { ShebaNumber, getIranBankByShebaCode } from "iran-validation";
// or: import ShebaNumber, { getIranBankByShebaCode } from "iran-validation/sheba";

const sheba = new ShebaNumber("IR840170000000343149119002");

sheba.isValid(); // boolean

// Persian / Arabic‑Indic digits are normalized automatically
sheba.englishForm; // "IR840170000000343149119002" (Latin digits, IR uppercase)

sheba.bankCode; // e.g. "017"
sheba.bankInfo; // { en_name, fa_name, code }

getIranBankByShebaCode("017"); // same shape as bankInfo when known

// Optional length override (non‑Iran IBAN experimentation)
sheba.shebaLength = 25;

National code & national ID (NationalCode, IranNationalIdentifier, validateNationalId)

  • Natural person: 10-digit national code (with optional zero-padding rules for shorter inputs).
  • Legal entity: 11-digit national identifier; inferred when length is 11 unless you pass { kind: 'natural' | 'legal' } to IranNationalIdentifier / validateNationalIdentifier.
import {
  NationalCode,
  IranNationalIdentifier,
  NationalIdentifierKind,
  validateNationalIdentifier,
  validateNationalId,
  getNaturalNationalCodePlace,
} from "iran-validation";
// or from "iran-validation/national-code" / "iran-validation/national-id"

validateNationalIdentifier("5940041698"); // natural
validateNationalId("۱۰۳۸۰۱۷۴۷۸۵", { kind: NationalIdentifierKind.LEGAL }); // legal

const unified = new IranNationalIdentifier("5940041698");
unified.isValid();
unified.provinceInfo; // natural: FA/EN place hints from first 3 digits; legal: unknown
unified.cityInfo;

const nc = new NationalCode("5940041698"); // backwards-compatible: forces natural interpretation
nc.isValid();

getNaturalNationalCodePlace("5940041698"); // place row from first three digits

Bank card (validateBankCard, IranBankCard)

Iranian 16-digit debit/credit-style numbers: optional Luhn (default true) and Iranian BIN table check (default iranianBinOnly: true).

import {
  validateBankCard,
  IranBankCard,
  normalizeBankCardInput,
  bankInfoFromCardBin,
} from "iran-validation";
// or from "iran-validation/bank-card"

validateBankCard("6037991111111112");
validateBankCard("4532015112830366", { iranianBinOnly: false });

const card = new IranBankCard("۶۰۳۷-۹۹۱۱ ۱۱۱۱ ۱۱۱۲");
card.englishForm; // "6037991111111112"
card.bankInfo; // via BIN → SHEBA map or inline BIN table
card.isValid();

Vehicle plate (IranPlate, validateCarNumber)

  • Car / public: normalized pattern two digits + Persian letter + three digits + two-digit province code (e.g. 66ق66611).
  • Motorcycle: eight consecutive digits three-digit area + five-digit serial.

Persian letter variants and separators are normalized.

import { IranPlate, validateCarNumber, normalizePlateInput } from "iran-validation";
// or from "iran-validation/car-number"

validateCarNumber("66ق66611");
validateCarNumber("11112345", { kinds: ["motorcycle"] });

const plate = new IranPlate("۶۶ ق ۶۶۶ ۱۱");
plate.normalized;
plate.kind; // "car" | "motorcycle" | null
plate.isValid();
plate.provinceInfo; // { fa_name }
plate.cityInfo;     // { fa_name }
plate.details;

IMEI (validateImei, normalizeImeiInput)

15-digit GSMA-style IMEI with Luhn check digit (default enabled; pass { luhn: false } for length/digits-only).

import { validateImei, normalizeImeiInput } from "iran-validation";
// or from "iran-validation/imei"

validateImei("490154203237518");
validateImei("۴۹۰۱۵۴۲۰۳۲۳۷۵۱۸");

IP address (IranIpAddress, validateIp)

Valid IPv4 or IPv6 literals. Iranian geo uses aggregated IPv4 ranges (no IPv6 country data in-library → isIranian is false for IPv6).

import {
  validateIp,
  IranIpAddress,
  getIpVersion,
  isIranianIp,
} from "iran-validation";
// or from "iran-validation/ip"

validateIp("185.143.232.1", { country: "IR" });
validateIp("2001:db8::1", { version: "ipv6" });

const ip = new IranIpAddress("185.143.232.1");
ip.version;
ip.normalized;
ip.isIranian;

Mobile only (IranMobileNumber, validateMobile)

Same input shapes as Phone, but accepts only Iranian mobile lines (landlines fail).

import {
  validateMobile,
  IranMobileNumber,
  getMobileOperatorInfo,
} from "iran-validation";
// or from "iran-validation/mobile"

validateMobile("+989115555555");

const m = new IranMobileNumber("09115555555");
m.operatorInfo;    // { fa_name, en_name }
m.nationalFormat;
getMobileOperatorInfo("09121987654");

Phone (Phone)

Default export class is PhoneNumber; the main package exposes it as Phone.

Supports mobile (09…) and landline (021…, 009821…, +9821…, …). Persian / Arabic‑Indic digits and spaces are normalized.

import { Phone } from "iran-validation";
// or: import Phone from "iran-validation/phone";

const mobile = new Phone("+989115555555");

mobile.phoneType;      // "mobile" | "landline" | "invalid"
mobile.isValid();      // boolean
mobile.cleanNumber;    // national significant digits without country/trunk (e.g. "9115555555" or "2188776655")
mobile.operationCode;  // mobile: operator prefix "911"; landline: area code without trunk "21"
mobile.phoneInfo;      // mobile: { codeName, operationName }; landline: { codeName: "Landline", operationName (FA city), cityEn }
mobile.cityInfo;       // landline only: { fa_name, en_name }; mobile: null

mobile.englishForm;    // "989115555555" or "982188776655" when valid
mobile.nationalFormat; // "09115555555" or "02188776655" when valid

Landline example (Tehran):

const fixed = new Phone("02188776655");
// or: new Phone("00982188776655"), new Phone("+982188776655")

fixed.phoneType;    // "landline"
fixed.cityInfo;     // { fa_name: "تهران", en_name: "Tehran" }

Accepted mobile shapes include +98…, 0098…, 098…, leading 0, national significant only, and optional dashes.

Landline validation uses a prefix table of Iranian area codes (approximate; subscriber length 5–8 digits after the area code).


Postal code (PostalCode / validatePostalCode)

Iran uses 10-digit postal codes. Spaces and dashes are ignored; Persian / Arabic‑Indic digits are converted.

import { PostalCode, validatePostalCode } from "iran-validation";
// or: import PostalCode, { validatePostalCode } from "iran-validation/postal-code";

validatePostalCode("1496714313"); // boolean

const pc = new PostalCode("۱۴۹۶۷۱۴۳۱۳"); // Persian digits OK

pc.isValid();
pc.code;          // normalized 10-digit string (Latin digits)
pc.routingArea;   // first 5 digits (string)

pc.provinceInfo; // { fa_name, en_name } — approximate from routing prefix tables
pc.regionInfo;   // { fa_name, en_name } — city / postal zone / province label

Region lookup is based on published routing-prefix ranges and may not match every edge case.


Passport number (PassportNumber)

Official-style Iranian passports use one Latin letter + eight digits. On the Persian data page only eight digits may appear (without the letter); enable that with { digitsOnly: true }.

import {
  PassportNumber,
  validatePassportNumber,
  normalizePassportInput,
} from "iran-validation";

validatePassportNumber("A12345678"); // true
validatePassportNumber("۱۲۳۴۵۶۷۸", { digitsOnly: true }); // true

const pp = new PassportNumber("a87654321");
pp.isValid(); // true
pp.englishForm; // "A87654321"

Helper: toEnglishDigits

Converts Persian (۰–۹) and Arabic‑Indic (٠–٩) digits to Latin 0–9; other characters are unchanged.

import { toEnglishDigits } from "iran-validation";
// or: import { toEnglishDigits } from "iran-validation/utils/toEnglishDigits";

toEnglishDigits("۰۱۲۳"); // "0123"

API summary

| Export / symbol | Role | |-----------------|------| | ShebaNumber, getIranBankByShebaCode | SHEBA / IBAN + bank metadata | | NationalCode, IranNationalIdentifier, validateNationalIdentifier, NationalIdentifierKind, validateNationalId, place helpers | Natural + legal national IDs | | Phone | Mobile + landline | | validateMobile, IranMobileNumber, getMobileOperatorInfo | Mobile-only wrapper | | validateBankCard, IranBankCard, normalizeBankCardInput, bankInfoFromCardBin, BIN maps | 16-digit card + BIN | | validateCarNumber, IranPlate, normalizePlateInput | Car + motorcycle plates | | validateImei, normalizeImeiInput | 15-digit IMEI + Luhn | | validateIp, IranIpAddress, getIpVersion, isIranianIp | IPv4/v6 + optional IR IPv4 | | PostalCode, validatePostalCode | 10-digit postal code + region hints | | PassportNumber, validatePassportNumber, normalizePassportInput | Passport formats | | toEnglishDigits | Digit normalization |


License

ISC — see LICENSE.