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

tz-locations

v1.0.2

Published

Complete Tanzania location data — regions, districts, wards, streets & postcodes

Readme

tz-locations

npm version License: MIT TypeScript

Complete Tanzania location data — 31 regions, 168 districts, 4,054 wards, 75,061 streets with postcodes.

Offline-first. Fully typed. Zero network dependency.

Why use this?

Every developer building for Tanzania ends up scraping address data, maintaining spreadsheets, or hardcoding locations. This package gives you the entire Tanzania postal hierarchy in a single npm install — no API calls, no network latency, works offline.

  • Complete coverage: Every region, district, ward, and street with official postcodes
  • TypeScript-first: Full type definitions for all entities
  • Zero dependencies: Just data and pure functions
  • Offline-first: Works without network — ideal for mobile and edge
  • Fast lookups: Lazy-built Map indexes for O(1) access by slug or postcode

Install

npm install tz-locations

Quick Start

import {
  getRegions,
  getDistrictsByRegion,
  getWardsByDistrict,
  getStreets,
  searchLocations,
  getByPostcode,
} from 'tz-locations';

// All 31 regions
const regions = getRegions();

// Districts in Dar es Salaam
const districts = getDistrictsByRegion('dar-es-salaam');

// Wards in Ilala district
const wards = getWardsByDistrict('dar-es-salaam', 'ilala');

// Streets in Buguruni ward
const streets = getStreets('dar-es-salaam', 'ilala', 'buguruni');

// Search by name
const results = searchLocations('buguruni', { type: 'ward', limit: 5 });

// Lookup by postcode
const location = getByPostcode('12102');

API Reference

| Function | Returns | Description | |----------|---------|-------------| | getRegions() | Region[] | All 31 regions | | getRegion(slug) | Region \| undefined | Single region by slug | | getDistricts(regionSlug?) | District[] | All districts or filtered by region | | getDistrictsByRegion(slug) | District[] | Districts in a region | | getDistrict(slug) | District \| undefined | Single district by slug | | getWards(regionSlug?, districtSlug?) | Ward[] | All wards or filtered | | getWardsByDistrict(region, district) | Ward[] | Wards in a district | | getWard(slug) | Ward \| undefined | Single ward by slug | | getStreets(region, district, ward) | Street[] | Streets in a ward | | getByPostcode(postcode) | PostcodeLookupResult | Lookup by 5-digit postcode | | searchLocations(query, options?) | Location[] | Search by name | | getStats() | object | Count of each entity type |

TypeScript Types

interface Region {
  name: string;
  slug: string;
}

interface District {
  name: string;
  slug: string;
  region_slug: string;
}

interface Ward {
  name: string;
  slug: string;
  district_slug: string;
  region_slug: string;
}

interface Street {
  name: string;
  postcode: string;
  ward_slug: string;
  district_slug: string;
  region_slug: string;
}

interface Location {
  type: 'region' | 'district' | 'ward' | 'street';
  name: string;
  slug?: string;
  postcode?: string;
  ward_slug?: string;
  district_slug?: string;
  region_slug?: string;
}

interface PostcodeLookupResult {
  ward: Ward | null;
  streets: Street[];
}

Real-World Examples

Cascading Address Select

import { getRegions, getDistrictsByRegion, getWardsByDistrict, getStreets } from 'tz-locations';

// Step 1: User picks a region
const regions = getRegions();
// → [{ name: "Dar es Salaam", slug: "dar-es-salaam" }, ...]

// Step 2: Load districts for selected region
const districts = getDistrictsByRegion('dar-es-salaam');
// → [{ name: "Ilala", slug: "ilala", region_slug: "dar-es-salaam" }, ...]

// Step 3: Load wards for selected district
const wards = getWardsByDistrict('dar-es-salaam', 'ilala');
// → [{ name: "Buguruni", slug: "buguruni", ... }, ...]

// Step 4: Load streets for selected ward
const streets = getStreets('dar-es-salaam', 'ilala', 'buguruni');
// → [{ name: "Malapa", postcode: "12102", ... }, ...]

Postcode Validation

import { getByPostcode } from 'tz-locations';

function validatePostcode(postcode: string): boolean {
  const result = getByPostcode(postcode);
  return result.streets.length > 0;
}

// Get full location from postcode
const location = getByPostcode('12102');
if (location.ward) {
  console.log(`${location.ward.name}, ${location.ward.district_slug}`);
  // → "Buguruni, ilala"
}

Search-as-you-type

import { searchLocations } from 'tz-locations';

function onSearchInput(query: string) {
  if (query.length < 2) return [];
  return searchLocations(query, { limit: 10 });
}

// Returns mixed results: regions, districts, wards, streets
const results = onSearchInput('kinu');
// → [{ type: "district", name: "Kinondoni", ... }, ...]

Compatibility

This package is ESM-only ("type": "module").

| Environment | Usage | |---|---| | Node.js 20.19+ / 22.12+ | import or require() both work | | Node.js 18–20.18 | Use import (or await import('tz-locations') for CJS) | | Bundlers (Vite, webpack, etc.) | Works out of the box | | Deno / Bun | Works out of the box |

Performance

All lookups use lazy-built Map indexes. The first call to a lookup function builds the index (fast — just iterating arrays), and subsequent calls are O(1). Data is loaded once from bundled JSON files.

REST API

Need server-side or cross-platform access? The same data is available as a REST API deployed on Cloudflare Workers with full-text search and autocomplete.

Data Source

Scraped from tanzaniapostcode.com and verified.

License

MIT