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

@bzync/ph-address-intel

v0.1.8

Published

Headless Philippine address lookup library with PSGC hierarchy and ZIP code autofill

Readme

PH Address Intel

Framework-agnostic TypeScript library for Philippine address lookup, ZIP autofill, and hierarchical region → province → municipality → barangay selection.

npm version MIT License


Features

  • ZIP Autofill — Resolve a 4-digit ZIP code into region, province, municipality, and barangays.
  • Cascading Selection — Full PSGC hierarchy: getRegions → getProvinces → getMunicipalities → getBarangays
  • Full Path Resolution — Resolve any PSGC code upward through the hierarchy with getFullPath.
  • Free-Text Search — Search across all address levels with optional fuzzy matching and parent scoping.
  • Alias Resolution — Resolve region nicknames and abbreviations (e.g. "NCR", "CALABARZON") to PSGC codes.
  • Validation — Verify that address codes exist and form a consistent hierarchy.
  • Zero Runtime Dependencies — No API calls. Works offline and at the edge.
  • TypeScript First — Fully typed API with .d.ts support (CJS + ESM).
  • Official PSGC Data — Based on PSA PSGC Q4 2025. Covers 17 regions, 80 provinces, 42,000+ barangays.

Installation

npm install @bzync/ph-address-intel
yarn add @bzync/ph-address-intel
pnpm add @bzync/ph-address-intel
bun add @bzync/ph-address-intel

Quick Start

import {
  lookupByZip,
  getRegions,
  getProvinces,
  getMunicipalities,
  getBarangays,
  getFullPath,
  search,
  resolveAlias,
  validate,
} from '@bzync/ph-address-intel'

// ZIP autofill
const result = lookupByZip('4322')

// Hierarchical selection
const regions = getRegions()
const provinces = getProvinces('040000000')
const municipalities = getMunicipalities('045600000')
const barangays = getBarangays('045645000')

// Full path from any PSGC code
const path = getFullPath('045645001') // barangay → full chain

// Scoped search (municipalities within CALABARZON only)
const hits = search('San Jose', { types: ['municipality'], parentCode: '040000000' })

// Alias resolution
const ncr = resolveAlias('NCR')

// Validation
const check = validate({ regionCode: '040000000', provinceCode: '045600000' })

API Reference

lookupByZip(zip: string): ZipLookupResult | null

Resolves a 4-digit ZIP code to the full address hierarchy.

const result = lookupByZip('4322')

if (result) {
  console.log(result.region.name)       // "Region IV-A (CALABARZON)"
  console.log(result.province?.name)    // "Quezon"
  console.log(result.municipality.name) // "Sariaya"
  console.log(result.barangays.length)  // number of barangays
}

Hierarchical getters

getRegions(): Region[]
getProvinces(regionCode: string): Province[]
getMunicipalities(provinceCode: string): Municipality[]
getBarangays(municipalityCode: string): Barangay[]

Returns all items at each level. Pass the parent PSGC code to get children.


Single-item lookups

getRegion(code: string): Region | undefined
getProvince(code: string): Province | undefined
getMunicipality(code: string): Municipality | undefined
getBarangay(code: string): Barangay | undefined

O(1) lookups by PSGC code.


getFullPath(code: string): FullPath | null

Resolves any PSGC code upward through the hierarchy and returns the complete address chain.

// From a barangay code
const path = getFullPath('045645001')
// → { region, province, municipality, barangay }

// From a municipality code
const path = getFullPath('045645000')
// → { region, province, municipality, barangay: null }

// NCR municipality (no province)
const path = getFullPath('133900000')
// → { region, province: null, municipality, barangay: null }

// Unknown code
getFullPath('999999999') // → null

Accepts codes at any level — region, province, municipality, or barangay. Levels below the given code are null.


search(query: string, options?: SearchOptions): SearchResult[]

Searches across all address levels. Supports substring matching (default) and fuzzy matching, with optional scoping to a parent region, province, or municipality.

