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

@olism/bd-geo

v0.1.8

Published

Bangladesh geographical data and utilities

Downloads

562

Readme

@olism/bd-geo

Bangladesh geographical data and utilities for JavaScript and TypeScript.

npm version npm downloads License

[!IMPORTANT] Always use the latest version of @olism/bd-geo.

This package is actively maintained and geographical data is continuously being improved and expanded. New releases may include updated geographical data, additional locations, corrections, and API improvements.

Check the latest version on npm before installing or upgrading.

@olism/bd-geo provides structured geographical data for Bangladesh, including:

  • Divisions
  • Districts
  • Upazilas / Thanas
  • Unions
  • Wards
  • Villages

The package is designed for applications such as:

  • Address forms
  • Location selectors
  • Delivery systems
  • E-commerce applications
  • Real-estate platforms
  • Job platforms
  • User profiles
  • Registration forms
  • Location filters
  • Bangladesh-focused maps
  • Database seed data

Installation

npm

npm install @olism/bd-geo

Yarn

yarn add @olism/bd-geo

pnpm

pnpm add @olism/bd-geo

Geography Hierarchy

The geographical structure provided by the package is:

Division
   │
   └── District
          │
          └── Upazila / Thana
                    │
                    └── Area
                         ├── Union
                         │     └── Village
                         │
                         └── Ward

Important

  • Upazila and Thana are represented by the same geographical level.
  • Area can be either a union or a ward.
  • A Village belongs to an Area whose type is union.
  • Villages do not belong directly to wards.

Quick Start

Import the functions you need:

import {
  getDivisions,
  getDistricts,
  getUpazilas,
  getAreas,
  getVillages,
} from "@olism/bd-geo";

Then use them directly:

const divisions = getDivisions();
const districts = getDistricts();
const upazilas = getUpazilas();
const areas = getAreas();
const villages = getVillages();

API

getDivisions()

Returns all available Bangladesh divisions.

const divisions = getDivisions();

Return type:

Division[]

Example:

[
  {
    id: 1,
    name: "Barishal",
    nameBn: "বরিশাল",
  },
  {
    id: 2,
    name: "Chattogram",
    nameBn: "চট্টগ্রাম",
  },
];

getDistricts()

Returns all available Bangladesh districts.

const districts = getDistricts();

Return type:

District[]

Example:

[
  {
    id: 1,
    name: "Dhaka",
    nameBn: "ঢাকা",
    divisionId: 3,
  },
];

getUpazilas()

Returns all available upazilas.

const upazilas = getUpazilas();

Return type:

Upazila[]

Example:

[
  {
    id: 1,
    name: "Mirpur",
    nameBn: "মিরপুর",
    districtId: 1,
    type: "thana",
  },
];

getThanas()

[!WARNING] getThanas() is deprecated.

Use getUpazilas() for new applications.

const thanas = getThanas();

It returns the same data as:

getUpazilas();

This function is kept for backward compatibility.

Recommended

const upazilas = getUpazilas();

Legacy

const thanas = getThanas();

getAreas()

Returns all available areas.

An area can be either:

"union";

or:

"ward";

Example:

const areas = getAreas();

Return type:

Area[]

Example:

[
  {
    id: 1,
    name: "Mirpur-1",
    nameBn: "মিরপুর-১",
    upazilaId: 1,
    type: "ward",
  },
];

getVillages()

Returns all available villages.

const villages = getVillages();

Return type:

Village[]

Example:

[
  {
    id: 1,
    name: "Example Village",
    nameBn: "উদাহরণ গ্রাম",
    areaId: 10,
  },
];

A village's areaId references an area where:

area.type === "union";

TypeScript Types

The package exports TypeScript types for all geographical levels.

Division

export interface Division {
  id: number;
  name: string;
  nameBn: string;
  latitude?: number;
  longitude?: number;
}

District

export interface District {
  id: number;
  name: string;
  nameBn: string;
  divisionId: number;
  latitude?: number;
  longitude?: number;
}

Upazila

An upazila and thana are represented by the same geographical level.

export interface Upazila {
  id: number;
  name: string;
  nameBn: string;
  districtId: number;
  type?: "upazila" | "thana";
  latitude?: number;
  longitude?: number;
}

The optional type field can distinguish between:

"upazila";

and:

"thana";

Area

export type AreaType = "union" | "ward";

export interface Area {
  id: number;
  name: string;
  nameBn: string;
  upazilaId: number;
  type: AreaType;
  latitude?: number;
  longitude?: number;
}

