Skip to content

Domain History API

# Show ownership changes for chat.com
curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" 'https://api.domaintools.com/v1/domain-history/?domain=chat.com&include_fields=registrar'

The Domain History API provides access to DomainTools’ record of changes to a domain’s infrastructure, registration, and content. Track the evolution of domains across their lifecycle and identify significant events such as infrastructure weaponization, service changes, or registration transfers.

This API delivers change events that show what changed, when it changed, and the before/after states for each modification. Use field filtering to focus on specific types of changes relevant to your investigation.

Each change event in the response includes:

  • timestamp: When the change was detected (ISO 8601 format, an international standard for date and time representation)
  • field: The specific property that changed (e.g., ip, mx, registrar)
  • before: The complete state before the change
  • after: The complete state after the change

Note: When a domain starts a new registration lifecycle, the before field may be null or empty. The API only tracks changes within a given lifecycle, so previous lifecycle data is not included in history events.

The API uses one of two data sources for registration information:

  • parsed_whois: Traditional WHOIS data, parsed and normalized
  • parsed_domain_rdap: RDAP (Registration Data Access Protocol) data, the modern successor to WHOIS

The registration_source field indicates which source the API used. By default, the API uses parsed_whois as the registration source. The API switches to RDAP data only when you explicitly request it or when RDAP is the only available source for the domain.

The active field in change events indicates whether a domain was actively registered at the time of the change (this field corresponds to the status field in the DomainTools user interface). Use this to distinguish modifications during the current registration period from changes in prior lifecycles.

Domain History launched in October 2021. For domains that were active before this date:

  • No history event records the initial transition to active status
  • History events only capture changes that occurred after October 2021
  • The domain’s state at launch serves as the baseline for subsequent change tracking

Field filtering operates at the event level, not the property level:

  • Filtering determines which change events appear in the response
  • Each returned event includes the complete before and after objects for that field
  • Filtering doesn’t remove properties from the before and after objects

Pinpoint when a domain’s infrastructure was weaponized by isolating changes in IP addresses, name servers, or mail servers.

Example workflow:

  1. Filter for infrastructure changes using include_fields=ip,nameserver_host,mailserver_host
  2. Review the active field to identify changes during the current registration
  3. Examine the timeline to determine when the domain was brought online for a campaign

Determine when a domain launched a functional service by identifying the first SSL certificate issuance.

Example workflow:

  1. Filter for SSL changes using include_fields=ssl_hash (or other SSL-related fields)
  2. Find the earliest timestamp where an SSL certificate appears in the after state
  3. Correlate with other infrastructure changes to understand service deployment

Reveal transfers of domain ownership by comparing registrar and registrant data across distinct registration lifecycles.

Example workflow:

  1. Filter for registration changes using include_fields=registrar,registrant,create_date,expiration_date
  2. Look for changes in registrar or registrant fields
  3. Use the active field to distinguish between registration periods

The Domain History API supports three authentication methods.

Include your API key in the X-Api-Key header:

curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com'

HMAC (Hash-based Message Authentication Code) authentication provides enhanced security by signing each request with a hash derived from your API secret. See the Authentication Guide for implementation details.

Pass your credentials as query parameters. This method is less secure and not recommended for production use. See the Authentication Guide for implementation details.

ParameterDescriptionExample
domainThe domain name to retrieve history fordomaintools.com
ParameterDescriptionExample
include_fieldsComma-separated list of fields to include. Only change events matching these fields appear in results.ip,mx,name_server
exclude_fieldsComma-separated list of fields to exclude. Change events matching these fields are omitted from results.ssl_information,web_trackers_information
ParameterDescriptionDefaultExample
page_sizeNumber of results per page. Maximum is 100 entries per request.10050
offsetStarting point for results (0-indexed). Controls pagination across large result sets. Note: Real-time delays between paginated requests may result in duplicate data, as new changes can occur between requests.0500
nextBoolean flag. When set to true, includes a next URL in the response for cursor-based pagination. Authentication parameters must still be included when following the next URL.falsetrue
ParameterDescriptionDefault
parsed_whoisInclude full parsed WHOIS record in before and after objectsfalse
parsed_domain_rdapInclude full parsed Domain RDAP record in before and after objectsfalse
ParameterDescriptionExample
formatResponse format (json, xml, html)json
app_partnerYour product name (for debugging)MySecurityPlatform
app_nameYour appliance, module, or playbook nameThreatIntel
app_versionYour integration version2.1.0

Field filtering determines which change events appear in the response based on the field property of each event. When you filter:

  • The API evaluates each change event’s field value
  • Events matching your filter criteria are included
  • Events not matching are excluded
  • Each included event contains its complete before and after objects

Important: Filtering doesn’t remove properties from the before and after objects. It determines which entire change events are returned.

