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

bd-geo-address

v0.1.4

Published

Bangladesh geo address library — division/district/upazila/thana lookup, BBS geocode resolution, Bangla name support, postal codes, geolocation. Works on Node.js, React, Next.js, Vue, Angular, NestJS and all major JS frameworks.

Readme

bd-geo-address

Bangladesh address library — division/district/upazila/thana lookup, BBS geocode resolution, Bangla name support, postal codes, geolocation. Zero dependencies. Works on Node.js, React, React Native, Next.js, Vue, Angular, NestJS, Deno and Bun.

npm version npm downloads license TypeScript


Compatibility

React Native

Fully compatible — no setup required:

  • Zero Node.js APIs in library code (fs, path, process are only in build scripts, not shipped)
  • Zero DOM/browser APIs (window, document, navigator — none used)
  • Zero runtime dependencies
  • All functions synchronous — no async, no Promises, no side effects
  • JSON data import works natively in Metro bundler
  • Ships both CJS (index.js) and ESM (index.mjs) — Metro picks the right one automatically
npm install bd-geo-address

No additional Metro config or babel plugin needed.

TypeScript

Full TypeScript support out of the box:

  • strict: true throughout — no any, no @ts-ignore
  • Ships .d.ts and .d.mts declaration files for both CJS and ESM consumers
  • Declaration maps (.d.ts.map) for go-to-definition in VS Code and JetBrains IDEs
  • All public types explicitly exported — see TypeScript Types

Installation

npm install bd-geo-address
# or
yarn add bd-geo-address
# or
pnpm add bd-geo-address

Quick Start

Name-Based API

import { districtsOf, upazilasOf, isUpazila, isThana, DivisionName } from "bd-geo-address"

// All districts in Dhaka division
districtsOf(DivisionName.Dhaka)
// → ['Dhaka', 'Gazipur', 'Kishoreganj', 'Manikganj', 'Munshiganj', 'Narayanganj', ...]

// Upazilas of Tangail district
upazilasOf("Tangail")
// → [{ upazila: 'Tangail Sadar', upazilaBn: 'টাঙ্গাইল সদর', district: 'Tangail', ... }, ...]

// Correctly distinguishes upazilas from metropolitan thanas
isUpazila("Savar")   // → true
isUpazila("Gulshan") // → false  (Gulshan is a metropolitan thana)
isThana("Gulshan")   // → true

BBS Code API

import { resolveCode, toAddressString, toShortAddress } from "bd-geo-address"

// App stores BBS geocode in the database, resolves at runtime
const address = resolveCode("30262530")

address?.formatted.en
// → 'Kafrul, Dhaka North City Corporation, Dhaka, Dhaka Division'

address?.formatted.bn
// → 'কাফরুল, ঢাকা উত্তর সিটি কর্পোরেশন, ঢাকা, ঢাকা বিভাগ'

toShortAddress("30262530")  // → 'Kafrul, Dhaka'

CommonJS Usage

const { allDivision, districtsOf, resolveCode, DivisionName } = require("bd-geo-address")

console.log(allDivision())
// → ['Dhaka', 'Chattogram', 'Mymensingh', 'Khulna', 'Rajshahi', 'Rangpur', 'Sylhet', 'Barisal']

console.log(resolveCode("30262530").formatted.short)
// → 'Kafrul, Dhaka'

API Reference

Division

import {
  allDivision, allDivisionBn,
  divisionalDataOf, divisionalDataOfBn,
  isValidDivision, isValidDivisionBn,
} from "bd-geo-address"

allDivision()
// → ['Dhaka', 'Chattogram', 'Mymensingh', 'Khulna', 'Rajshahi', 'Rangpur', 'Sylhet', 'Barisal']

allDivisionBn()
// → ['ঢাকা', 'চট্টগ্রাম', 'ময়মনসিংহ', 'খুলনা', 'রাজশাহী', 'রংপুর', 'সিলেট', 'বরিশাল']

divisionalDataOf("Sylhet")
// → { districts: ['Sylhet', 'Sunamganj', 'Habiganj', 'Moulvibazar'], upazilas: [...] }