Village

export interface Village {
  id: number;
  name: string;
  nameBn: string;
  areaId: number;
  latitude?: number;
  longitude?: number;
}

A village must reference an Area whose type is union.


Relationship IDs

Each geographical level references its parent.

District.divisionId
        ↓
Division.id
Upazila.districtId
        ↓
District.id
Area.upazilaId
        ↓
Upazila.id
Village.areaId
        ↓
Area.id

Example

Find the division of a district:

const districts = getDistricts();
const divisions = getDivisions();

const district = districts.find((district) => district.id === 1);

const division = divisions.find(
  (division) => division.id === district?.divisionId,
);

Cascading Address Selector

The package can easily be used to create cascading location selectors.

import {
  getDivisions,
  getDistricts,
  getUpazilas,
  getAreas,
  getVillages,
} from "@olism/bd-geo";

const divisions = getDivisions();

const districts = getDistricts().filter(
  (district) => district.divisionId === selectedDivisionId,
);

const upazilas = getUpazilas().filter(
  (upazila) => upazila.districtId === selectedDistrictId,
);

const areas = getAreas().filter((area) => area.upazilaId === selectedUpazilaId);

const villages = getVillages().filter(
  (village) => village.areaId === selectedAreaId,
);

This gives you a hierarchy:

Division
   ↓
District
   ↓
Upazila
   ↓
Area
   ↓
Village

React Example

import { useState } from "react";

import {
  getDivisions,
  getDistricts,
  getUpazilas,
  getAreas,
  getVillages,
} from "@olism/bd-geo";

export default function AddressForm() {
  const [divisionId, setDivisionId] = useState<number>();
  const [districtId, setDistrictId] = useState<number>();
  const [upazilaId, setUpazilaId] = useState<number>();
  const [areaId, setAreaId] = useState<number>();

  const divisions = getDivisions();

  const districts = getDistricts().filter(
    (district) => district.divisionId === divisionId,
  );

  const upazilas = getUpazilas().filter(
    (upazila) => upazila.districtId === districtId,
  );

  const areas = getAreas().filter((area) => area.upazilaId === upazilaId);

  const villages = getVillages().filter((village) => village.areaId === areaId);

  return (
    <div>
      <select
        value={divisionId ?? ""}
        onChange={(event) => {
          setDivisionId(Number(event.target.value));
          setDistrictId(undefined);
          setUpazilaId(undefined);
          setAreaId(undefined);
        }}
      >
        <option value="">Select Division</option>

        {divisions.map((division) => (
          <option key={division.id} value={division.id}>
            {division.name}
          </option>
        ))}
      </select>

      <select
        value={districtId ?? ""}
        onChange={(event) => {
          setDistrictId(Number(event.target.value));
          setUpazilaId(undefined);
          setAreaId(undefined);
        }}
      >
        <option value="">Select District</option>

        {districts.map((district) => (
          <option key={district.id} value={district.id}>
            {district.name}
          </option>
        ))}
      </select>

      <select
        value={upazilaId ?? ""}
        onChange={(event) => {
          setUpazilaId(Number(event.target.value));
          setAreaId(undefined);
        }}
      >
        <option value="">Select Upazila / Thana</option>

        {upazilas.map((upazila) => (
          <option key={upazila.id} value={upazila.id}>
            {upazila.name}
          </option>
        ))}
      </select>

      <select
        value={areaId ?? ""}
        onChange={(event) => {
          setAreaId(Number(event.target.value));
        }}
      >
        <option value="">Select Area</option>

        {areas.map((area) => (
          <option key={area.id} value={area.id}>
            {area.name}
          </option>
        ))}
      </select>

      <select>
        <option value="">Select Village</option>

        {villages.map((village) => (
          <option key={village.id} value={village.id}>
            {village.name}
          </option>
        ))}
      </select>
    </div>
  );
}

Bangla Names

Every geographical entity contains both English and Bangla names.

Example:

{
  id: 10,
  name: "Dhaka",
  nameBn: "ঢাকা",
}

Use the English name:

<span>{division.name}</span>

Or the Bangla name:

<span>{division.nameBn}</span>

This makes the package suitable for applications with both English and Bangla interfaces.


Filtering by Parent

Districts by Division

const districts = getDistricts().filter(
  (district) => district.divisionId === divisionId,
);

Upazilas by District

const upazilas = getUpazilas().filter(
  (upazila) => upazila.districtId === districtId,
);

Areas by Upazila

