ipwhois-rust 1.2.0

Official Rust client for the ipwhois.io IP Geolocation API. Simple, supports single and bulk IP lookups.
Documentation
//! Run with: `cargo run --example bulk`
//!
//! Bulk lookup is available on the Business and Unlimited plans only.
//! The library uses the GET / comma-separated form of the bulk endpoint:
//!
//!     https://ipwhois.pro/bulk/IP1,IP2,IP3?key=...
//!
//! Up to 100 IP addresses can be passed in a single call. Each address
//! counts as one credit.

use ipwhois::{IpWhois, Options};

#[tokio::main]
async fn main() {
    let ipwhois = IpWhois::with_key("YOUR_API_KEY");

    let ips = [
        "8.8.8.8",
        "1.1.1.1",
        "208.67.222.222",
        "2c0f:fb50:4003::", // IPv6 is fine too — mix freely
    ];

    let opts = Options::new().with_lang("en").with_security(true);

    let results = match ipwhois.bulk_lookup_with(ips, &opts).await {
        Ok(r) => r,
        Err(e) => {
            // Whole-batch failure (network down, bad API key, rate limit, …)
            // — surfaces here as a single `Err`.
            eprintln!(
                "Bulk request failed: {} (HTTP {})",
                e.message(),
                e.http_status()
                    .map(|s| s.to_string())
                    .unwrap_or_else(|| "?".to_string()),
            );
            std::process::exit(1);
        }
    };

    for row in &results {
        if !row.success {
            // Per-IP errors (e.g. "Invalid IP address", "Reserved range")
            // are returned inline. The rest of the batch is still usable.
            println!(
                "[skip] {}{}",
                row.ip.as_deref().unwrap_or("?"),
                row.message.as_deref().unwrap_or("error"),
            );
            continue;
        }

        println!(
            "{:<18} {} {:<4} {}",
            row.ip.as_deref().unwrap_or(""),
            row.flag
                .as_ref()
                .and_then(|f| f.emoji.as_deref())
                .unwrap_or("  "),
            row.country_code.as_deref().unwrap_or(""),
            row.connection
                .as_ref()
                .and_then(|c| c.isp.as_deref())
                .unwrap_or(""),
        );
    }
}