Skip to main content

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 99 parses fine even though it doesn't exist.
  • Look up cities or neighbourhoods: locality and department are captured as written and never checked (warning LOCALITY_UNVERIFIED).
  • Fix typos or fuzzy-match: Carerra is not recognized.

Those need data and infrastructure, and will be part of the geographicol API.

License

MIT

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)

Source distribution for geographicol 0.2.0
File Size Uploaded
geographicol-0.2.0.tar.gz 11.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for geographicol 0.2.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page