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

nik-id

v1.0.1

Published

Parser, validator, dan generator NIK (Nomor Induk Kependudukan) Indonesia — TypeScript, zero dependencies

Readme

nik-id

npm version npm downloads CI TypeScript License: MIT Node.js Zero Dependencies codecov

Parser, validator, dan generator NIK (Nomor Induk Kependudukan) Indonesia.

TypeScript-first, zero dependencies, 100% test coverage, dual ESM+CJS, tree-shakeable.

npm install nik-id

Tidak perlu database, API call, atau file eksternal. Cukup install dan langsung pakai.

Fitur

  • Validasi format -- cek apakah NIK valid (panjang, digit, provinsi, tanggal lahir, nomor urut)
  • Parse komponen -- ekstrak kode wilayah, tanggal lahir, gender, dan nomor urut dari NIK
  • Generate NIK -- buat NIK yang valid secara format untuk testing, seeding, atau demo
  • Discriminated union -- return type aman di-narrow pakai result.valid (TypeScript-friendly)
  • Error bahasa Indonesia -- semua pesan error dalam bahasa Indonesia
  • Tree-shakeable -- import hanya fungsi yang dibutuhkan via sub-path
  • TypeScript-first -- strict types, auto-complete di IDE
  • Dual ESM + CJS -- support semua environment (browser, Node.js, Bun, Deno)
  • Zero dependencies -- tidak ada dependency runtime sama sekali
  • 100% coverage -- statements, branches, functions, lines

Struktur NIK

NIK (Nomor Induk Kependudukan) adalah nomor identitas penduduk Indonesia yang terdiri dari 16 digit angka:

3204 07 650885 0001
│    │  │      └── Nomor urut registrasi (4 digit, 0001-9999)
│    │  └── Tanggal lahir DDMMYY — perempuan: DD + 40 (jadi 41-71)
│    └── Kode kecamatan (2 digit, format Kemendagri)
└── Kode kabupaten/kota (4 digit, format Kemendagri)

| Posisi | Digit | Keterangan | Contoh | |--------|-------|------------|--------| | 1-2 | 2 digit | Kode provinsi Kemendagri (11-97) | 32 = Jawa Barat | | 3-4 | 2 digit | Kode kabupaten/kota | 04 = Kab. Bandung | | 5-6 | 2 digit | Kode kecamatan | 07 = Nagreg | | 7-8 | 2 digit | Tanggal lahir (DD), perempuan +40 | 65 = tanggal 25 (perempuan) | | 9-10 | 2 digit | Bulan lahir (MM) | 08 = Agustus | | 11-12 | 2 digit | Tahun lahir (YY) | 85 = 1985 | | 13-16 | 4 digit | Nomor urut registrasi | 0001 |

Catatan penting:

  • NIK menggunakan kode Kemendagri (Kementerian Dalam Negeri), bukan BPS
  • Perempuan: tanggal lahir ditambah 40 (DD 01-31 → DD 41-71)
  • Tahun 2 digit: disambiguasi berdasarkan tahun sekarang (YY > sekarang → 1900+YY, else 2000+YY)

Quick Start

import { validateNIK, parseNIK, generateNIK } from 'nik-id';

// Validasi — cek apakah NIK valid
const valid = validateNIK("3204076508850001");
console.log(valid); // { valid: true }

// Parse — ekstrak semua komponen
const parsed = parseNIK("3204076508850001");
if (parsed.valid) {
  console.log(parsed.provinceCode);    // "32"
  console.log(parsed.regencyCode);     // "3204"
  console.log(parsed.districtCode);    // "320407"
  console.log(parsed.gender);          // "F"
  console.log(parsed.birthDate);       // Date: 1985-08-25
  console.log(parsed.sequenceNumber);  // "0001"
}

// Generate — buat NIK untuk testing
const nik = generateNIK({ gender: "F", birthDate: new Date("1985-08-25") });
console.log(nik); // "xxxxxx6508850001" (wilayah random)

API Reference

validateNIK(nik: string): ValidationResult

Validasi format NIK secara bertahap (fail-fast). Return discriminated union:

import { validateNIK } from 'nik-id';
// atau: import { validateNIK } from 'nik-id/validate';

// NIK valid
validateNIK("3204076508850001");
// → { valid: true }

// Panjang salah
validateNIK("123");
// → { valid: false, error: "NIK harus 16 digit" }

// Mengandung huruf
validateNIK("320407650885000A");
// → { valid: false, error: "NIK hanya boleh berisi angka" }