divisionalDataOfBn("ঢাকা")
// → { districts: [...], upazilas: [...] }

isValidDivision("Dhaka")       // → true
isValidDivision("InvalidName") // → false
isValidDivisionBn("ঢাকা")      // → true

District

import {
  allDistricts, allDistrictsBn,
  districtsOf, districtsOfBn,
  isValidDistrict, isValidDistrictBn,
  getDivisionOfDistrict, getDivisionOfDistrictBn,
} from "bd-geo-address"

allDistricts()            // → all 64 district names in English
allDistrictsBn()          // → all 64 district names in Bangla

districtsOf("Dhaka")      // → ['Dhaka', 'Gazipur', 'Kishoreganj', ...]
districtsOfBn("ঢাকা")     // → ['Dhaka', 'Gazipur', ...]

isValidDistrict("Tangail")  // → true
isValidDistrict("Savar")    // → false  (upazila, not a district)

getDivisionOfDistrict("Tangail")      // → 'Dhaka'
getDivisionOfDistrict("Cox's Bazar")  // → 'Chattogram'
getDivisionOfDistrictBn("টাঙ্গাইল")   // → 'Dhaka'

Upazila

import {
  allUpazila, allUpazilaNames, allUpazilaNamesBn,
  upazilasOf, upazilasOfBn,
  upazilaNamesOf, upazilaNamesOfBn,
  upazilasOfDivision, upazilasOfDivisionBn,
  upazilaNamesOfDivision, upazilaNamesOfDivisionBn,
  isUpazila, isUpazilabn,
  getUpazila, getUpazilabn,
  getDistrictOfUpazila, getDistrictOfUpazilabn,
  upazilaData,
} from "bd-geo-address"

allUpazila()                 // → all 595 upazila names

upazilasOf("Tangail")
// → [{ upazila: 'Tangail Sadar', upazilaBn: 'টাঙ্গাইল সদর', district: 'Tangail', ... }, ...]

upazilaNamesOf("Tangail")    // → ['Tangail Sadar', 'Basail', 'Bhuapur', ...]
upazilaNamesOfBn("টাঙ্গাইল") // → Bangla upazila names for Tangail

upazilasOfDivision("Sylhet") // → all upazilas in Sylhet division

isUpazila("Savar")           // → true
isUpazila("Gulshan")         // → false  (metropolitan thana)
isUpazilabn("সাভার")          // → true

getUpazila("Savar")
// → { upazila: 'Savar', upazilaBn: 'সাভার', district: 'Dhaka', division: 'Dhaka', ... }

// Disambiguate names that appear in multiple divisions:
getUpazila("Mohammadpur", "Khulna")
// → { upazila: 'Mohammadpur', district: 'Magura', division: 'Khulna', ... }

getDistrictOfUpazila("Savar")      // → 'Dhaka'
getDistrictOfUpazilabn("সাভার")    // → 'Dhaka'

upazilaData   // raw Upazila[] constant — all 595 objects

Thana

The 26 metropolitan police thanas across Dhaka (15), Chattogram (6), Khulna (3), and Rajshahi (2).

import {
  allThana, allThanaNames,
  thanasOf, thanasOfBn,
  thanaNamesOf, thanaNamesOfBn,
  isThana, isThanabn,
  getThana, getThanabn,
  thanaData,
} from "bd-geo-address"

allThana()                  // → all 26 Thana objects
allThanaNames()             // → ['Adabor', 'Badda', 'Banani', ..., 'Matihar']

thanasOf("Dhaka")           // → 15 Dhaka thana objects
thanaNamesOf("Dhaka")       // → ['Adabor', 'Badda', 'Banani', ...]
thanaNamesOfBn("ঢাকা")      // → Bangla thana names

// isThana without district = true if it is a thana in any city
isThana("Gulshan")               // → true
isThana("Kotwali", "Dhaka")      // → true   (disambiguate)
isThana("Kotwali", "Chattogram") // → true
isThanabn("গুলশান")              // → true