const areas = getAreas().filter((area) => area.upazilaId === upazilaId);

Villages by Area

const villages = getVillages().filter((village) => village.areaId === areaId);

Filtering Unions and Wards

Because Area contains a type field, you can easily separate unions and wards.

Get all unions

const unions = getAreas().filter((area) => area.type === "union");

Get all wards

const wards = getAreas().filter((area) => area.type === "ward");

Get unions in an Upazila

const unions = getAreas().filter(
  (area) => area.upazilaId === selectedUpazilaId && area.type === "union",
);

Get wards in an Upazila

const wards = getAreas().filter(
  (area) => area.upazilaId === selectedUpazilaId && area.type === "ward",
);

Village Relationship

Villages are linked to areas.

Village
   │
   └── areaId
          │
          ↓
        Area
          │
          └── type: "union"

Example:

const areas = getAreas();
const villages = getVillages();

const village = villages.find((village) => village.id === 1);

const area = areas.find((area) => area.id === village?.areaId);

You can verify that the area is a union:

if (area?.type === "union") {
  console.log("This village belongs to a union.");
}

Using the Package as Database Seed Data

@olism/bd-geo can be used as geographical seed data for applications using:

  • Prisma
  • TypeORM
  • Sequelize
  • Drizzle
  • NestJS
  • Next.js
  • Express.js
  • Other SQL/NoSQL database systems

The package provides plain JavaScript/TypeScript data, allowing you to transform it into your own database schema.


Recommended Database Structure

A relational database can use the following structure:

divisions
    │
    └── districts
          │
          └── upazilas
                │
                └── areas
                      │
                      ├── unions
                      │     └── villages
                      │
                      └── wards

Example tables:

divisions

├── id
├── name
├── nameBn
├── latitude
└── longitude


districts

├── id
├── name
├── nameBn
├── divisionId
├── latitude
└── longitude


upazilas

├── id
├── name
├── nameBn
├── districtId
├── type
├── latitude
└── longitude


areas

├── id
├── name
├── nameBn
├── upazilaId
├── type
├── latitude
└── longitude


villages

├── id
├── name
├── nameBn
├── areaId
├── latitude
└── longitude

Prisma

Install:

npm install @olism/bd-geo

Example prisma/seed.ts:

import { PrismaClient } from "@prisma/client";

import {
  getDivisions,
  getDistricts,
  getUpazilas,
  getAreas,
  getVillages,
} from "@olism/bd-geo";

const prisma = new PrismaClient();

async function main() {
  console.log("Seeding Bangladesh geographical data...");

  await prisma.division.createMany({
    data: getDivisions(),
  });

  await prisma.district.createMany({
    data: getDistricts(),
  });

  await prisma.upazila.createMany({
    data: getUpazilas(),
  });

  await prisma.area.createMany({
    data: getAreas(),
  });

  await prisma.village.createMany({
    data: getVillages(),
  });

  console.log("Bangladesh geographical data seeded successfully.");
}

main()
  .catch((error) => {
    console.error(error);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });

Make sure your Prisma model field names match the data provided by the package.


NestJS + TypeORM

Example seed:

import { DataSource } from "typeorm";

import {
  getDivisions,
  getDistricts,
  getUpazilas,
  getAreas,
  getVillages,
} from "@olism/bd-geo";

import { Division } from "./entities/division.entity";
import { District } from "./entities/district.entity";
import { Upazila } from "./entities/upazila.entity";
import { Area } from "./entities/area.entity";
import { Village } from "./entities/village.entity";

export async function seed(dataSource: DataSource) {
  const divisionRepository = dataSource.getRepository(Division);

  const districtRepository = dataSource.getRepository(District);

  const upazilaRepository = dataSource.getRepository(Upazila);

  const areaRepository = dataSource.getRepository(Area);

  const villageRepository = dataSource.getRepository(Village);

  await divisionRepository.save(getDivisions());

  await districtRepository.save(getDistricts());

  await upazilaRepository.save(getUpazilas());

  await areaRepository.save(getAreas());

  await villageRepository.save(getVillages());
}

Express.js + Sequelize

The package works independently of your backend framework.

Example:

import {
  getDivisions,
  getDistricts,
  getUpazilas,
  getAreas,
  getVillages,
} from "@olism/bd-geo";

import { Division } from "./models/division";
import { District } from "./models/district";
import { Upazila } from "./models/upazila";
import { Area } from "./models/area";
import { Village } from "./models/village";