// Kode provinsi di luar range
validateNIK("0004076508850001");
// → { valid: false, error: "Kode provinsi tidak valid" }

// Tanggal tidak ada di kalender (31 Februari)
validateNIK("3204073102850001");
// → { valid: false, error: "Tanggal lahir tidak valid" }

// Nomor urut 0000
validateNIK("3204076508850000");
// → { valid: false, error: "Nomor urut tidak valid" }

parseNIK(nik: string): NIKResult

Parse NIK menjadi komponen-komponennya. Memvalidasi terlebih dahulu — kalau tidak valid, return error.

import { parseNIK } from 'nik-id';
// atau: import { parseNIK } from 'nik-id/parse';

const result = parseNIK("3204076508850001");
if (result.valid) {
  console.log(result.nik);             // "3204076508850001"
  console.log(result.provinceCode);    // "32"       — Jawa Barat
  console.log(result.regencyCode);     // "3204"     — Kab. Bandung
  console.log(result.districtCode);    // "320407"   — Nagreg
  console.log(result.gender);          // "F"        — Perempuan
  console.log(result.birthDate);       // Date: 1985-08-25
  console.log(result.sequenceNumber);  // "0001"
} else {
  console.log(result.error);
}

Komponen yang diekstrak:

| Field | Tipe | Keterangan | Contoh | |-------|------|------------|--------| | nik | string | NIK asli yang di-parse | "3204076508850001" | | provinceCode | string | Kode provinsi Kemendagri (2 digit) | "32" | | regencyCode | string | Kode kabupaten/kota Kemendagri (4 digit) | "3204" | | districtCode | string | Kode kecamatan Kemendagri (6 digit) | "320407" | | birthDate | Date | Tanggal lahir (object Date) | Date(1985-08-25) | | gender | "M" \| "F" | Jenis kelamin | "F" | | sequenceNumber | string | Nomor urut registrasi (4 digit) | "0001" |

generateNIK(options?: GenerateOptions): string

Generate NIK yang valid secara format. Semua parameter opsional — yang tidak diisi akan di-random.

import { generateNIK } from 'nik-id';
// atau: import { generateNIK } from 'nik-id/generate';

// Full random
generateNIK();

// Gender spesifik
generateNIK({ gender: "F" });
generateNIK({ gender: "M" });

// Tanggal lahir spesifik
generateNIK({ birthDate: new Date("1985-08-25") });

// Gender + tanggal lahir
generateNIK({ gender: "F", birthDate: new Date("1985-08-25") });

// Wilayah spesifik (harus konsisten dari provinsi ke kecamatan)
generateNIK({
  provinceCode: "32",
  regencyCode: "3204",
  districtCode: "320407",
});

// Semua opsi sekaligus
generateNIK({
  provinceCode: "32",
  regencyCode: "3204",
  districtCode: "320407",
  gender: "F",
  birthDate: new Date("1985-08-25"),
});

Opsi yang tersedia:

| Opsi | Tipe | Keterangan | |------|------|------------| | provinceCode | string? | Kode provinsi Kemendagri (2 digit, 11-97) | | regencyCode | string? | Kode kabupaten/kota (4 digit, harus match provinsi) | | districtCode | string? | Kode kecamatan (6 digit, harus match kabupaten) | | gender | "M" \| "F"? | Jenis kelamin | | birthDate | Date? | Tanggal lahir (kalau tidak diisi, random 1950-2005) |

Error yang di-throw:

// Kode provinsi di luar range
generateNIK({ provinceCode: "99" });
// → Error: "Kode provinsi tidak valid (harus 11-97)"

// Kode kabupaten tidak cocok dengan provinsi
generateNIK({ provinceCode: "32", regencyCode: "3301" });
// → Error: 'Kode kabupaten/kota "3301" tidak sesuai dengan kode provinsi "32"'

// Kode kecamatan tidak cocok dengan kabupaten
generateNIK({ provinceCode: "32", regencyCode: "3204", districtCode: "320501" });
// → Error: 'Kode kecamatan "320501" tidak sesuai dengan kode kabupaten/kota "3204"'

Catatan: NIK yang dihasilkan valid secara format tapi bukan NIK asli milik orang sungguhan. Cocok untuk testing, seeding database, atau demo.

Validasi yang Dilakukan

validateNIK dan parseNIK melakukan pengecekan bertahap (fail-fast — berhenti di error pertama):