getThana("Gulshan")
// → { thana: 'Gulshan', thanaBn: 'গুলশান', district: 'Dhaka', division: 'Dhaka', type: 'thana' }

getThana("Kotwali", "Chattogram")
// → { thana: 'Kotwali', district: 'Chattogram', ... }

thanaData   // raw Thana[] constant — all 26 objects

| City | Thanas | |------------|--------| | Dhaka | 15 | | Chattogram | 6 | | Khulna | 3 | | Rajshahi | 2 |


Search

import { searchLocations } from "bd-geo-address"

searchLocations("pur")
// → matches any division, district, upazila, or thana containing "pur"
// → [{ name: 'Rangpur', type: 'division' }, { name: 'Mirpur', type: 'thana', district: 'Dhaka' }, ...]

searchLocations("সিলেট")
// → Bangla search works the same way

// Optional second parameter filters by level
searchLocations("pur", "upazila")   // only upazilas
searchLocations("pur", "district")  // only districts
searchLocations("pur", "thana")     // only thanas
searchLocations("pur", "division")  // only divisions

BBS Code Resolution

import { resolveCode, resolveCodes } from "bd-geo-address"

// Division-level code (2 digits)
resolveCode("30")
// {
//   fhirCode: '30',
//   division: { name: 'Dhaka', ... },
//   // district is undefined for division-level codes
//   formatted: { en: 'Dhaka Division', short: 'Dhaka Division', ... }
// }

// Upazila / thana / union code (8+ digits)
resolveCode("30262530")
// {
//   fhirCode: '30262530',  // BBS geocode
//   thana:    { code: '30262530', name: 'Kafrul', level: 'thana', ... },
//   city_corp:{ name: 'Dhaka North City Corporation', ... },
//   district: { name: 'Dhaka', ... },
//   division: { name: 'Dhaka', ... },
//   formatted: {
//     en:      'Kafrul, Dhaka North City Corporation, Dhaka, Dhaka Division',
//     bn:      'কাফরুল, ঢাকা উত্তর সিটি কর্পোরেশন, ঢাকা, ঢাকা বিভাগ',
//     short:   'Kafrul, Dhaka',
//     shortBn: 'কাফরুল, ঢাকা'
//   },
//   postal: { postalCode: '1216', postOfficeName: 'Kafrul', ... }
// }

resolveCodes(["30262530", "10040009", "INVALID"])
// → [BDAddress, BDAddress, null]

Address Formatting

import { toAddressString, toShortAddress, toCustomAddress } from "bd-geo-address"

toAddressString("30262530")
// → 'Kafrul, Dhaka North City Corporation, Dhaka, Dhaka Division'

toAddressString("30262530", "bn")
// → 'কাফরুল, ঢাকা উত্তর সিটি কর্পোরেশন, ঢাকা, ঢাকা বিভাগ'

toShortAddress("30262530")       // → 'Kafrul, Dhaka'
toShortAddress("30262530", "bn") // → 'কাফরুল, ঢাকা'

toCustomAddress("30262530", ["thana", "district", "division"])
// → 'Kafrul, Dhaka, Dhaka Division'

toCustomAddress("30262530", ["thana", "district"], "bn")
// → 'কাফরুল, ঢাকা'

Lookup by BBS Code

import { getByCode, findByName, findByNameBn, search, getAllByLevel } from "bd-geo-address"

getByCode("30")               // → { code: '30', name: 'Dhaka', level: 'division', ... }
getByCode("INVALID")          // → null

findByName("Dhaka")           // → [division, district, ...]
findByName("Dhaka", "district") // → [{ name: 'Dhaka', level: 'district', ... }]
findByNameBn("ঢাকা")          // → same but by Bangla name

search("Dhaka")               // → English first, then Bangla fallback

getAllByLevel("division")      // → all 8 division BDLocation objects
getAllByLevel("district")      // → all 64 district BDLocation objects
getAllByLevel("upazila")       // → all upazila BDLocation objects

Name → BBS Code (Dropdown Use Case)

