Skip to main content
This page contains real, working examples extracted from the library’s examples/ directory.

Basic Query

Simple domain query with colored output:
examples/basic_query.rs
use rdap::{QueryType, RdapClient, RdapRequest, display::RdapDisplay};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    env_logger::init();

    // Create a client
    let client = RdapClient::new()?;

    // Create a domain query
    let request = RdapRequest::new(QueryType::Domain, "example.com");

    // Execute the query
    println!("Querying example.com...\n");
    let result = client.query(&request).await?;

    // Display the result with colors
    result.display(true);

    Ok(())
}
Source: examples/basic_query.rs
The RdapDisplay trait provides colored terminal output. Set the boolean parameter to true for colors.

Auto-Detection

Automatically detect query type from input:
examples/auto_detect.rs
use rdap::{RdapClient, RdapRequest};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = RdapClient::new()?;

    // Query different types - type is auto-detected
    let queries = vec![
        "example.com",          // Domain
        "8.8.8.8",              // IPv4
        "2001:4860:4860::8888", // IPv6
        "AS15169",              // AS number
    ];

    for query in queries {
        println!("\n=== Querying: {} ===", query);

        // Auto-detect query type
        let query_type = RdapRequest::detect_type(query)?;
        println!("Detected type: {:?}", query_type);

        let request = RdapRequest::new(query_type, query);
        let result = client.query(&request).await?;

        // Display result
        use rdap::display::RdapDisplay;
        result.display(false);
    }

    Ok(())
}
Source: examples/auto_detect.rs

Domain Information Extraction

Extract specific fields from a domain response:
examples/domain_info.rs
use rdap::{QueryType, RdapClient, RdapObject, RdapRequest};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = RdapClient::new()?;
    let request = RdapRequest::new(QueryType::Domain, "example.com");
    let result = client.query(&request).await?;

    if let RdapObject::Domain(domain) = result {
        println!("=== Domain Information ===\n");

        // Basic info
        if let Some(name) = &domain.ldh_name {
            println!("Domain: {}", name);
        }

        if let Some(handle) = &domain.handle {
            println!("Handle: {}", handle);
        }

        // Status
        println!("\nStatus:");
        for status in &domain.status {
            println!("  - {}", status);
        }

        // Nameservers
        println!("\nNameservers:");
        for ns in &domain.nameservers {
            if let Some(name) = &ns.ldh_name {
                print!("  - {}", name);
                if let Some(ips) = &ns.ip_addresses {
                    let addrs: Vec<String> = ips.v4.iter().chain(&ips.v6).cloned().collect();
                    if !addrs.is_empty() {
                        print!(" ({})", addrs.join(", "));
                    }
                }
                println!();
            }
        }

        // DNSSEC
        if let Some(dnssec) = &domain.secure_dns {
            println!("\nDNSSEC:");
            if let Some(signed) = dnssec.delegation_signed {
                println!("  Delegation Signed: {}", if signed { "Yes" } else { "No" });
            }
            if let Some(signed) = dnssec.zone_signed {
                println!("  Zone Signed: {}", if signed { "Yes" } else { "No" });
            }

            // DS records
            if !dnssec.ds_data.is_empty() {
                println!("\n  DS Records:");
                for ds in &dnssec.ds_data {
                    if let (Some(tag), Some(alg), Some(digest_type)) =
                        (ds.key_tag, ds.algorithm, ds.digest_type)
                    {
                        println!(
                            "    - Key Tag: {}, Algorithm: {}, Digest Type: {}",
                            tag, alg, digest_type
                        );
                        if let Some(digest) = &ds.digest {
                            println!("      Digest: {}", digest);
                        }
                    }
                }
            }
        }

        // Events
        println!("\nImportant Dates:");
        for event in &domain.events {
            match event.action.as_str() {
                "registration" => println!("  Registered: {}", event.date),
                "expiration" => println!("  Expires: {}", event.date),
                "last changed" => println!("  Last Updated: {}", event.date),
                _ => {}
            }
        }

        // Entities
        println!("\nEntities:");
        for entity in &domain.entities {
            if let Some(handle) = &entity.handle {
                println!("  - {} ({})", handle, entity.roles.join(", "));

                if let Some(vcard) = &entity.vcard {
                    if let Some(name) = vcard.name() {
                        println!("    Name: {}", name);
                    }
                    if let Some(email) = vcard.email() {
                        println!("    Email: {}", email);
                    }
                }
            }
        }
    }

    Ok(())
}
Source: examples/domain_info.rs

IP Lookup

