Skip to main content

NIK-lookup

High-performance, lightweight Indonesian National Identity Number (Nomor Induk Kependudukan — NIK) parser and validator for JavaScript/TypeScript and Python, powered by the official kodenik database.

License: MIT Node.js Python


Features

  • $O(1)$ Hash Map Lookups: Sub-microsecond regional resolution using pre-indexed 6-digit prefix lookups from kodenik.
  • Zero External Runtime Dependencies: Built entirely with native language runtimes and standard libraries (beyond kodenik).
  • Comprehensive Calendar Validation: Strict validation including 30-day month limits, February leap-year logic ($YY \pmod 4 = 0$, $2000$ leap), and century resolution.
  • Dual-Ecosystem Distribution: Available as both an npm package (nik-lookup) and a pip package (nik-lookup).
  • TypeScript & PEP 561 Typing: Hand-authored .d.ts types for TypeScript and py.typed marker for mypy / pyright.
  • Immutable & Safe: Frozen parsed instances prevent accidental mutations; provides tryParse / try_parse and isValid / is_valid for non-throwing validation flows.
  • 100% Backward Compatible: Preserves all legacy Indonesian attribute names (provinsi, kabkota, kecamatan, tanggal_lahir, etc.).

16-Digit NIK Structure

[ P P ][ K K ][ C C ][ D D ][ M M ][ Y Y ][ S S S S ]
  1 2    3 4    5 6    7 8    9 10  11 12   13 14 15 16
|-- Wilayah (6) -----|----- Tanggal Lahir -----|-- Urut --|
  • Digits 1–2 (PP): Provincial code (kode_provinsi, 38 official provinces).
  • Digits 3–4 (KK): Regency/City code (kode_kabkota, 01–69 Kabupaten, 71–99 Kota).
  • Digits 5–6 (CC): District code (kode_kecamatan, 01–55).
  • Digits 7–8 (DD): Day of birth (Male: 01–31; Female: 41–71, where $\text{Actual Day} = \text{DD} - 40$).
  • Digits 9–10 (MM): Month of birth (01–12).
  • Digits 11–12 (YY): 2-digit birth year (century resolved against sliding window).
  • Digits 13–16 (SSSS): 4-digit unique civil registration sequential number (0001–9999).

JavaScript / TypeScript Usage

Installation

npm install nik-lookup kodenik

ECMAScript Modules (ESM)

import { NIK, parse, tryParse, isValid } from 'nik-lookup';

// Standard parsing
const nik = new NIK('3174071708450001');

console.log(nik.provinsi);         // "DKI Jakarta"
console.log(nik.kabkota);          // "Kota Jakarta Selatan"
console.log(nik.kecamatan);        // "Kebayoran Baru"
console.log(nik.tanggal_lahir);    // 17
console.log(nik.bulan_lahir);      // 8
console.log(nik.tahun_lahir);      // 45
console.log(nik.jenis_kelamin);    // "Laki - laki"
console.log(nik.kode_unik);        // "0001"

// Modern English attributes
console.log(nik.province);         // "DKI Jakarta"
console.log(nik.regency);          // "Kota Jakarta Selatan"
console.log(nik.district);         // "Kebayoran Baru"
console.log(nik.gender);           // "male"
console.log(nik.birthYear);        // 1945
console.log(nik.birthDateString);  // "1945-08-17"

CommonJS (CJS)

const { NIK, tryParse, isValid } = require('nik-lookup');

const nik = new NIK('3273016104790002');
console.log(nik.provinsi);       // "Jawa Barat"
console.log(nik.tanggal_lahir);  // 21 (Female 61 - 40 = 21)
console.log(nik.jenis_kelamin);  // "Perempuan"

Non-Throwing Validation

import { tryParse, isValid } from 'nik-lookup';

if (isValid('3174071708450001')) {
    console.log('Valid NIK');
}

const result = tryParse('invalid-nik');
// result === null

Python Usage

Installation

pip install nik-lookup kodenik

Python Quickstart

from nik_lookup import NIK, parse, try_parse, is_valid

# Standard parsing
nik = NIK("3174071708450001")

# Indonesian attributes (legacy compatibility)
print(nik.provinsi)         # "DKI Jakarta"
print(nik.kabkota)          # "Kota Jakarta Selatan"
print(nik.kecamatan)        # "Kebayoran Baru"
print(nik.tanggal_lahir)    # 17
print(nik.bulan_lahir)      # 8
print(nik.tahun_lahir)      # 45
print(nik.jenis_kelamin)    # "Laki - laki"
print(nik.kode_unik)        # "0001"

# Modern attributes
print(nik.province)         # "DKI Jakarta"
print(nik.regency)          # "Kota Jakarta Selatan"
print(nik.district)         # "Kebayoran Baru"
print(nik.province_code)    # "31"
print(nik.regency_code)     # "74"
print(nik.district_code)    # "07"
print(nik.gender)           # "male"
print(nik.birth_year)       # 1945
print(nik.birth_date)       # datetime.date(1945, 8, 17)
print(nik.birth_date_string)# "1945-08-17"
print(nik.serial_number)    # "0001"

Safe Parsing & Dictionary Export

from nik_lookup import try_parse, is_valid

# Safe validation without exceptions
if is_valid("3174071708450001"):
    print("NIK is valid")

parsed = try_parse("invalid")
# parsed is None

# Export to dictionary
data = nik.to_dict()
print(data["birth_date"])  # "1945-08-17"

Error Handling

Both implementations provide typed exceptions inheriting from standard error bases:

Exception (JS / TS) Exception (Python) Trigger Condition
NikTypeError NikTypeError Input is not a string (TypeError)
InvalidNikLengthError InvalidNikLengthError Input length is not exactly 16 characters
InvalidNikFormatError InvalidNikFormatError Input contains non-numeric characters
InvalidNikDateError InvalidNikDateError Invalid calendar date, invalid month, or non-leap year Feb 29
UnknownAdministrativeCodeError UnknownAdministrativeCodeError Province, regency, or district code not in database

All custom exceptions inherit from NikError (Error in JS, ValueError in Python).


Testing

Both packages include zero-dependency test suites:

# Run Node.js test suite (node:test)
npm test

# Run Python test suite (unittest)
python3 -m unittest discover -s test -p "test_*.py"

License

MIT © Faiz A

Metadata

Release files for nik-lookup 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nik-lookup 1.0.0
File Size Uploaded
nik_lookup-1.0.0.tar.gz 9.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nik-lookup 1.0.0
File Interpreter ABI Platform
nik_lookup-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 18.5 kB

Release files / nik_lookup-1.0.0.tar.gz

Download URL nik_lookup-1.0.0.tar.gz
Size 9.8 kB
Tags Source
SHA-256 checksum
How to use checksums
673cab592e111d9167d46b7e6a0a2698cd5d3859f63052dcd4e8ab272d568f52
BLAKE2b-256 checksum
How to use checksums
3f65c618304f5e7ee7c87a06697f54165f779fa2b8a836470243346fe045ef4b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / nik_lookup-1.0.0-py3-none-any.whl

Download URL nik_lookup-1.0.0-py3-none-any.whl
Size 8.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b8acd302e479ef81c1d44e923baf4be411121dc2b642e056f57cb75eaec6e1a2
BLAKE2b-256 checksum
How to use checksums
df43db520ae4660afe70c8c3930493e4300146ca1b5fd6875af0e432a728ae84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page