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

sri-lanka-police

v1.0.1

Published

API client & CLI for the Sri Lanka Police recruitment portal (joinus.police.lk). Browse provinces, districts, police divisions, divisional secretariats, and police stations.

Readme

Sri Lanka Police — Recruitment Portal API & CLI

npm version Node.js License: MIT

Unofficial Node.js API client & CLI for the Sri Lanka Police recruitment portal. Browse the full administrative hierarchy:

Province → District → Police Division / Divisional Secretariat → Police Station

Features

  • Interactive CLI — Browse the hierarchy step by step with live progress
  • Data Collector — Fetch all data at once across all provinces/districts
  • CSV / JSON Export — Save data directly to files for analysis
  • Programmatic API — Use the API in your Node.js projects
  • Dynamic Sessions — Automatically refreshes cookies & CSRF tokens (no hardcoded tokens)
  • Multi-language — Supports Sinhala, Tamil, and English responses
  • TypeScript friendly — Type definitions included

Installation

npm install sri-lanka-police

Global install (for CLI usage)

npm install -g sri-lanka-police

Now you can run sri-lanka-police or sl-police from anywhere.

CLI Usage — Interactive Wizard

npx sri-lanka-police

Navigate through the hierarchy step by step:

╔══════════════════════════════════════════════════════════════╗
║     Sri Lanka Police — Recruitment Portal CLI               ║
║     Province → District → Division / DivSec → Police       ║
║     S=Summary C=Divisions P=Police H=Hierarchy E=Export    ║
╚══════════════════════════════════════════════════════════════╝

Available Provinces:
  1. Western (බස්නාහිර)
  2. Central (මධ්‍යම)
  ...
  0. Exit
  ──
  S. Data Summary (📊)
  C. Collect All Divisions
  P. Collect All Police Stations
  H. Full Hierarchy Tree
  E. Export Data to File (CSV/JSON)

Interactive letter commands

| Key | Action | Description | |-----|--------|-------------| | S | Summary | Show counts for all entity types | | C | Divisions | Collect all 47 police divisions with progress bar | | P | Police | Collect all 608 police stations with progress bar | | H | Hierarchy | Show the complete nested tree | | E | Export | Interactive export menu (choose type & collect) |

After collecting data via C or P, you'll be asked: "Export this data to file? (y/N)"

CLI Usage — Direct Mode

Quick lookups

# Get districts in a province
npx sri-lanka-police 1

# Get divisions & divsecs for a district
npx sri-lanka-police 1 2

# Get divisions, divsecs & police stations
npx sri-lanka-police 1 2 13

Data collector commands

# Quick summary of all data
npx sri-lanka-police --summary
# → 9 provinces, 25 districts, 47 divisions, 338 divsecs, 608 police

# Collect all districts (flat list)
npx sri-lanka-police --collect districts

# Collect all police divisions (flat list with province/district context)
npx sri-lanka-police --collect divisions

# Collect all divisional secretariats
npx sri-lanka-police --collect divsecs

# Collect all police stations (makes ~200 API calls — shows progress)
npx sri-lanka-police --collect police

# Full hierarchy tree (nested by province > district)
npx sri-lanka-police --hierarchy

Export commands

# Export all districts to CSV (default format)
npx sri-lanka-police --export districts

# Export police stations to JSON
npx sri-lanka-police --export police --format json

# Export to a custom file path
npx sri-lanka-police --export divisions --format csv --output ./data/divisions.csv

# Export hierarchy (auto-switches to JSON — nested data)
npx sri-lanka-police --export hierarchy

# Export summary as JSON
npx sri-lanka-police --export summary --format json

Export auto-generates filenames with timestamps: ./sri-lanka-police-police-20260728-023015.csv

| Flag | Description | |------|-------------| | --format csv\|json | Output format (default: CSV for flat data, JSON for nested) | | --output <path> | Custom output file path |

Programmatic API

const police = require('sri-lanka-police');

// Fetch districts in province 1 (Western)
const districts = await police.getDistricts(1);

// Fetch police divisions for district 2
const divisions = await police.getDivisions(2);

// Fetch divisional secretariats for district 2
const divsecs = await police.getDivsecs(2);

// Fetch police stations for division 13
const stations = await police.getPolice(13);

API Reference

Individual endpoint functions

getDistricts(provinceId, lang?)

Fetches all districts in a province.

| Param | Type | Default | Description | |-------|------|---------|-------------| | provinceId | number \| string | required | Province ID (1–9) | | lang | string | 'sinhala' | Language: sinhala, tamil, or english |

Returns: Promise<Array<{ id: number, district: string, district_si?: string }>>

getDivisions(districtId, lang?)

Fetches police divisions in a district.

Returns: Promise<Array<{ id: number, division: string, division_si?: string }>>

