Philippine Standard Geographic Code (PSGC) Python package with fuzzy search for barangays, municipalities, cities, provinces, and regions. Based on the official April 2026 PSGC masterlist. Offline access to all 42,011 barangays — no API calls or database needed.
pip install barangayfrom barangay import barangays, search_fuzzy
# Browse all 42,011 barangays
print(barangays) # <PSGC barangay database: 42010 records>
# Get a specific barangay
brgy = barangays.get(name="Tongmageng")
print(brgy.region) # Bangsamoro Autonomous Region In Muslim Mindanao (BARMM)
print(brgy.province) # Tawi-Tawi
print(brgy.psgc_id) # 1907005010
# Fuzzy search
for r in search_fuzzy("Tongmagen, Tawi-Tawi"):
print(f"{r.name} — score: {r.score}")| Feature | Description |
|---|---|
| 🔍 Fuzzy Search | Fast, customizable matching for unstandardized addresses |
| 🏛️ Hierarchy Traversal | Navigate parent, children, and ancestors of any admin division |
| 📊 Pandas Export | Direct to_frame() / to_dicts() export from database views |
| ✅ Address Validation | validate() and validate_many() for automated address checking |
| 📅 Historical Data | Access previous PSGC releases by date |
| 👩💻 Command Line Interface | Easy-to-use command line interface |
| 📚 Multiple Data Models | Choose the structure that fits your use case |
| 💾 Smart Caching | Automatic caching for faster subsequent loads |
| 🧩 Plug-in System | Enrich PSGC data with custom extensions via plug-ins |
pip install barangayRequirements: Python 3.13+
# Search for barangays
barangay search "Tongmageng, Tawi-Tawi"
# Export data
barangay export --model flat --format json --output data.json
# Show information
barangay info version
barangay info stats
# Work with historical data
barangay history list-dates
barangay history search-history "Tongmageng" --as-of "2025-07-08"
# Manage cache
barangay cache info
barangay cache clear
# Search with plugin enrichment
barangay search "Tongmageng" --plugin psgc-aux-data --format json
# Export with plugin enrichment
barangay export --model flat --plugin psgc-aux-data --format json --output enriched.json
# Batch operations
barangay batch batch-search queries.txt --limit 5 --output results.json
barangay batch validate barangay_names.txt📖 Full CLI Reference: quarto-docs/reference/cli.qmd 📖 Plugin Guide: quarto-docs/plugins/index.qmd
Pre-built views let you browse and search any admin level directly:
from barangay import regions, provinces, municipalities, cities, barangays
print(regions) # <PSGC region database: 18 records>
print(barangays) # <PSGC barangay database: 42010 records>
# Look up by name
brgy = barangays.get(name="Tongmageng")
print(brgy.province) # Tawi-Tawi
# Look up by PSGC ID
brgy = barangays.lookup("1907005010")
print(brgy) # <barangay: Tongmageng (1907005010)>
# Iterate over records
for region in regions:
print(region.name)Each record exposes its position in the administrative hierarchy:
brgy = barangays.get(name="Tongmageng")
print(brgy.region) # Bangsamoro Autonomous Region In Muslim Mindanao (BARMM)
print(brgy.province) # Tawi-Tawi
print(brgy.municipality) # Sitangkai
print(brgy.parent) # <municipality: Sitangkai (1907005000)>
print(brgy.ancestors) # [<municipality: Sitangkai ...>, <province: Tawi-Tawi ...>, ...]
manila = cities.get(name="City of Manila")
print(manila.children[:2]) # [<submunicipality: Tondo I/II ...>, <submunicipality: Binondo ...>]from barangay import search_fuzzy
results = search_fuzzy("Tongmagen, Tawi-Tawi", threshold=60.0, limit=5)
for r in results:
print(f"{r.name} ({r.psgc_id}) — score: {r.score}")
# Tongmageng (1907005010) — score: 100.0
# Tonggosong (1907004005) — score: 84.21
# ...from barangay import validate, validate_many
v = validate("Tongmageng, Tawi-Tawi")
print(v.valid, v.matched_name, v.score) # True Tongmageng 100.0
results = validate_many(["Tongmageng, Tawi-Tawi", "Nonexistent Place"])
for r in results:
print(f"{r.input!r} -> {'valid' if r.valid else 'invalid'}")from barangay import barangays
df = barangays.to_frame() # pd.DataFrame
data = barangays.to_dicts() # List[dict]from barangay import barangay, barangay_flat, barangay_extended
# Basic nested model (simple lookups)
ncr_cities = list(barangay["National Capital Region (NCR)"].keys())
# Extended model (recursive with metadata)
for region in barangay_extended.components:
print(f"{region.name} ({region.type})")
# Flat model (search & filtering)
brgy = [loc for loc in barangay_flat if loc.name == "Marayos"][0]Deprecated: The
search()function returns raw dicts and will be removed in 2027.X.X.X. Usesearch_fuzzy()instead for typed results.
from barangay import search
# Simple search
results = search("Tongmageng, Tawi-Tawi")
# Custom search
search(
"Tongmagen, Tawi-Tawi",
n=4, # Number of results
match_hooks=["municipality", "barangay"], # Match levels
threshold=70.0, # Minimum similarity (0-100)
)from barangay import sanitize_input, resolve_date, get_available_dates, use_version
# Sanitize strings
cleaned = sanitize_input("City of San Jose", exclude=["city of "])
# Result: "san jose"
# Switch to historical data
use_version("2025-07-08")
brgy = barangays.lookup("1907005010")
use_version(None) # back to latest📖 Full API Reference: quarto-docs/reference/index.qmd
Configure via environment variables:
export BARANGAY_AS_OF="2025-07-08" # Default dataset date
export BARANGAY_VERBOSE="true" # Enable verbose logging
export BARANGAY_CACHE_DIR="/custom/path" # Custom cache directoryOr set programmatically:
import barangay
barangay.as_of = "2025-07-08"Priority: Function parameter → Module attribute → Environment variable → Default (latest)
📖 Full Configuration Guide: quarto-docs/reference/configuration.qmd
Three data structures are available. Choose based on your use case:
| Model | Use Case | Structure |
|---|---|---|
barangay |
Simple lookups | Nested dictionary (region → city → barangay) |
barangay_extended |
Complex hierarchies | Recursive with rich metadata |
barangay_flat |
Search & filtering | Flat list with parent references |
Note: Pydantic models (barangay, barangay_extended, barangay_flat) are recommended. Dict versions (BARANGAY, BARANGAY_EXTENDED, BARANGAY_FLAT) are available for backward compatibility.
Deprecation:
BARANGAY,BARANGAY_EXTENDED,BARANGAY_FLATdict aliases will be removed in 2027.X.X.X. Use the Database API instead (e.g.from barangay import barangays; barangays.get(name="Tongmageng")).
Access previous PSGC releases by date. Data is automatically cached after first download.
Current Data Version: 2026-04-13 (April 13 2026 PSGC masterlist)
Available Dates:
- Current:
2026-04-13(bundled) - Historical:
2026-01-13,2025-07-08,2025-08-29,2025-10-13
import barangay
print(barangay.current) # '2026-04-13'
print(barangay.available_dates) # ['2026-04-13', '2026-01-13', '2025-08-29', '2025-10-13', '2025-07-08']Fuzzy search is optimized for speed:
| Configuration | Performance |
|---|---|
| Default (4 hooks) | ~80ms per search |
| Optimized (1–2 hooks) | ~10–25ms per search |
Use fewer match_hooks for better performance when appropriate.
- 📚 Full Documentation - Comprehensive guides and API reference
- 📩 PSGC Source - April 2026 masterlist
- 📦 PyPI Package
- 💻 GitHub Repository
- 📊 Data Repository - Raw PSGC datasets (JSON, YAML)
- 🐳 Barangay-API Docker - REST API companion
Contributions are welcome! See our Contributing Guide and Code of Conduct.
MIT © bendlikeabamboo