The include_fields and exclude_fields parameters accept a specific format:

Required format:

  • Comma-separated list of exact field names
  • No spaces before or after commas
  • Field names must match exactly (case-sensitive)

Valid examples:

include_fields=ip,mx,name_server
include_fields=all_ssl,registrar
include_fields=ssl_hash

What is NOT supported:

  • Wildcards or patterns (e.g., ssl_*, *_email)
  • Regular expressions
  • Partial matches
  • Ranges
  • Spaces in the list (e.g., ip, mx is invalid)
  • Other delimiters besides commas

Only exact field name matches work. If you need multiple related fields, use the aggregate field categories (prefixed with all_) rather than attempting pattern matching.

You can filter change events using either individual field names or aggregate field groups:

Individual fields target specific properties:

  • Use when you need precise control over which change types to include
  • Example: include_fields=ip,registrar returns only IP address and registrar changes

Aggregate fields (prefixed with all_) group related individual fields:

  • Use when you want all changes within a category
  • Example: include_fields=all_ssl returns changes for any SSL-related field (ssl_hash, ssl_common_name, ssl_alt_names, ssl_not_before, ssl_not_after)
  • More efficient than listing multiple individual fields

Filtering behavior:

  • When you specify an aggregate field, the API returns events for any of its included individual fields
  • You can mix individual and aggregate fields in the same request
  • Example: include_fields=ip,all_ssl returns IP changes plus all SSL-related changes

Fields are organized by category. Each category shows the aggregate field (if available) that returns events for any of the individual fields in that category.

Contact Information:

  • Aggregate: all_contact_information — Returns events for any contact-related field
  • Individual fields: contact_name, contact_phone, contact_street, contact_city, contact_state, contact_fax, contact_organization

Email:

  • Aggregate: all_emails — Returns events for any email field
  • Individual fields: admin_contact_email, billing_contact_email, email_dns_soa, technical_contact_email, registrant_contact_email, additional_whois_email

IP and Network:

  • Aggregate: all_ip — Returns events for any IP-related field
  • Individual fields: ip, asn, ip_country_code, isp_name

Mail Server:

  • Aggregate: all_mailserver — Returns events for any mail server field
  • Individual fields: mailserver_host, mailserver_ip

Name Server:

  • Aggregate: all_nameserver — Returns events for any name server field
  • Individual fields: nameserver_host, nameserver_ip

SSL:

  • Aggregate: all_ssl — Returns events for any SSL field
  • Individual fields: ssl_hash, ssl_common_name, ssl_alt_names, ssl_not_before, ssl_not_after

Web Content:

  • Aggregate: all_web_content — Returns events for any web content field
  • Individual fields: redirect, redirect_domain, screenshot_collected_timestamp, server_type, website_response, website_title

Web Trackers:

  • Aggregate: all_web_trackers — Returns events for any web tracker field
  • Individual fields: adsense, baidu_analytics, facebook, google_analytics, ga4, google_tag_manager, hotjar, matomo, statcounter_project, statcounter_security, yandex_metrica

Registration:

  • Individual fields: create_date, expiration_date, registrant, registrar, registrar_status, active

Other:

  • Aggregate: all_other — Returns events for remaining uncategorized fields

To get a complete list of valid field names, provide an invalid field name in your request. The API returns an error message listing all valid options.

Example:

curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com&include_fields=invalid_field_name'

Include only infrastructure changes:

# Returns events where field: "ip", "mx", or "name_server"
curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com&include_fields=ip,mailserver_host,nameserver_host'

Exclude web trackers and SSL information:

# Excludes events where field matches tracking codes or "ssl_info"
curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com&exclude_fields=all_web_trackers,all_ssl'

Focus on registration lifecycle events:

# Returns events where field: "create_date", "expiration_date", "registrar", "registrant", or "active"
curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com&include_fields=create_date,expiration_date,registrar,registrant,active'
{
"response": {
"domain": "example.com",
"count": 1234,
"registration_source": "parsed_whois",
"changes": [
{
"timestamp": "2025-10-14T09:44:26Z",
"field": "mx",
"before": { ... },
"after": { ... }
}
]
}
}

The API returns change events in the changes array in reverse chronological order, with the most recent changes appearing first. This ordering applies to the timestamp field of each change event.

FieldDescription
domainThe domain name queried
countTotal number of historical changes available
registration_sourceData source used (parsed_whois or parsed_domain_rdap)
changesArray of change events

Each change event contains:

FieldDescription
timestampISO 8601 timestamp when the change was detected
fieldThe property that changed
beforeComplete state before the change (EnrichResult object)
afterComplete state after the change (EnrichResult object)

