Skip to main content

Entity

Represents a person or organization entity in RDAP responses. Entities can be registrants, technical contacts, administrative contacts, abuse contacts, or registrars.
object_class_name
string
Always “entity” for entity objects
conformance
array<string>
RDAP conformance levels (e.g., ["rdap_level_0"])
notices
array<Notice>
Server notices and terms of service. See common fields
handle
string
Registry-unique identifier for the entity
let entity_handle = entity.handle.unwrap_or_default();
vcard
VCard
Contact information in jCard format (RFC 7095)
roles
array<string>
Entity roles in the context where it appearsCommon roles:
  • "registrant" - Domain/resource owner
  • "administrative" - Administrative contact
  • "technical" - Technical contact
  • "abuse" - Abuse contact
  • "billing" - Billing contact
  • "registrar" - Domain registrar
  • "reseller" - Reseller
  • "sponsor" - Sponsoring organization
if entity.roles.contains(&"abuse".to_string()) {
    println!("This is an abuse contact");
}

// Find specific role
let is_registrar = entity.roles.iter()
    .any(|r| r == "registrar");
public_ids
array<PublicId>
Public identifiers (e.g., IANA Registrar ID). See common fields
// Find IANA Registrar ID
let registrar_id = entity.public_ids.iter()
    .find(|id| id.id_type == "IANA Registrar ID")
    .map(|id| &id.identifier);
entities
array<Entity>
Nested entities (e.g., contacts associated with a registrar)
// Recursively process nested entities
fn process_entity(entity: &Entity, depth: usize) {
    let indent = "  ".repeat(depth);
    println!("{}Entity: {}", indent, entity.handle.as_deref().unwrap_or("N/A"));
    
    for child in &entity.entities {
        process_entity(child, depth + 1);
    }
}
remarks
array<Remark>
Informational remarks. See common fields
Related links. See common fields
events
array<Event>
Lifecycle events for the entity. See common fields
as_event_actor
array<Event>
Events where this entity was the actor
status
array<string>
Entity status values (e.g., “active”, “validated”)
port43
string
WHOIS server hostname for port 43 queries
networks
array<IpNetwork>
IP networks associated with this entity. See IpNetwork
autnums
array<Autnum>
AS numbers associated with this entity. See Autnum
lang
string
Language tag (e.g., “en”, “fr”)

Example Usage

Finding Contacts in Domain Query

use rdap_client::RdapClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = RdapClient::new();
    let result = client.query("example.com").await?;
    
    if let Some(domain) = result.domain() {
        // Find registrar
        for entity in &domain.entities {
            if entity.roles.contains(&"registrar".to_string()) {
                if let Some(vcard) = &entity.vcard {
                    println!("Registrar: {}", vcard.name().unwrap_or("Unknown"));
                    
                    if let Some(email) = vcard.email() {
                        println!("Email: {}", email);
                    }
                }
                
                // Get IANA Registrar ID
                for pid in &entity.public_ids {
                    if pid.id_type == "IANA Registrar ID" {
                        println!("Registrar ID: {}", pid.identifier);
                    }
                }
            }
        }
        
        // Find abuse contact
        for entity in &domain.entities {
            if entity.roles.contains(&"abuse".to_string()) {
                if let Some(vcard) = &entity.vcard {
                    println!("\nAbuse Contact:");
                    if let Some(email) = vcard.email() {
                        println!("  Email: {}", email);
                    }
                    if let Some(tel) = vcard.tel() {
                        println!("  Phone: {}", tel);
                    }
                }
            }
        }
    }
    
    Ok(())
}

Accessing VCard Information

fn display_entity_contact(entity: &Entity) {
    if let Some(vcard) = &entity.vcard {
        // Basic contact info
        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);
        }
        
        // Full address
        if let Some(addr) = vcard.address() {
            println!("Address:");
            
            if let Some(label) = &addr.label {
                // Use pre-formatted address if available
                println!("  {}", label);
            } else {
                // Build address from components
                if !addr.street.is_empty() {
                    println!("  {}", addr.street);
                }
                if !addr.locality.is_empty() || !addr.region.is_empty() {
                    println!("  {}, {}", addr.locality, addr.region);
                }
                if !addr.postal_code.is_empty() {
                    println!("  {}", addr.postal_code);
                }
                if !addr.country.is_empty() {
                    println!("  {}", addr.country);
                }
            }
        }
    }
}

Finding Entities by Role

fn find_entities_by_role<'a>(
    entities: &'a [Entity],
    role: &str
) -> impl Iterator<Item = &'a Entity> {
    entities.iter().filter(move |e| e.roles.contains(&role.to_string()))
}

// Usage
let registrars: Vec<_> = find_entities_by_role(&domain.entities, "registrar").collect();
let abuse_contacts: Vec<_> = find_entities_by_role(&domain.entities, "abuse").collect();

Build docs developers (and LLMs) love