getDivsecs(districtId, lang?)

Fetches divisional secretariats (DivSec) in a district.

Returns: Promise<Array<{ id: number, divsec: string, divsec_si?: string }>>

getPolice(divisionId, lang?)

Fetches police stations in a police division.

Returns: Promise<Array<{ id: number, police: string, police_si?: string }>>

Language support

// Fetch in Tamil
const districts = await police.getDistricts(1, 'tamil');

// Fetch in English
const districts = await police.getDistricts(1, 'english');

Data collector functions

These aggregate functions traverse the full hierarchy to collect all data at once. Progress callbacks are supported for long-running operations.

getAllDistricts()

Fetches ALL districts across all 9 provinces in parallel.

Returns: Promise<Array<{ id, district, district_si, provinceId, provinceName }>>

const allDistricts = await police.getAllDistricts();
console.log(allDistricts.length); // 25
// → [{ id: 1, district: 'කොළඹ', provinceId: 1, provinceName: 'Western (බස්නාහිර)' }, ...]

getAllDivisions(opts?)

Fetches ALL police divisions across every district. Each record includes district & province context.

| Option | Type | Description | |--------|------|-------------| | onProgress | function | Callback ({ done, total, current }) for live progress |

Returns: Promise<Array<{ id, division, division_si, districtId, districtName, provinceId, provinceName }>>

const divisions = await police.getAllDivisions({
  onProgress: ({ done, total, current }) => console.log(`${done}/${total} ${current}`)
});
// → 47 divisions with full context

getAllDivsecs(opts?)

Fetches ALL divisional secretariats across every district.

Returns: 338 records with district & province context.

getAllPolice(opts?)

Fetches ALL police stations across every division. ⚠ Makes ~200 API calls.

Returns: 608 records with full hierarchy context (division, district, province names).

getFullHierarchy(opts?)

Fetches the COMPLETE administrative hierarchy as a nested tree.

const hierarchy = await police.getFullHierarchy();
// → [{
//   provinceId: 1,
//   provinceName: 'Western (බස්නාහිර)',
//   districts: [{
//     id: 1,
//     district: 'කොළඹ',
//     divisions: [{ id, division, police: [...] }],
//     divsecs: [{ id, divsec }]
//   }]
// }]

getSummary()

Quick statistical summary — counts for every entity type. Data is shared internally (no redundant API calls).

const summary = await police.getSummary();
// → { provinces: 9, districts: 25, divisions: 47, divsecs: 338, police: 608 }

startWizard()

Launches the interactive CLI wizard programmatically. Useful if you want to embed the CLI in your own tool.

const { startWizard } = require('sri-lanka-police');
await startWizard();

PROVINCES

A lookup object mapping province IDs to names.

console.log(police.PROVINCES[1]);
// → "Western (බස්නාහිර)"

Province IDs

| ID | Province | |----|----------| | 1 | Western (බස්නාහිර) | | 2 | Central (මධ්‍යම) | | 3 | Southern (දකුණු) | | 4 | Northern (උතුරු) | | 5 | Eastern (නැගෙනහිර) | | 6 | North Western (වයඹ) | | 7 | North Central (උතුරු මැද) | | 8 | Uva (ඌව) | | 9 | Sabaragamuwa (සබරගමුව) |

Technical Details

Dynamic Sessions

Cookies and CSRF tokens are no longer hardcoded. On first use, the package scrapes joinus.police.lk/home to obtain fresh credentials:

  • XSRF-TOKEN and laravel-session cookies are extracted from Set-Cookie headers
  • CSRF token is extracted from <meta name="csrf-token"> in the HTML
  • Sessions automatically refresh on HTTP 419 (CSRF token expired)

Caching

In-memory caches avoid re-fetching data during a session:

  • Districts are cached per province
  • Divisions are cached per district
  • Collector functions share data internally (e.g., getSummary() fetches districts once and reuses them)

Project Structure

sri-lanka-police/
├── bin/
│   └── sri-lanka-police.js   # CLI binary entry point
├── src/
│   ├── index.js              # Programmatic API (main entry)
│   ├── cli.js                # Interactive CLI wizard + collector commands
│   ├── collector.js          # Aggregate data-collector functions
│   ├── exporter.js           # CSV/JSON file export
│   ├── session.js            # Dynamic session scraper (cookies + CSRF)
│   ├── police-api.js         # Shared HTTP helper with auto-retry
│   ├── get-district.js       # Districts endpoint
│   ├── get-division.js       # Police divisions endpoint
│   ├── get-divsec.js         # Divisional secretariats endpoint
│   └── get-police.js         # Police stations endpoint
├── types/
│   └── index.d.ts            # TypeScript declarations
├── package.json
├── README.md
└── LICENSE

License

MIT © DEW Coders