> ## Documentation Index
> Fetch the complete documentation index at: https://persian-tools.usestrict.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# National ID

> Validate Iranian National IDs (کد ملی) with optional city-prefix check, and generate valid synthetic IDs for fixtures.

The Iranian National ID (کد ملی) is a 10-digit code with a check digit and an embedded 3-digit city/registration prefix. Persian Tools provides validation, prefix lookup, and a generator family for tests.

## Validate

### `verifyIranianNationalId(nationalId, options?)`

```ts theme={null}
import { verifyIranianNationalId } from "@persian-tools/persian-tools";

verifyIranianNationalId("0499370899"); // true
verifyIranianNationalId("1234567890"); // false (checksum fails)
verifyIranianNationalId(undefined); // undefined (falsy input)

// Skip the city-prefix check (still verifies the checksum)
verifyIranianNationalId("9999970899", { checkPrefix: false });
```

```ts theme={null}
interface VerifyIranianNationalIdOptions {
	checkPrefix?: boolean; // default true
}
```

#### Algorithm

1. Falsy → `undefined`.
2. Length must be ≥ 8; shorter inputs are zero-padded to 10 (so `499370899` is accepted as `0499370899`).
3. Reject all-same-digit sequences (`0000000000`, `1111111111`, …) via the exported `invalidNationalIdSequences` set.
4. If `checkPrefix !== false`, the leading 3 digits must be in `validNationalIdPrefixes`.
5. Standard check-digit computation: `sum = Σ digit[i] * (10 - i)` for i = 0..8, then `digit[9]` must equal `sum % 11` (or `11 - sum%11` if `sum%11 ≥ 2`).

## Look up the place

For city/province from a National ID's 3-digit prefix, see the [Place by National ID](./place-by-national-id) page.

## Generate (for tests)

```ts theme={null}
import {
	createIranianNationalId,
	createIranianNationalIdDetailed,
	createIranianRoundNationalId,
	validateNationalIdChecksum,
	isValidNationalIdFormat,
} from "@persian-tools/persian-tools";

createIranianNationalId(); // random valid ID
createIranianNationalId({ preventRepeatedDigits: true }); // forbids all-same-digit results
createIranianNationalId({ randomGenerator: () => 0.5 }); // deterministic seed for tests

const detailed = createIranianNationalIdDetailed({ preventRepeatedDigits: true, maxRetries: 50 });
// {
//   nationalId: "1234567890",
//   checkDigit: 0,
//   attempts: 1,
//   hasRepeatedDigits: false,
//   digits: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
// }

validateNationalIdChecksum(detailed.nationalId); // true
isValidNationalIdFormat("0499370899"); // true (just shape)
```

```ts theme={null}
interface NationalIdGenerationOptions {
	preventRepeatedDigits?: boolean;
	maxRetries?: number;
	randomGenerator?: () => number;
}
interface NationalIdGenerationResult {
	nationalId: string;
	checkDigit: number;
	attempts: number;
	hasRepeatedDigits: boolean;
	digits: number[];
}
```

## Pitfalls

* **Persian/Arabic digit input is NOT auto-normalized.** `verifyIranianNationalId("۰۴۹۹۳۷۰۸۹۹")` returns `false` because `parseInt` of Persian digits yields `NaN`. Run `autoConvertDigitsToEN` first.
* **Return type is `boolean | undefined`** — use `=== true`, not truthy checks.
* **For test fixtures**, generate IDs with `createIranianNationalId(...)`. Don't commit real personal data.

## Source

`src/modules/nationalId/index.ts`, `src/modules/nationalId/create-national-id.ts` · Tests: `test/verifyIranianNationalId.spec.ts`