export async function seedDatabase() {
  await Division.bulkCreate(getDivisions());

  await District.bulkCreate(getDistricts());

  await Upazila.bulkCreate(getUpazilas());

  await Area.bulkCreate(getAreas());

  await Village.bulkCreate(getVillages());
}

Next.js + Prisma

You can use the same Prisma seed approach in a Next.js application.

Create:

prisma/
└── seed.ts

Then use:

import { PrismaClient } from "@prisma/client";

import {
  getDivisions,
  getDistricts,
  getUpazilas,
  getAreas,
  getVillages,
} from "@olism/bd-geo";

const prisma = new PrismaClient();

async function main() {
  console.log("Seeding Bangladesh geographical data...");

  await prisma.division.createMany({
    data: getDivisions(),
  });

  await prisma.district.createMany({
    data: getDistricts(),
  });

  await prisma.upazila.createMany({
    data: getUpazilas(),
  });

  await prisma.area.createMany({
    data: getAreas(),
  });

  await prisma.village.createMany({
    data: getVillages(),
  });

  console.log("Bangladesh geographical data seeded successfully.");
}

main()
  .catch((error) => {
    console.error(error);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });

Important: Preserve Parent-Child Relationships

When inserting geographical data into a relational database, insert the records in hierarchical order:

1. Divisions
       ↓
2. Districts
       ↓
3. Upazilas
       ↓
4. Areas
       ↓
5. Villages

This is especially important when your database uses foreign-key constraints.

For example:

await prisma.division.createMany({
  data: getDivisions(),
});

await prisma.district.createMany({
  data: getDistricts(),
});

await prisma.upazila.createMany({
  data: getUpazilas(),
});

await prisma.area.createMany({
  data: getAreas(),
});

await prisma.village.createMany({
  data: getVillages(),
});

The IDs provided by @olism/bd-geo allow parent-child relationships to remain consistent.


Using Only Specific Levels

You don't need to use the entire dataset.

For example, if your application only needs divisions and districts:

import { getDivisions, getDistricts } from "@olism/bd-geo";

const divisions = getDivisions();
const districts = getDistricts();

Only upazilas:

import { getUpazilas } from "@olism/bd-geo";

const upazilas = getUpazilas();

Only areas:

import { getAreas } from "@olism/bd-geo";

const areas = getAreas();

Only villages:

import { getVillages } from "@olism/bd-geo";

const villages = getVillages();

Coordinates

Geographical records may contain optional coordinates:

{
  latitude?: number;
  longitude?: number;
}

Example:

{
  id: 10,
  name: "Dhaka",
  nameBn: "ঢাকা",
  latitude: 23.8103,
  longitude: 90.4125,
}

Coordinates can be useful for:

  • Maps
  • Location markers
  • Distance calculations
  • Delivery systems
  • Location-based search
  • Geographic visualizations

Coordinates should be treated as geographical reference data and verified before being used for high-precision applications.


Data Structure

The package source is organized approximately as:

src/
├── types.ts
├── geo.ts
├── index.ts
└── data/
    ├── divisions.json
    ├── districts.json
    ├── upazilas.json
    ├── areas.json
    └── villages.json

The JSON files contain the underlying geographical dataset.

The TypeScript API provides convenient access to that data.


Current API

getDivisions();

getDistricts();

getUpazilas();

getAreas();

getVillages();

For backward compatibility:

getThanas();

getThanas() is deprecated. New applications should use:

getUpazilas();

Data Accuracy

Geographical data is an important part of this package.

The dataset may evolve over time as geographical information is added, corrected, or improved.

Before using the data for critical production purposes, verify the relevant information against authoritative Bangladesh government sources where appropriate.

The project aims to maintain consistency in:

  • IDs
  • English names
  • Bangla names
  • Parent-child relationships
  • Administrative classifications
  • Area types
  • Geographic coordinates

If you discover incorrect information, please contribute a correction.


Contributing

Contributions are welcome.

You can contribute by:

  • Adding missing geographical data
  • Correcting English names
  • Correcting Bangla names
  • Correcting parent-child relationships
  • Adding missing villages
  • Correcting area types
  • Improving coordinates
  • Improving tests
  • Improving documentation
  • Reporting bugs

If you find an issue, please open an issue or submit a pull request in the project repository.


Development

Clone the repository:

git clone https://github.com/mohammad-oliullah/bd-geo.git

Enter the project:

cd bd-geo

Install dependencies:

npm install

Run tests:

npm test

Build the package:

npm run build

License

MIT License

Copyright (c) 2026 @olism/bd-geo contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.