geographicol
Normalize Colombian addresses into one canonical, structured form. Python 3.10+, zero dependencies.
| Input | Canonical (catastral, default) |
dian style |
|---|---|---|
Cra 45 No 12 30 Loc 3 |
KR 45 12 30 LC 3 |
CR 45 12 30 LC 3 |
cl. 26 nº 13-19 |
CL 26 13 19 |
CL 26 13 19 |
Av. Cra 68 #22 - 47 |
AK 68 22 47 |
AK 68 22 47 |
calle 38 a bis sur # 3A-18 este |
CL 38A BIS SUR 3A 18 ESTE |
CL 38A BIS SUR 3A 18 ESTE |
KR45#12-30 |
KR 45 12 30 |
CR 45 12 30 |
Cll 147 No 7 70 To 2 Ap 501 |
CL 147 7 70 TO 2 APTO 501 |
CL 147 7 70 TO 2 AP 501 |
Kr 43A # 1-50 Ed San Fernando Of 801 |
KR 43A 1 50 ED SAN FERNANDO OF 801 |
CR 43A 1 50 ED SAN FERNANDO OF 801 |
Calle 8 # 530 |
CL 8 5 30, confidence 0.8, warning AMBIGUOUS_PLATE |
CL 8 5 30 |
Install
pip install geographicol
Usage
from geographicol import is_valid, normalize, parse
normalize("Cra 7 # 45-12 Torre 2 Apto 501") # "KR 7 45 12 TO 2 APTO 501"
normalize("Cra 7 # 45-12 Torre 2 Apto 501", style="dian") # "CR 7 45 12 TO 2 AP 501"
is_valid("Calle 45") # False: no cross street
Styles
style |
Output | Use it for |
|---|---|---|
"catastral" (default) |
Compact cadastral codes: KR 7 45 12 TO 2 APTO 501 |
Storage, matching, a canonical key |
"igac" |
IGAC's 2024 cadastral manual: Carrera 7 45 12 TO 2 AP 501 |
Cadastre and municipal systems |
"dian" |
DIAN's table: CR 7 45 12 TO 2 AP 501 |
RUT, tax forms, accounting and ERP software |
"readable" |
Full words: Carrera 7 # 45-12, Torre 2, Apartamento 501 |
Showing addresses to people |
Every style accepts codes from all three tables as input. strict=True doubles every confidence penalty.
Named streets are supported: Avenida Boyacá # 12-30 gives street_name "BOYACÁ" and the canonical string AV BOYACÁ 12 30.
ParsedAddress
parse("Cra 7 # 45-12 Torre 2 Apto 501, Bogotá")
# ParsedAddress(
# street_type="KR", street_number=7, street_name=None, street_letter=None,
# street_quadrant=None,
# cross_number=45, cross_letter=None, cross_quadrant=None, plate_number=12,
# complements=[
# Complement(type="TORRE", code="TO", value="2"),
# Complement(type="APARTAMENTO", code="APTO", value="501"),
# ],
# locality="Bogotá", department=None,
# canonical="KR 7 45 12 TO 2 APTO 501",
# normalized="Carrera 7 # 45-12, Torre 2, Apartamento 501",
# confidence=1.0,
# warnings=["LOCALITY_UNVERIFIED"],
# raw="Cra 7 # 45-12 Torre 2 Apto 501, Bogotá",
# )
ParsedAddress is a dataclass, so dataclasses.asdict() turns it into a plain dict. parse never raises. When it can't make sense of the input, it says so through confidence (0 to 1) and machine-readable warnings instead of guessing silently. The full rules, codes and warning list are in docs/nomenclature.md.
What this library does NOT do
It normalizes the syntax of an address, offline, from the string alone. It does not:
- Geocode: no coordinates, no maps.
- Validate against real addresses:
KR 999 999 99parses fine even though it doesn't exist. - Look up cities or neighbourhoods:
localityanddepartmentare captured as written and never checked (warningLOCALITY_UNVERIFIED). - Fix typos or fuzzy-match:
Carerrais not recognized.
Those need data and infrastructure, and will be part of the geographicol API.
License
Metadata
Release files for geographicol 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| geographicol-0.2.0.tar.gz | 11.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| geographicol-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.5 kB
Release files / geographicol-0.2.0.tar.gz
| Download URL | geographicol-0.2.0.tar.gz |
|---|---|
| Size | 11.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6a68889c6ef3b3ae3396a6dd8e79c3c22f903de403be546af1eba76a0ca14333
|
|
BLAKE2b-256 checksum How to use checksums |
e3b6679ee00b3eae446d7662d17d0bbba8728aebb78cbc25e6be9219016402bc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.
Transparency logRelease files / geographicol-0.2.0-py3-none-any.whl
| Download URL | geographicol-0.2.0-py3-none-any.whl |
|---|---|
| Size | 13.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8a957bb3b95ca18408f931a3cd27859ec191ef76f8b8cc77f29ef160e697b07e
|
|
BLAKE2b-256 checksum How to use checksums |
485dd13374ee049f551b20b4aaf19f8313ff9c1f07ee271ab9331369680217ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.
Transparency log