Philippine Standard Geographic Code (PSGC) Python package with fuzzy search for barangays, municipalities, cities, provinces, and regions. Based on the official July 2026 PSGC masterlist. Offline access to all 42,000+ barangays — no API calls or database needed.
pip install barangayfrom barangay import barangays, search_fuzzy
# Browse all 42,000+ 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-07-13 (July 13 2026 PSGC masterlist)
Available Dates:
- Current:
2026-07-13(bundled) - Historical: See barangay-data-repository
# Sample only, actual values might differ
import barangay
print(barangay.current) # '2026-07-13'
print(barangay.available_dates) # ['2026-07-13', '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