// Substring search
search('Manila')

// Fuzzy search with options
search('Mandaluyong', { fuzzy: true, limit: 5, types: ['municipality'] })

// Scoped to a region (useful for cascading dropdowns)
search('San Jose', { types: ['municipality'], parentCode: '040000000' })

// Scoped to a municipality
search('Antipolo', { types: ['barangay'], parentCode: '045645000' })

SearchOptions

| Option | Type | Default | Description | |--------------|------------------------------------------------------------------|---------|------------------------------------------------------| | fuzzy | boolean | false | Enable Dice's bigram fuzzy matching | | limit | number | — | Max results to return | | types | Array<'region' \| 'province' \| 'municipality' \| 'barangay'> | all | Restrict search to specific levels | | parentCode | string | — | Scope results to children of a region, province, or municipality |

Results are sorted by score (descending) when fuzzy: true. When parentCode is set, regions are excluded from results (the parent context is already known).


resolveAlias(alias: string): SearchResult | null

Resolves a common region nickname, abbreviation, or number to a SearchResult. Returns null if not recognized.

resolveAlias('NCR')         // → { type: 'region', code: '130000000', name: '...' }
resolveAlias('Region IV-A') // → { type: 'region', code: '040000000', name: '...' }
resolveAlias('BARMM')       // → { type: 'region', code: '150000000', name: '...' }
resolveAlias('unknown')     // → null

Recognized aliases include region numbers (Region 113), Roman numerals (Region IXIII), official names, and common shorthands (NCR, CAR, CALABARZON, MIMAROPA, CARAGA, etc.).


validate(input: ValidationInput): ValidationResult

Validates that the provided PSGC codes exist and form a consistent hierarchy. Only fields that are provided are validated — partial inputs are fine.

validate({ regionCode: '040000000', provinceCode: '045600000' })
// → { valid: true, errors: [] }

validate({ regionCode: '040000000', provinceCode: '010100000' })
// → { valid: false, errors: ['Province "Ilocos Norte" does not belong to region "040000000"'] }

TypeScript Types

interface Region {
  code: string
  name: string
}

interface Province {
  code: string
  name: string
  regionCode: string
}

interface Municipality {
  code: string
  name: string
  regionCode: string
  provinceCode: string | null
  isCity: boolean
  zipCodes: string[]
}

interface Barangay {
  code: string
  name: string
  municipalityCode: string
}

interface ZipLookupResult {
  zip: string
  region: Region
  province: Province | null
  municipality: Municipality
  barangays: Barangay[]
}

interface SearchResult {
  type: 'region' | 'province' | 'municipality' | 'barangay'
  code: string
  name: string
  score?: number
  regionCode?: string
  provinceCode?: string | null
  municipalityCode?: string
}

interface FullPath {
  region: Region
  province: Province | null
  municipality: Municipality | null
  barangay: Barangay | null
}

interface SearchOptions {
  fuzzy?: boolean
  limit?: number
  types?: Array<'region' | 'province' | 'municipality' | 'barangay'>
  parentCode?: string
}

interface ValidationInput {
  regionCode?: string
  provinceCode?: string
  municipalityCode?: string
  barangayCode?: string
}

interface ValidationResult {
  valid: boolean
  errors: string[]
}

PSGC Code Structure

RRPPMMMBBB

| Part | Meaning | |------|--------------| | RR | Region | | PP | Province | | MMM | Municipality | | BBB | Barangay |

Example:

040000000  → Region IV-A (CALABARZON)
045600000  → Quezon
045645000  → Sariaya
045645001  → Barangay Antipolo

Notes

  • NCR has no provincesprovince is null in ZIP lookup results.
  • ZIP dataset contains ~958 mappings; some barangays share ZIP codes.
  • BARMM barangay data may be incomplete (PSGC limitation).

License

MIT License © 2026


Support

Star the repo if this helped you: https://github.com/bzync/ph-address-intel