getCodeByName is designed for cascade-dropdown flows (division → district → upazila → thana/union). Once the user makes their final selection, pass the selected name + level + the ancestor names already selected to get the single BBS code to store in your database.

import { getCodeByName } from "bd-geo-address"

// Unique name — no ancestors needed
getCodeByName("Savar", "upazila")
// → "302645"

// Ambiguous name — same upazila name exists in multiple districts
getCodeByName("Mohammadpur", "upazila")                          // → null (ambiguous)
getCodeByName("Mohammadpur", "upazila", { district: "Magura" }) // → BBS code for Magura's Mohammadpur
getCodeByName("Mohammadpur", "upazila", { division: "Khulna" }) // → same, via division

// Works for all levels
getCodeByName("Dhaka",   "division")                            // → "30"
getCodeByName("Barguna", "district")                            // → district BBS code
getCodeByName("Kafrul",        "thana",     { district: "Dhaka" })     // → "30262530"
getCodeByName("Amtali Paurasava", "paurasava")                         // → "1004000920"
getCodeByName("SomeUnion", "union", { district: "X", upazila: "Y" })

// Returns null when not found or still ambiguous after filtering

React example — saving the selected BBS code:

import { getCodeByName } from "bd-geo-address"

const handleUpazilaChange = (upazilaName: string) => {
  setUpazila(upazilaName)
  const code = getCodeByName(upazilaName, "upazila", { district, division })
  setBBSCode(code) // store this in your database
}

Hierarchy

import { getParent, getChildren, getAllDescendants, getHierarchy } from "bd-geo-address"

getParent("1004")              // → { code: '10', name: 'Barishal', level: 'division', ... }
getParent("10")                // → null  (divisions have no parent)

getChildren("10")              // → all direct children of Barishal division
getAllDescendants("10")        // → all locations under Barishal at any depth
getAllDescendants("10", "district")  // → only districts
getAllDescendants("10", "upazila")   // → only upazilas

getHierarchy("30262530")
// → BDAddress without the `formatted` field

Validation

import { isValidCode, isValidName, isValidNameBn, isChildOf, getLevel } from "bd-geo-address"

isValidCode("30262530")   // → true
isValidCode("INVALID")    // → false

isValidName("Dhaka")               // → true
isValidName("Dhaka", "division")   // → true
isValidName("Dhaka", "upazila")    // → false
isValidNameBn("ঢাকা", "division")  // → true

isChildOf("10040009", "10")        // → true  (in Barishal division)
isChildOf("10040009", "1004")      // → true  (in Barguna district)
isChildOf("10040009", "30")        // → false (not in Dhaka)

getLevel("10")        // → 'division'
getLevel("1004")      // → 'district'
getLevel("10040009")  // → 'upazila'
getLevel("INVALID")   // → null

Postal Codes

import {
  getByPostalCode, getPostalCode, getPostalCodeBn,
  getPostalCodesByArea, getFhirCodeFromPostal, resolvePostalCode,
} from "bd-geo-address"

getByPostalCode("8710")
// → { postalCode: '8710', postOfficeName: 'Amtali', upazilaName: 'Amtali', districtName: 'Barguna', ... }

getPostalCode("Amtali")          // → '8710'
getFhirCodeFromPostal("8710")    // → '10040009'  (Amtali upazila BBS code)

getPostalCodesByArea("Barguna", "district")  // → all postal entries in Barguna district
getPostalCodesByArea("Barisal", "division")  // → all postal entries in Barisal division

resolvePostalCode("8710")
// → full BDAddress for Amtali (same as resolveCode('10040009'))

Geolocation

Coordinate data requires running npm run build:coords with HDX shapefiles.

import { getCoordinates, getCoordinatesByName, getNearestLocation, getLocationsWithinRadius } from "bd-geo-address"

// By BBS code
getCoordinates("30")                  // → { lat: 23.8103, lng: 90.4125 }

// By name — level and ancestors optional, same disambiguation rules as getCodeByName
getCoordinatesByName("Savar", "upazila")
// → { lat: 23.8576, lng: 90.2659 }