Query IP network information:
examples/ip_lookup.rs
use rdap::{QueryType, RdapClient, RdapObject, RdapRequest};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = RdapClient::new()?;

    // Query an IP address
    let ip = "8.8.8.8";
    let request = RdapRequest::new(QueryType::Ip, ip);
    let result = client.query(&request).await?;

    if let RdapObject::IpNetwork(network) = result {
        println!("=== IP Network Information ===\n");

        if let Some(name) = &network.name {
            println!("Network Name: {}", name);
        }

        if let Some(handle) = &network.handle {
            println!("Handle: {}", handle);
        }

        if let (Some(start), Some(end)) = (&network.start_address, &network.end_address) {
            println!("Address Range: {} - {}", start, end);
        }

        if let Some(version) = &network.ip_version {
            println!("IP Version: IPv{}", version);
        }

        if let Some(net_type) = &network.network_type {
            println!("Network Type: {}", net_type);
        }

        if let Some(country) = &network.country {
            println!("Country: {}", country);
        }

        if let Some(parent) = &network.parent_handle {
            println!("Parent Network: {}", parent);
        }

        // Status
        if !network.status.is_empty() {
            println!("\nStatus:");
            for status in &network.status {
                println!("  - {}", status);
            }
        }

        // Entities
        if !network.entities.is_empty() {
            println!("\nContacts:");
            for entity in &network.entities {
                if let Some(handle) = &entity.handle {
                    println!("  - {} ({})", handle, entity.roles.join(", "));

                    if let Some(vcard) = &entity.vcard {
                        if let Some(name) = vcard.name() {
                            println!("    Name: {}", name);
                        }
                        if let Some(org) = vcard.org() {
                            println!("    Organization: {}", org);
                        }
                    }
                }
            }
        }
    }

    Ok(())
}
Source: examples/ip_lookup.rs

AS Number Lookup

Query Autonomous System information:
examples/asn_lookup.rs
use rdap::{QueryType, RdapClient, RdapObject, RdapRequest};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = RdapClient::new()?;

    // Query an AS number
    let asn = "AS15169";
    let request = RdapRequest::new(QueryType::Autnum, asn);
    let result = client.query(&request).await?;

    if let RdapObject::Autnum(autnum) = result {
        println!("=== AS Number Information ===\n");

        if let Some(start) = autnum.start_autnum {
            if let Some(end) = autnum.end_autnum {
                if start == end {
                    println!("AS Number: AS{}", start);
                } else {
                    println!("AS Range: AS{} - AS{}", start, end);
                }
            }
        }

        if let Some(name) = &autnum.name {
            println!("Name: {}", name);
        }

        if let Some(handle) = &autnum.handle {
            println!("Handle: {}", handle);
        }

        if let Some(as_type) = &autnum.as_type {
            println!("Type: {}", as_type);
        }

        if let Some(country) = &autnum.country {
            println!("Country: {}", country);
        }

        // Status
        if !autnum.status.is_empty() {
            println!("\nStatus:");
            for status in &autnum.status {
                println!("  - {}", status);
            }
        }

        // Events
        if !autnum.events.is_empty() {
            println!("\nEvents:");
            for event in &autnum.events {
                println!("  {}: {}", event.action, event.date);
            }
        }

        // Entities
        if !autnum.entities.is_empty() {
            println!("\nContacts:");
            for entity in &autnum.entities {
                if let Some(handle) = &entity.handle {
                    println!("\n  {} ({})", handle, entity.roles.join(", "));

                    if let Some(vcard) = &entity.vcard {
                        if let Some(name) = vcard.name() {
                            println!("    Name: {}", name);
                        }
                        if let Some(org) = vcard.org() {
                            println!("    Organization: {}", org);
                        }
                        if let Some(email) = vcard.email() {
                            println!("    Email: {}", email);
                        }
                        if let Some(tel) = vcard.tel() {
                            println!("    Phone: {}", tel);
                        }
                        if let Some(addr) = vcard.address() {
                            if let Some(label) = &addr.label {
                                println!("    Address: {}", label);
                            }
                        }
                    }
                }
            }
        }
    }

    Ok(())
}
Source: examples/asn_lookup.rs

Error Handling

Comprehensive error handling:
examples/error_handling.rs
use rdap::{QueryType, RdapClient, RdapError, RdapObject, RdapRequest};

