Offline postal-code / geocode lookup — O(1) & O(log N) indexed, TB/ZB scale ready
Project description
zipfinder
Upgraded from
bd-geocode-offline? See the migration guide below.
Complete offline GeoNames postal-code / geocode database for Python. Works 100 % offline no internet connection required.
Features
- 1.8 million records 121 countries, complete GeoNames dataset
- O(1) lookups hash-indexed, constant time regardless of dataset size
- O(log N) prefix search bisect-based, no full-table scans ever
- Spatial radius search geo-grid index, O(C + Klog K)
- TB / ZB scale optional SQLite mode for datasets that exceed RAM
- Zero dependencies Python standard library only
- Fully embedded all data ships inside the package
- Backward compatible old
bd-geocode-offlineimports still work
Installation
pip install zipfinder
To upgrade from the old package:
pip install zipfinder
pip uninstall bd-geocode-offline # optional cleanup
Quick Start
from zip_finder import lookup_zip, lookup_all_zips, search_zip, find_nearby_zips
# Exact lookup O(1)
record = lookup_zip("94107", country="US")
print(record["city"]) # San Francisco
print(record["latitude"]) # 37.7647
# Lookup without country returns first match across all countries
record = lookup_zip("94107")
# All countries sharing the same code O(1)
all_matches = lookup_all_zips("94107")
for r in all_matches:
print(r["country_code"], r["city"])
# Prefix search by zip or city O(log N + K)
results = search_zip("Lon", country="GB", limit=5)
for r in results:
print(r["postal_code"], r["city"])
# Nearby zip codes by coordinates O(C + Klog K)
nearby = find_nearby_zips(37.7749, -122.4194, radius_km=10, limit=5)
for r in nearby:
print(r["city"], r["distance_km"], "km")
API Reference
| Function | Description | Time Complexity |
|---|---|---|
lookup_zip(code, country=None) |
Single zip lookup, returns one record or None |
O(1) |
lookup_all_zips(code, country=None) |
All records for a zip across countries | O(1) |
search_zip(query, country=None, limit=10) |
Prefix search by zip or city name | O(log N + K) |
find_nearby_zips(lat, lon, radius_km=10, limit=10) |
Radius search by coordinates | O(C + Klog K) |
get_db_stats() |
Total records and country count | O(1) |
list_countries() |
Sorted list of all ISO-3166 country codes | O(1) |
get_database(use_sqlite=False) |
Access the raw database singleton |
Record format
Every returned dict contains:
{
"postal_code": "94107",
"city": "San Francisco",
"state": "California",
"state_code": "CA",
"country_code": "US",
"latitude": 37.7647,
"longitude": -122.4194,
"accuracy": 4
}
Results from find_nearby_zips also include a "distance_km" field.
Advanced Usage
Database statistics
from zip_finder import get_db_stats, list_countries
stats = get_db_stats()
print(f"Records : {stats['total_records']:,}") # 1,826,607
print(f"Countries: {stats['countries']}") # 121
countries = list_countries()
print(countries[:5]) # ['AD', 'AE', 'AI', 'AL', 'AR']
TB / ZB scale SQLite mode
For datasets that exceed available RAM:
from zip_finder import get_database
db = get_database(use_sqlite=True)
record = db.lookup_zip("94107", country="US")
Migrating from bd-geocode-offline
zipfinder 2.0.0 is a drop-in upgrade. Old function names still work as
deprecated aliases, so no code change is required immediately.
However, the new names are recommended:
| Old name (still works) | New name (recommended) |
|---|---|
get(code, country) |
lookup_zip(code, country) |
get_all(code) |
lookup_all_zips(code) |
search(query) |
search_zip(query) |
find_nearby(lat, lon) |
find_nearby_zips(lat, lon) |
get_stats() |
get_db_stats() |
get_countries() |
list_countries() |
# Install the new package
pip install zipfinder
# Old import path still works (backward-compatible alias)
from zip_finder import get
# New recommended API
from zip_finder import lookup_zip
Contributing
- Fork https://github.com/karthikbd/zipfinder
- Create a branch:
git checkout -b feature/my-feature - Run tests:
python -m pytest tests/ -v - Push and open a Pull Request
License
Previously published as bd-geocode-offline 1.0.0.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zipfinder-2.0.0.tar.gz.
File metadata
- Download URL: zipfinder-2.0.0.tar.gz
- Upload date:
- Size: 58.9 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d036738030872a5e2d0a918fd8f4c7d95b384d53953b3e291d500987c94ce1d9
|
|
| MD5 |
ae72adbd916406af48dafe76f52be8a7
|
|
| BLAKE2b-256 |
224c58e6debf90b499367aab268f9d28feecf18faf3b3cae89244049a25e05d0
|
File details
Details for the file zipfinder-2.0.0-py3-none-any.whl.
File metadata
- Download URL: zipfinder-2.0.0-py3-none-any.whl
- Upload date:
- Size: 58.9 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25ff13dbc1df4a1f88e4d8e201dfc365d5a2e4fab464d5796b320d517d14e185
|
|
| MD5 |
354d18a6eda152377d9a8c3d5d08e461
|
|
| BLAKE2b-256 |
a2b367df22bf2dd2fdf7012092b18dea4c68b4b3c02daf183c49817be2cd42c0
|