The before and after objects contain comprehensive domain profile data representing the state at that point in time. Available properties include:

  • Domain information: domain, tld, first_seen, active
  • Infrastructure: ip, mx, name_server, ssl_info
  • Registration: create_date, expiration_date, registrar, registrant_name, registrant_org
  • Contacts: admin_contact, billing_contact, registrant_contact, technical_contact
  • Web content: website_title, website_response, server_type, redirect, redirect_domain
  • Trackers: adsense, google_analytics, ga4, gtm_codes, fb_codes, and others
  • Risk: domain_risk (with risk_score and components)
  • Enrichment: parsed_whois, parsed_domain_rdap (when requested)

Retrieve the complete change history without filtering:

curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com'

Focus on IP, name server, and mail server modifications:

curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com&include_fields=ip,nameserver_host,mailserver_host'

Track registration changes across lifecycles

Section titled “Track registration changes across lifecycles”

Monitor registrar and registrant modifications:

curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com&include_fields=registrar,registrant,create_date,expiration_date,active'

Handle domains with extensive change history:

# First page
curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com&page_size=100&offset=0'
# Second page
curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com&page_size=100&offset=100'

Include full parsed WHOIS records in the response:

curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com&parsed_whois=true&include_fields=registrar,registrant'

Choosing between include_fields and exclude_fields

Section titled “Choosing between include_fields and exclude_fields”

Use include_fields when:

  • You need a specific subset of change types
  • You want to focus on a particular investigation area
  • You’re building targeted alerts or monitoring

Use exclude_fields when:

  • You want most changes but need to filter out noise
  • You’re excluding large categories (e.g., web trackers)
  • You need everything except a few specific types

Don’t use both parameters in the same request. If both are provided, the API behavior is undefined.

For large result sets:

  1. Start with a reasonable page_size (100-500)
  2. Use the offset parameter to navigate through pages
  3. Implement retry logic for network failures
  4. Consider rate limits when processing multiple domains

For targeted investigations:

  1. Use field filtering to reduce result volume
  2. Smaller page sizes (50-100) for faster initial response
  3. Process pages as needed rather than fetching all data upfront

Domain History complements:

  • Hosting History: Domain History provides granular change events; Hosting History provides summarized infrastructure timeline
  • WHOIS History: Domain History includes registration changes; WHOIS History provides raw WHOIS records
  • Iris Investigate: Use Domain History to understand how a domain reached its current state shown in Iris

Workflow example:

  1. Use Iris Investigate to identify a suspicious domain
  2. Query Domain History to understand its evolution
  3. Filter for infrastructure changes during active registration
  4. Cross-reference with WHOIS History for detailed registration records

Your subscription level determines rate limits and quotas. Monitor your usage through the Account Information endpoint:

curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/account/'

Best practices:

  • Implement exponential backoff for rate limit errors (HTTP 429)
  • Cache results when appropriate to reduce API calls
  • Use field filtering to minimize response size and processing time
  • Batch domain queries when investigating multiple domains

Problem: Unsure which field names are valid for filtering.

Solution: Make a request with an invalid field name to receive a complete list:

curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com&include_fields=show_me_all_fields'

The error response includes all valid field names.

Problem: Response contains thousands of changes, making it difficult to process.

Solution: Use field filtering to focus on relevant changes:

# Instead of retrieving all changes
curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com'
# Filter for specific change types
curl -H "X-Api-Key: $DOMAINTOOLS_API_KEY" \
'https://api.domaintools.com/v1/domain-history/?domain=example.com&include_fields=ip,registrar'

Problem: Query returns no changes or fewer changes than expected.

Possible causes:

  1. Domain has no history: Newly registered domains may not have change events yet
  2. Historical coverage limitation: For domains active before October 2021, no history event records the initial active status. Only changes after the October 2021 launch are captured.
  3. Overly restrictive filtering: Your include_fields or exclude_fields parameters may filter out all events
  4. Domain not found: Verify the domain name is correct and uses the apex domain (e.g., example.com, not www.example.com)

Solution: Start with an unfiltered query to verify data exists, then add filtering incrementally.

Problem: Pagination seems to skip results.

Solution: Increment the offset parameter by the page_size value for each request. For example, with page_size=100, use offset=0 for the first page, offset=100 for the second page, and offset=200 for the third page.

Problem: Receiving 401 Unauthorized errors.

Solutions:

  • Verify your API key is correct and active
  • Check that the X-Api-Key header is properly formatted
  • For HMAC authentication, ensure the timestamp is current (within 5 minutes)
  • Confirm your account has access to the Domain History API

Problem: Receiving 429 Too Many Requests errors.

Solutions:

  • Implement exponential backoff: wait before retrying
  • Check your rate limits via the Account Information endpoint
  • Reduce request frequency
  • Contact DomainTools support to discuss quota increases

For additional assistance, contact DomainTools Enterprise Support at enterprisesupport@domaintools.com.