getCoordinatesByName("Mohammadpur", "upazila", { district: "Magura" })
// → { lat, lng } for Mohammadpur in Magura district

getCoordinatesByName("Dhaka", "division")   // → Dhaka division centroid
getCoordinatesByName("Dhaka")               // → first Dhaka entry with coordinates

getNearestLocation(23.7, 90.4)             // → nearest BDLocation to the point
getNearestLocation(23.7, 90.4, "upazila")  // → nearest upazila
getLocationsWithinRadius(23.7, 90.4, 50)   // → all locations within 50 km

TypeScript Types

import type {
  DivisionName,     // enum
  DistrictName,     // string literal union of all 64 districts
  LocationLevel,    // 'division' | 'district' | 'city_corp' | 'municipality' | 'upazila' | 'thana' | 'union' | 'paurasava'
  Upazila,
  Thana,
  SearchResult,
  BDLocation,
  BDAddress,
  BDPostalEntry,
} from "bd-geo-address"

BDAddress — resolved BBS geocode result:

interface BDAddress {
  fhirCode:      string
  division:      BDLocation
  district?:     BDLocation   // absent for division-level codes
  city_corp?:    BDLocation
  municipality?: BDLocation
  upazila?:      BDLocation
  thana?:        BDLocation
  union?:        BDLocation
  paurasava?:    BDLocation
  formatted: { en: string; bn: string; short: string; shortBn: string }
  coordinates?: { lat: number; lng: number }
  postal?:      { postalCode: string; postOfficeName: string; postOfficeNameBn: string }
}

DivisionName enum — use for IDE autocomplete:

import { DivisionName } from "bd-geo-address"

DivisionName.Dhaka      // → 'Dhaka'
DivisionName.Chattogram // → 'Chattogram'
// Dhaka, Chattogram, Mymensingh, Khulna, Rajshahi, Rangpur, Sylhet, Barisal

Framework Examples

React — Cascade Location Picker

import { useState } from "react"
import { allDivision, districtsOf, upazilasOf } from "bd-geo-address"

export function LocationPicker({ onChange }) {
  const [division, setDivision] = useState("")
  const [district, setDistrict] = useState("")

  const districts = division ? districtsOf(division) : []
  const upazilas  = district ? upazilasOf(district) : []

  return (
    <div>
      <select onChange={e => { setDivision(e.target.value); setDistrict("") }}>
        <option value="">Division</option>
        {allDivision().map(d => <option key={d} value={d}>{d}</option>)}
      </select>
      <select onChange={e => setDistrict(e.target.value)} disabled={!division}>
        <option value="">District</option>
        {districts.map(d => <option key={d} value={d}>{d}</option>)}
      </select>
      <select onChange={e => onChange(e.target.value)} disabled={!district}>
        <option value="">Upazila</option>
        {upazilas.map(u => (
          <option key={u.upazila} value={u.upazila}>{u.upazilaBn} ({u.upazila})</option>
        ))}
      </select>
    </div>
  )
}

Next.js — Server Component

import { resolveCode } from "bd-geo-address"

export default async function UserPage({ params }) {
  const user = await fetchUser(params.id)
  const address = resolveCode(user.locationCode)

  return (
    <div>
      <p>{address?.formatted.en}</p>
      <p>{address?.formatted.bn}</p>
    </div>
  )
}

Vue 3

<template>
  <select v-model="selectedDivision">
    <option v-for="d in divisions" :key="d" :value="d">{{ d }}</option>
  </select>
  <select v-model="selectedDistrict">
    <option v-for="d in districts" :key="d" :value="d">{{ d }}</option>
  </select>
</template>

<script setup lang="ts">
import { ref, computed } from "vue"
import { allDivision, districtsOf } from "bd-geo-address"

const selectedDivision = ref("")
const divisions = allDivision()
const districts = computed(() =>
  selectedDivision.value ? districtsOf(selectedDivision.value) : []
)
</script>

Node.js / Express

import express from "express"
import { isValidCode, resolveCode, upazilasOf } from "bd-geo-address"

const app = express()