| # | Pengecekan | Detail | |---|-----------|--------| | 1 | Tipe data | Input harus bertipe string | | 2 | Panjang | Harus tepat 16 karakter | | 3 | Format | Harus semua digit angka (0-9) | | 4 | Kode provinsi | 2 digit pertama harus dalam range 11-97 | | 5 | Tanggal lahir | DD (01-31 atau 41-71), MM (01-12), valid di kalender | | 6 | Nomor urut | Digit 13-16 tidak boleh 0000 |

Catatan: Validasi bersifat format-only. Package ini tidak mengecek apakah kode wilayah benar-benar terdaftar di database Kemendagri. Untuk lookup nama wilayah, gunakan package kode-wilayah-id.

Error Messages

Semua pesan error dalam Bahasa Indonesia:

| Error | Penyebab | Contoh Input | |-------|----------|-------------| | NIK harus berupa string | Input bukan bertipe string | 12345, null, undefined | | NIK harus 16 digit | Panjang bukan 16 karakter | "123", "" | | NIK hanya boleh berisi angka | Mengandung karakter non-digit | "320407650885000A" | | Kode provinsi tidak valid | 2 digit pertama di luar range 11-97 | "0004076508850001" | | Tanggal lahir tidak valid | Tanggal/bulan invalid atau tidak ada di kalender | "3204073102850001" | | Nomor urut tidak valid | 4 digit terakhir adalah 0000 | "3204076508850000" |

Tree-shaking / Sub-path Imports

Import hanya fungsi yang dibutuhkan — bundler hanya include kode yang di-import:

// Hanya validasi
import { validateNIK } from 'nik-id/validate';

// Hanya parsing
import { parseNIK } from 'nik-id/parse';

// Hanya generator
import { generateNIK } from 'nik-id/generate';

// Types only (zero runtime)
import type { NIKResult, ValidationResult, GenerateOptions } from 'nik-id/types';

// Atau import semua sekaligus
import { validateNIK, parseNIK, generateNIK } from 'nik-id';

Bundle Size

Package ini sangat ringan karena zero dependencies dan hanya berisi logika validasi:

| Import | Ukuran (minified) | |--------|-------------------| | nik-id/validate | ~1.8 KB | | nik-id/parse | ~2.8 KB | | nik-id/generate | ~2.3 KB | | nik-id (full) | ~5.2 KB |

Integrasi dengan kode-wilayah-id

Package ini tidak menyertakan data wilayah — hanya mengembalikan kode Kemendagri. Untuk resolve ke nama wilayah, gunakan package kode-wilayah-id:

npm install kode-wilayah-id
import { parseNIK } from 'nik-id';
import {
  getProvinceByKemendagriCode,
  getRegencyByKemendagriCode,
  getDistrictByKemendagriCode,
} from 'kode-wilayah-id';

const result = parseNIK("3204076508850001");
if (result.valid) {
  const province = getProvinceByKemendagriCode(result.provinceCode);
  const regency = getRegencyByKemendagriCode(result.regencyCode);
  const district = getDistrictByKemendagriCode(result.districtCode);

  console.log(province?.name); // "JAWA BARAT"
  console.log(regency?.name);  // "KAB. BANDUNG"
  console.log(district?.name); // "NAGREG"
}

Discriminated Union Pattern

Return type parseNIK dan validateNIK menggunakan discriminated union — TypeScript bisa narrow type otomatis berdasarkan result.valid:

import { parseNIK } from 'nik-id';
import type { NIKResult, NIKValid, NIKInvalid } from 'nik-id/types';

const result: NIKResult = parseNIK(input);

if (result.valid) {
  // TypeScript tahu ini NIKValid — semua field tersedia
  console.log(result.provinceCode);  // ✅ string
  console.log(result.gender);        // ✅ "M" | "F"
  console.log(result.birthDate);     // ✅ Date
} else {
  // TypeScript tahu ini NIKInvalid — hanya error
  console.log(result.error);         // ✅ string
  // console.log(result.gender);     // ❌ compile error!
}

Pattern yang sama berlaku untuk validateNIK:

import { validateNIK } from 'nik-id';

const result = validateNIK(input);
if (result.valid) {
  // ValidationValid — tidak ada field lain
  console.log("NIK valid!");
} else {
  // ValidationInvalid — ada field error
  console.log(result.error);
}

Contoh Penggunaan

Lihat folder examples/ untuk contoh lengkap di berbagai framework dan runtime:

