doorplate
Parse US addresses into components, with USPS Publication 28 and RESO output, a match key, a URL-safe slug, and diagnostics. A Rust library with Python bindings (PyO3, abi3 wheels for Python 3.10 and later); no runtime dependencies and no data to download.
This library formats and parses; it does not validate that an address exists or can receive mail.
Alpha release (0.5.1). Expect rough edges. The match key is versioned (
k4:) and will probably get new versions as the parser improves, so store the version prefix with your keys and plan to re-key.k4is new in 0.5.0 and has only been checked on the project's own data (37 million rows of public records), and ak5is planned for an eventual 0.6.0 release. Accuracy and speed are measurements on a few datasets, not guarantees.Help wanted: messy addresses. If it parses your addresses badly, please open an issue with a sample. I want to fix them. Private data can be anonymized first (how).
Quickstart
pip install doorplate
import doorplate as dp
a = dp.parse("123 north main street apt 4, Miami FL 33101")
a.street_name # "MAIN"
a.unit_number # "4"
a.place # {"name": "MIAMI", "state": "FL", "county": "DADE", ...}
a.warnings # []
a.to_usps()["line1"] # "123 N MAIN ST APT 4"
a.to_display()["line1"] # "123 N Main St Apt 4" (to_long(): "123 North Main Street Apartment 4"); display only, not Pub 28
a.key() # "k4:S|123|N|MAIN|ST||FL|33101"
a.slug() # "123-n-main-st-apt-4-miami-fl-33101"
a.to_reso() # RESO Data Dictionary 2.0 fields
a.to_dict() # everything above as plain Python values, and provenance (the library version and the state data version; also `a.library_version`, `a.state_data_version`)
dp.parse_fields(line1="THE COVE", line2="1111 ASBURY WAY",
city="Orlando", state="FL", zip="32801")
dp.parse_many(["1 Main St, Miami FL", "PO Box 5, Tampa FL"]) # GIL released
dp.parse_fields_many(line1=["1 Main St", "PO Box 5"], city=["Miami", "Tampa"])
dp.parse("281 EVELYN DR DOTHAN", default_state="AL").city # "DOTHAN"
- Unusable input (no address text at all) raises
ParseError, aValueError; inparse_manythat element isNone. Anything else comes back withwarnings(what each one tells you, and how often it is wrong). default_stateis a lookup hint for input with no state; it never fillsstate. A value that is not a US state, DC or territory raisesValueError.
Install
pip install doorplate # the parser
pip install "doorplate[pandas]" # plus the pandas helper
pip install "doorplate[polars]" # plus the Polars helper
pip install "doorplate[duckdb]" # plus the DuckDB functions (DuckDB and PyArrow)
Python 3.10 or later. Wheels are built for Linux (x86_64, aarch64), macOS (universal2) and Windows (x64), and tested on Python 3.10 and 3.13. To build from source (Rust 1.83 or later):
pip install maturin
cd crates/doorplate-py
maturin develop --release # builds the extension into your virtualenv
pytest tests
The API
The calls are parse, parse_fields, parse_many, parse_fields_many, Parser, tag, parse_tokens,
load_layer, Anonymizer and address_type; a ParsedAddress is read-only and typed (py.typed), with the components,
warnings, unparsed, and key(), slug(), to_usps(), to_display(), to_reso() and to_dict(). The tour is the
Python guide; every function and class is in the Python reference.
Your data, by shape
A column of addresses in pandas, Polars or DuckDB, split columns, mixed shapes, a CSV file: see pandas, Polars and DuckDB (one call per shape, with timings), or the examples in the repository.
Batches, pandas, Polars and DuckDB
parse_many(texts) parses a list on every core with the GIL released (about 3x a loop of parse), and the helpers
doorplate.pandas.parse_column, doorplate.polars.parse_column and doorplate.duckdb build on it:
from doorplate.polars import parse_column # or doorplate.pandas
out = df.hstack(parse_column(df["address"])) # Polars
out = df.join(parse_column(df["address"], default_state="FL")) # pandas
The columns, DuckDB in SQL, doing it by hand and the timings are in pandas, Polars and DuckDB.
Custom layers
Your data spells TRAIL as TRAYL, or lives in a place the shipped list lacks? doorplate.load_layer("DIR") adds your own
spellings, words, places and ZIPs on top of the shipped tables (custom_layer= on every call). A layer can change a key, so
every parse reports it. The files, the rules, a demo layer, a template and a prompt for an LLM are in
Custom layers.
Sharing messy data
doorplate.Anonymizer(seed=None).anonymize("123 N Zephyrmill Ave Apt 4, Miami, FL 33101") gives a copy that keeps the shape and
loses the names and numbers, even when the text does not parse. It is obfuscation, not anonymity: read the output before
you share it. The rules, the limits and what it can leak are in Anonymizing data.
Coming from usaddress
For a script that calls usaddress.parse and usaddress.tag, change one import (label compatibility, not identical output):
import doorplate.compat as usaddress # was: import usaddress
The same calls under doorplate's own names are parse_tokens(s) and tag(s). The mapping and the differences are in
Coming from usaddress.
Accuracy and speed
| doorplate | usaddress | |
|---|---|---|
Whole address right, benchmark suite, natural stratum (16,001 addresses written in five styles) |
98.5% | 96.1% |
| Whole address right, geocode benchmark dev split (60,522 one-line addresses) | 94.3% | 88.1% |
| Addresses per second, one thread (suite inputs) | about 43,400 | about 9,300 |
The suite is 19,586 labeled addresses that neither library was made from; it also holds both libraries' known blind spots
on purpose, so read its natural stratum as the estimate for ordinary input. Speed is on 4 CPUs, 8 GB. These are measurements on a few data sets, not promises for yours. Method and every other figure:
accuracy and speed and size; how to rerun them: running the benchmarks.
Disclaimer
doorplate is provided "as is", without warranty of any kind, under the MIT or Apache-2.0 license at your option; the license text is what governs. In plain terms: use it at your own risk. Nothing here guarantees that a parse, a warning, a match key or a figure is correct, complete or fit for your purpose. Accuracy and speed numbers are measurements on particular datasets, not promises for yours. doorplate parses and formats addresses; it does not validate that an address exists or can receive mail, and Pub 28 formatting is not certified validation. Check its output before you rely on it for anything with legal, financial, safety or delivery consequences.
doorplate is an independent project. It is not affiliated with, endorsed by or certified by the US Postal Service, RESO, DataMade (the authors of usaddress) or any data source it cites; those names are used only to say what the output follows or is compared with.
More
- Documentation site: the Python guide, reference, pandas, Polars and DuckDB, the key, warnings and how it works.
- Project README: what it does, the Rust library, the command-line tool.
- Examples: a notebook tour and a pipeline for each DataFrame library.
Licensed under either of MIT or Apache-2.0 at your option.
Metadata
Release files for doorplate 0.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| doorplate-0.5.1.tar.gz | 961.2 kB | With provenance | Details for doorplate-0.5.1.tar.gz |
Built distributions (wheels)
| File | Actions Reset | |||
|---|---|---|---|---|
| doorplate-0.5.1-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details for doorplate-0.5.1-cp310-abi3-win_amd64.whl |
| doorplate-0.5.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details for doorplate-0.5.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
| doorplate-0.5.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details for doorplate-0.5.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
| doorplate-0.5.1-cp310-abi3-macosx_10_12_universal2.macosx_10_12_x86_64.macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64, macOS 11.0+ ARM64, macOS 10.12+ universal2 (ARM64, x86-64) | Details for doorplate-0.5.1-cp310-abi3-macosx_10_12_universal2.macosx_10_12_x86_64.macosx_11_0_arm64.whl |
Total release size: 11.2 MB
Release files / doorplate-0.5.1.tar.gz
| Download URL | doorplate-0.5.1.tar.gz |
|---|---|
| Size | 961.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
967df576a96c8ef19afc805bff7d870a3343e325c3e4f121e178682d0089037d
|
|
BLAKE2b-256 checksum How to use checksums |
5563f40ecff0fb670f1555ba6aba6d5c945f43cea0fbc03e67978268359f3803
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 1, 2026.
Transparency logRelease files / doorplate-0.5.1-cp310-abi3-win_amd64.whl
| Download URL | doorplate-0.5.1-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 2.0 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
701ed55d474b0162173a99981fea9b3a21a90cc745c6014e55adae190aff392d
|
|
BLAKE2b-256 checksum How to use checksums |
9d1fe0cfd474195c7b57dc07c1d87036082affee369cdd3f63bb2a1226541fea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 1, 2026.
Transparency logRelease files / doorplate-0.5.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | doorplate-0.5.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 2.1 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
507cbd5638a45669f46aefe6f820b4ef9f3e02571dde4fa1ba7d2e71d6da7351
|
|
BLAKE2b-256 checksum How to use checksums |
2be0033ebfc5f31a51a231c6dd1f95fd3262cafb4dac4c5cca3df11bf07316dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 1, 2026.
Transparency logRelease files / doorplate-0.5.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
| Download URL | doorplate-0.5.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
|---|---|
| Size | 2.1 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
4741f1a835149b848dd45bca5bc4eed493d8b898b538e1d22a4708eba05ccf33
|
|
BLAKE2b-256 checksum How to use checksums |
bc55103d2ca7574bff2832fcfa1f62b3d2b0e22f49866b9bbf054fd54a331f5f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 1, 2026.
Transparency logRelease files / doorplate-0.5.1-cp310-abi3-macosx_10_12_universal2.macosx_10_12_x86_64.macosx_11_0_arm64.whl
| Download URL | doorplate-0.5.1-cp310-abi3-macosx_10_12_universal2.macosx_10_12_x86_64.macosx_11_0_arm64.whl |
|---|---|
| Size | 4.1 MB |
| Tags | CPython 3.10 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
3b60e9c043272817b7c7fdb8fa2ca9bc83fb444937a362e220f5a536b9677220
|
|
BLAKE2b-256 checksum How to use checksums |
cbb31af8c1c952056cde16bd76278e6a5bb71a50ff3b63489a592431612e0b61
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 1, 2026.
Transparency logSecurity for doorplate 0.5.1
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.
Full provenance
All 5 files in this release have been uploaded with provenance metadata.
Attestation for doorplate-0.5.1.tar.gz
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 Nov 1, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.