app.get("/address/:code", (req, res) => {
  if (!isValidCode(req.params.code)) return res.status(400).json({ error: "Invalid geocode" })
  res.json(resolveCode(req.params.code))
})

app.get("/upazilas/:district", (req, res) => {
  res.json(upazilasOf(req.params.district))
})

NestJS

import { Injectable, BadRequestException } from "@nestjs/common"
import { resolveCode, isValidCode, BDAddress } from "bd-geo-address"

@Injectable()
export class LocationService {
  resolve(bbsCode: string): BDAddress {
    if (!isValidCode(bbsCode)) throw new BadRequestException("Invalid BD BBS geocode")
    return resolveCode(bbsCode)!
  }
}

React Native

Works out of the box — no config needed.

import { useState } from "react"
import { View, Text } from "react-native"
import { Picker } from "@react-native-picker/picker"
import { allDivision, districtsOf, upazilasOf, getCodeByName } from "bd-geo-address"

export function LocationPicker({ onCode }: { onCode: (code: string) => void }) {
  const [division, setDivision] = useState("")
  const [district, setDistrict] = useState("")
  const [upazila, setUpazila] = useState("")

  const districts = division ? districtsOf(division) : []
  const upazilas  = district ? upazilasOf(district) : []

  const handleUpazila = (name: string) => {
    setUpazila(name)
    const code = getCodeByName(name, "upazila", { district, division })
    if (code) onCode(code) // BBS code ready to store in DB
  }

  return (
    <View>
      <Picker selectedValue={division} onValueChange={v => { setDivision(v); setDistrict(""); setUpazila("") }}>
        <Picker.Item label="Select Division" value="" />
        {allDivision().map(d => <Picker.Item key={d} label={d} value={d} />)}
      </Picker>

      <Picker selectedValue={district} onValueChange={v => { setDistrict(v); setUpazila("") }} enabled={!!division}>
        <Picker.Item label="Select District" value="" />
        {districts.map(d => <Picker.Item key={d} label={d} value={d} />)}
      </Picker>

      <Picker selectedValue={upazila} onValueChange={handleUpazila} enabled={!!district}>
        <Picker.Item label="Select Upazila" value="" />
        {upazilas.map(u => <Picker.Item key={u.upazila} label={`${u.upazilaBn} (${u.upazila})`} value={u.upazila} />)}
      </Picker>
    </View>
  )
}

Database Dumps

For PHP, Python, Java, Go, Ruby or any non-JS project, database dumps are included in the package.

| File | Format | |------|--------| | db/mysql/bangladesh-address.sql | MySQL 8.0+ | | db/postgresql/bangladesh-address.sql | PostgreSQL 13+ | | db/sqlite/bangladesh-address.db | SQLite 3 binary | | db/mongodb/bangladesh-address.json | MongoDB insertMany-ready |

Schema:

  • divisions — 8 rows (code, name, name_bn, lat, lng)
  • districts — 64 rows (code, name, name_bn, division_code, lat, lng)
  • locations — 1519 rows (all other BBS locations: city corps, upazilas, unions, etc.)
  • thanas — 26 metropolitan thanas
  • postal_codes — 1343 postal code entries

MySQL example:

mysql -u root -p mydb < node_modules/bd-geo-address/db/mysql/bangladesh-address.sql

PostgreSQL example:

psql -U postgres mydb < node_modules/bd-geo-address/db/postgresql/bangladesh-address.sql

SQLite example:

cp node_modules/bd-geo-address/db/sqlite/bangladesh-address.db ./my-app.db

MongoDB example:

const data = require("bd-geo-address/db/mongodb/bangladesh-address.json")
await db.collection("divisions").insertMany(data.divisions)
await db.collection("locations").insertMany(data.locations)

Data Coverage

| Level | Count | |-------|-------| | Divisions | 8 | | Districts | 64 | | City Corporations | 12 | | Upazilas | 595 | | Metropolitan Thanas | 26 | | Unions | 848 | | Postal codes | 1343 |


Data Sources & Credits


Contributing

See CONTRIBUTING.md for guidelines on fixing data, adding tests, or improving the API.


License

MIT