| Framework | File | Fitur | |-----------|------|-------| | Node.js | node.ts | Basic usage — validasi, parse, generate | | React | react.tsx | Form validasi KTP dengan feedback real-time | | Next.js | nextjs.tsx | API route + server component | | Express | express.ts | REST API endpoint validasi NIK | | Hono | hono.ts | Lightweight REST API validasi NIK | | Bun | bun.ts | Native Bun HTTP server | | Deno | deno.ts | Native Deno server |

# Jalankan contoh Node.js
npx tsx examples/node.ts

Types

Semua type tersedia di nik-id/types:

import type {
  NIKValid,
  NIKInvalid,
  NIKResult,
  ValidationValid,
  ValidationInvalid,
  ValidationResult,
  GenerateOptions,
} from 'nik-id/types';

NIKResult (parseNIK)

// Hasil valid
interface NIKValid {
  valid: true;
  nik: string;              // "3204076508850001"
  provinceCode: string;     // "32"
  regencyCode: string;      // "3204"
  districtCode: string;     // "320407"
  birthDate: Date;          // Date(1985-08-25)
  gender: "M" | "F";       // "F"
  sequenceNumber: string;   // "0001"
}

// Hasil invalid
interface NIKInvalid {
  valid: false;
  error: string;            // "NIK harus 16 digit"
}

type NIKResult = NIKValid | NIKInvalid;

ValidationResult (validateNIK)

interface ValidationValid {
  valid: true;
}

interface ValidationInvalid {
  valid: false;
  error: string;
}

type ValidationResult = ValidationValid | ValidationInvalid;

GenerateOptions (generateNIK)

interface GenerateOptions {
  provinceCode?: string;    // "32" (2 digit, 11-97)
  regencyCode?: string;     // "3204" (4 digit, harus match provinsi)
  districtCode?: string;    // "320407" (6 digit, harus match kabupaten)
  gender?: "M" | "F";      // Jenis kelamin
  birthDate?: Date;         // Tanggal lahir (default: random 1950-2005)
}

Encoding Tanggal Lahir

NIK meng-encode tanggal lahir dalam 6 digit (posisi 7-12) dengan format DDMMYY:

Gender dan DD

| Gender | Range DD | Contoh | Arti | |--------|----------|--------|------| | Laki-laki | 01-31 | DD=15 | Lahir tanggal 15 | | Perempuan | 41-71 | DD=65 | Lahir tanggal 25 (65-40=25) | | Invalid | 00, 32-40, 72-99 | -- | Tidak valid |

Disambiguasi Tahun (YY)

Karena NIK hanya menyimpan 2 digit tahun, perlu disambiguasi:

| YY | Tahun sekarang (2 digit) | Hasil | Logika | |----|--------------------------|-------|--------| | 85 | 26 | 1985 | 85 > 26 → 1900 + 85 | | 02 | 26 | 2002 | 02 ≤ 26 → 2000 + 02 | | 26 | 26 | 2026 | 26 ≤ 26 → 2000 + 26 | | 27 | 26 | 1927 | 27 > 26 → 1900 + 27 | | 00 | 26 | 2000 | 00 ≤ 26 → 2000 + 00 | | 99 | 26 | 1999 | 99 > 26 → 1900 + 99 |

Kode Wilayah Kemendagri

NIK menggunakan kode wilayah format Kemendagri (bukan BPS):

| Level | Panjang | Contoh | Keterangan | |-------|---------|--------|------------| | Provinsi | 2 digit | "32" | Jawa Barat | | Kabupaten/Kota | 4 digit | "3204" | Kab. Bandung | | Kecamatan | 6 digit | "320407" | Nagreg |

Range kode provinsi yang valid: 11 (Aceh) sampai 97 (Papua Barat Daya).

Package ini hanya memvalidasi range kode provinsi (11-97), tidak mengecek apakah kode spesifik benar-benar ada. Untuk lookup nama wilayah, gunakan kode-wilayah-id.

Contributing

Kontribusi sangat diterima!

git clone https://github.com/sumitroajiprabowo/nik-id.git
cd nik-id
npm install
npm run lint          # Lint check (Biome)
npm run format:check  # Format check
npm run typecheck     # TypeScript check
npm run test:coverage # Test dengan coverage (harus 100%)
npm run build         # Build ESM + CJS

Changelog

Lihat CHANGELOG.md untuk riwayat perubahan.

Lisensi

MIT (c) Sumitro Aji Prabowo