#[tokio::main]
async fn main() {
    let client = RdapClient::new().unwrap();

    // Try queries that might fail
    let queries = vec![
        ("nonexistent-domain-12345.com", QueryType::Domain),
        ("999.999.999.999", QueryType::Ip),
        ("AS99999999", QueryType::Autnum),
    ];

    for (query, query_type) in queries {
        println!("\n=== Querying: {} ===", query);

        let request = RdapRequest::new(query_type, query);

        match client.query(&request).await {
            Ok(result) => {
                // Check if it's an error response from the RDAP server
                match result {
                    RdapObject::Error(err) => {
                        println!("❌ RDAP Error Response:");
                        if let Some(code) = err.error_code {
                            println!("   Code: {}", code);
                        }
                        if let Some(title) = &err.title {
                            println!("   Title: {}", title);
                        }
                        for desc in &err.description {
                            println!("   Description: {}", desc);
                        }
                    }
                    _ => {
                        println!("✅ Query successful");
                        use rdap::display::RdapDisplay;
                        result.display(false);
                    }
                }
            }
            Err(e) => {
                println!("❌ Client Error:");
                match e {
                    RdapError::Bootstrap(msg) => {
                        println!("   Bootstrap error: {}", msg);
                        println!("   (Try specifying a server with -s option)");
                    }
                    RdapError::Http(err) => {
                        println!("   HTTP error: {}", err);
                    }
                    RdapError::InvalidQuery(msg) => {
                        println!("   Invalid query: {}", msg);
                    }
                    RdapError::Json(err) => {
                        println!("   JSON parse error: {}", err);
                    }
                    RdapError::InvalidUrl(err) => {
                        println!("   URL error: {}", err);
                    }
                    RdapError::Io(err) => {
                        println!("   I/O error: {}", err);
                    }
                    _ => {
                        println!("   Other error: {}", e);
                    }
                }
            }
        }
    }
}
Source: examples/error_handling.rs

Batch Queries

Query multiple resources with rate limiting:
examples/batch_query.rs
use rdap::{RdapClient, RdapRequest};
use tokio::time::{Duration, sleep};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = RdapClient::new()?;

    // List of domains to query
    let queries = vec!["example.com", "google.com", "github.com", "rust-lang.org"];

    println!("Querying {} domains...\n", queries.len());

    for query in queries {
        println!("=== {} ===", query);

        // Auto-detect type
        let query_type = RdapRequest::detect_type(query)?;
        let request = RdapRequest::new(query_type, query);

        match client.query(&request).await {
            Ok(result) => {
                use rdap::display::RdapDisplay;
                result.display(false);
            }
            Err(e) => {
                eprintln!("Error querying {}: {}", query, e);
            }
        }

        println!();

        // Be nice to the server - add a small delay
        sleep(Duration::from_millis(500)).await;
    }

    Ok(())
}
Source: examples/batch_query.rs

Custom Server

Query a specific RDAP server:
examples/custom_server.rs
use rdap::{QueryType, RdapClient, RdapRequest, display::RdapDisplay};
use url::Url;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    env_logger::init();

    let client = RdapClient::new()?;

    // Query with a specific RDAP server
    let server = Url::parse("https://rdap.nic.cz")?;
    let request = RdapRequest::new(QueryType::Domain, "nic.cz").with_server(server);

    println!("Querying nic.cz via rdap.nic.cz...\n");
    let result = client.query(&request).await?;

    result.display(true);

    Ok(())
}
Source: examples/custom_server.rs

JSON Output

Serialize results to JSON:
examples/json_output.rs
use rdap::{QueryType, RdapClient, RdapRequest};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = RdapClient::new()?;
    let request = RdapRequest::new(QueryType::Domain, "example.com");

    let result = client.query(&request).await?;

    // Output as pretty JSON
    let json = serde_json::to_string_pretty(&result)?;
    println!("{}", json);

    Ok(())
}
Source: examples/json_output.rs

Complete Example

Demonstrates multiple features:
examples/complete_example.rs
use rdap::{RdapClient, RdapError, RdapObject, RdapRequest};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== RDAP Library Complete Example ===\n");

    // Create a client with custom timeout
    let client = RdapClient::new()?.with_timeout(Duration::from_secs(30));

    // Example 1: Domain query with detailed information extraction
    println!("1. Domain Query:");
    query_domain(&client, "example.com").await?;

    println!("\n{}\n", "=".repeat(60));

    // Example 2: IP address query
    println!("2. IP Address Query:");
    query_ip(&client, "8.8.8.8").await?;

    println!("\n{}\n", "=".repeat(60));

    // Example 3: AS number query
    println!("3. AS Number Query:");
    query_asn(&client, "AS15169").await?;

    println!("\n{}\n", "=".repeat(60));

    // Example 4: Error handling
    println!("4. Error Handling:");
    demonstrate_error_handling(&client).await;

    Ok(())
}

