| Crates.io | libpostal-rs |
| lib.rs | libpostal-rs |
| version | 0.1.3 |
| created_at | 2025-08-02 23:16:44.802321+00 |
| updated_at | 2025-08-04 15:29:43.424241+00 |
| description | Static Rust bindings for libpostal - international address parsing and normalization |
| homepage | |
| repository | https://github.com/Isaac-Duarte/libpostal-rs |
| max_upload_size | |
| id | 1779204 |
| size | 220,559 |
Rust bindings for libpostal, a library for parsing and normalizing international addresses. If you need to parse street addresses from around the world into structured components, this library can help.
This library handles the complexities of international address formats by wrapping the battle-tested libpostal C library. It can take messy address strings and break them down into useful parts like house numbers, street names, cities, and postal codes.
First, add this to your Cargo.toml:
[dependencies]
libpostal-rs = "0.1"
Here's a simple example:
use libpostal_rs::LibPostal;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize the library (downloads data files on first run)
let postal = LibPostal::new().await?;
// Parse an address
let parsed = postal.parse_address("123 Main St, New York, NY 10001")?;
if let Some(house_number) = parsed.house_number {
println!("House number: {}", house_number);
}
if let Some(road) = parsed.road {
println!("Street: {}", road);
}
if let Some(city) = parsed.city {
println!("City: {}", city);
}
Ok(())
}
The first time you run this, it will download about 1GB of language models and data files. After that, startup is fast.
The main thing you'll probably want to do is parse addresses:
let postal = LibPostal::new().await?;
let parsed = postal.parse_address("221B Baker Street, London")?;
// Access individual components
println!("House: {:?}", parsed.house_number);
println!("Street: {:?}", parsed.road);
println!("City: {:?}", parsed.city);
You can also normalize addresses to expand abbreviations:
let normalized = postal.normalize_address("123 Main St")?;
for expansion in normalized.expansions {
println!("{}", expansion); // "123 main street", "123 main st"
}
The library works with international addresses. You can provide language hints:
let parsed = postal.parse_address_with_hints(
"123 Rue de la Paix, Paris",
Some("fr"), // French
Some("FR") // France
)?;
For better performance when processing many addresses:
let parser = postal.parser();
let addresses = vec!["123 Main St", "456 Oak Ave", "789 Pine Rd"];
let results = parser.parse_batch(&addresses)?;
This library compiles libpostal from source, so you'll need some build tools:
Ubuntu/Debian:
sudo apt-get install build-essential autoconf automake libtool pkg-config
macOS:
brew install autoconf automake libtool pkg-config
Windows: You'll need MSYS2 or Visual Studio Build Tools. This is the trickiest platform to set up.
The library needs about 1GB of data files (language models, address dictionaries, etc.). On first run, it will automatically download these to your home directory under .libpostal/. This only happens once.
If you want to control where the data goes:
use libpostal_rs::{LibPostal, LibPostalConfig};
let config = LibPostalConfig::builder()
.data_dir("/custom/path/to/data")
.build();
let postal = LibPostal::with_config(config).await?;
The parser can extract these components from addresses:
house_number - "123", "123A"road - "Main Street", "Broadway"unit - "Apt 2B", "Unit 5"city - "New York", "London"state - "NY", "California"postcode - "10001", "SW1A 1AA"country - "USA", "United Kingdom"Plus several others like level, suburb, entrance, etc. Check the ParsedAddress struct for the full list.
This library is in early development. Here's what you should know:
What works:
If you run into issues, please open a GitHub issue. This is a work in progress.
You can find more examples in the examples/ directory:
basic_usage.rs - Simple address parsing and normalizationadvanced_usage.rs - More complex scenariosbasic_parsing.rs - Just parsing without the extrasTo run an example:
cargo run --example basic_usage
You can enable additional features in your Cargo.toml:
[dependencies]
libpostal-rs = { version = "0.1", features = ["serde", "parallel"] }
serde - Serialization support for parsed addressesparallel - Parallel batch processing with rayonruntime-data - Download data files at runtime (enabled by default)This project needs help! Some areas where contributions would be valuable:
If you're interested in contributing, please:
The codebase is straightforward Rust with FFI bindings to the C library.
This project is licensed under either of:
at your option.
The underlying libpostal C library is licensed under the MIT License.
This library builds upon the excellent libpostal project by Al Barrentine and contributors. The heavy lifting is done by their C library - this is just a Rust wrapper to make it easier to use from Rust code.