async fn query_domain(client: &RdapClient, domain: &str) -> Result<(), Box<dyn std::error::Error>> {
    let query_type = RdapRequest::detect_type(domain)?;
    let request = RdapRequest::new(query_type, domain);
    let result = client.query(&request).await?;

    if let RdapObject::Domain(domain_obj) = result {
        // Extract basic information
        if let Some(name) = &domain_obj.ldh_name {
            println!("  Domain: {}", name);
        }

        // Status information
        if !domain_obj.status.is_empty() {
            println!("  Status: {}", domain_obj.status.join(", "));
        }

        // Nameservers
        if !domain_obj.nameservers.is_empty() {
            println!("  Nameservers:");
            for ns in &domain_obj.nameservers {
                if let Some(name) = &ns.ldh_name {
                    println!("    - {}", name);
                }
            }
        }

        // DNSSEC status
        if let Some(dnssec) = &domain_obj.secure_dns {
            if let Some(signed) = dnssec.delegation_signed {
                println!("  DNSSEC: {}", if signed { "Enabled" } else { "Disabled" });
            }
        }

        // Important dates
        for event in &domain_obj.events {
            match event.action.as_str() {
                "registration" => println!("  Registered: {}", event.date),
                "expiration" => println!("  Expires: {}", event.date),
                _ => {}
            }
        }
    }

    Ok(())
}

async fn query_ip(client: &RdapClient, ip: &str) -> Result<(), Box<dyn std::error::Error>> {
    let query_type = RdapRequest::detect_type(ip)?;
    let request = RdapRequest::new(query_type, ip);
    let result = client.query(&request).await?;

    if let RdapObject::IpNetwork(network) = result {
        if let Some(name) = &network.name {
            println!("  Network: {}", name);
        }

        if let (Some(start), Some(end)) = (&network.start_address, &network.end_address) {
            println!("  Range: {} - {}", start, end);
        }

        if let Some(country) = &network.country {
            println!("  Country: {}", country);
        }

        // Find registrant
        for entity in &network.entities {
            if entity.roles.contains(&"registrant".to_string()) {
                if let Some(vcard) = &entity.vcard {
                    if let Some(org) = vcard.name() {
                        println!("  Organization: {}", org);
                    }
                }
                break;
            }
        }
    }

    Ok(())
}

async fn query_asn(client: &RdapClient, asn: &str) -> Result<(), Box<dyn std::error::Error>> {
    let query_type = RdapRequest::detect_type(asn)?;
    let request = RdapRequest::new(query_type, asn);
    let result = client.query(&request).await?;

    if let RdapObject::Autnum(autnum) = result {
        if let Some(start) = autnum.start_autnum {
            println!("  AS Number: AS{}", start);
        }

        if let Some(name) = &autnum.name {
            println!("  Name: {}", name);
        }

        if let Some(country) = &autnum.country {
            println!("  Country: {}", country);
        }

        // Count entities by role
        let mut role_counts = std::collections::HashMap::new();
        for entity in &autnum.entities {
            for role in &entity.roles {
                *role_counts.entry(role.clone()).or_insert(0) += 1;
            }
        }

        if !role_counts.is_empty() {
            println!("  Contacts:");
            for (role, count) in role_counts {
                println!("    - {}: {}", role, count);
            }
        }
    }

    Ok(())
}

async fn demonstrate_error_handling(client: &RdapClient) {
    let test_queries = vec!["nonexistent-domain-xyz123.com", "999.999.999.999"];

    for query in test_queries {
        println!("  Testing: {}", query);

        let query_type = match RdapRequest::detect_type(query) {
            Ok(qt) => qt,
            Err(e) => {
                println!("    ❌ Invalid query: {}", e);
                continue;
            }
        };

        let request = RdapRequest::new(query_type, query);

        match client.query(&request).await {
            Ok(result) => match result {
                RdapObject::Error(err) => {
                    println!("    ⚠️  RDAP Error:");
                    if let Some(title) = &err.title {
                        println!("       {}", title);
                    }
                }
                _ => {
                    println!("    ✅ Query successful");
                }
            },
            Err(e) => match e {
                RdapError::Bootstrap(msg) => {
                    println!("    ❌ Bootstrap error: {}", msg);
                }
                RdapError::NotFound => {
                    println!("    ℹ️  Object not found");
                }
                _ => {
                    println!("    ❌ Error: {}", e);
                }
            },
        }
    }
}
Source: examples/complete_example.rs

Running Examples

Run examples using cargo run --example:
# Basic query
cargo run --example basic_query

# Auto-detect query type
cargo run --example auto_detect

# Domain information extraction
cargo run --example domain_info

# IP lookup
cargo run --example ip_lookup

# AS number lookup
cargo run --example asn_lookup

# Error handling
cargo run --example error_handling

# Batch queries
cargo run --example batch_query

# Custom server
cargo run --example custom_server

# JSON output
cargo run --example json_output

# Complete example
cargo run --example complete_example

Next Steps

Getting Started

Back to getting started guide

API Reference

Browse the full API documentation

Build docs developers (and LLMs) love