Skip to content

Domain History API

Note

The Domain History API endpoint is also specified in the Lookups and Monitor OpenAPI specification.

Quick start

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

Introduction

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.

Core concepts

Change Events

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.

Registration Source

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.

Active Registration Period

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.

Historical Coverage

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 Behavior

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

Use cases

Detect infrastructure weaponization

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

Monitor service activation

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

Identify ownership changes

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

Authentication

The Domain History API supports three authentication methods.

Header authentication

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

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

HMAC authentication

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.

Open key authentication

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

Request parameters

Required parameters

Parameter Description Example
domain The domain name to retrieve history for domaintools.com

Filtering parameters

Parameter Description Example
include_fields Comma-separated list of fields to include. Only change events matching these fields appear in results. ip,mx,name_server
exclude_fields Comma-separated list of fields to exclude. Change events matching these fields are omitted from results. ssl_information,web_trackers_information

Pagination parameters

Parameter Description Default Example
page_size Number of results per page. Maximum is 100 entries per request. 100 50
offset Starting 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. 0 500
next Boolean 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. false true

Registration data source flags

Parameter Description Default
parsed_whois Include full parsed WHOIS record in before and after objects false
parsed_domain_rdap Include full parsed Domain RDAP record in before and after objects false

Optional parameters

Parameter Description Example
format Response format (json, xml, html) json
app_partner Your product name (for debugging) MySecurityPlatform
app_name Your appliance, module, or playbook name ThreatIntel
app_version Your integration version 2.1.0

Understanding field filtering

How filtering works

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.

Parameter format requirements

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.

Individual vs. aggregate field filtering

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

Valid field names

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 & 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

Discovering available 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: YOUR_API_KEY' \
  'https://api.domaintools.com/v1/domain-history/?domain=example.com&include_fields=invalid_field_name'

Filtering examples

Include only infrastructure changes:

# Returns events where field: "ip", "mx", or "name_server"
curl -H 'X-Api-Key: YOUR_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: YOUR_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: YOUR_API_KEY' \
  'https://api.domaintools.com/v1/domain-history/?domain=example.com&include_fields=create_date,expiration_date,registrar,registrant,active'

Response structure

Response format

{
  "response": {
    "domain": "example.com",
    "count": 1234,
    "registration_source": "parsed_whois",
    "changes": [
      {
        "timestamp": "2025-10-14T09:44:26Z",
        "field": "mx",
        "before": { ... },
        "after": { ... }
      }
    ]
  }
}

Result ordering

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.

Response fields

Field Description
domain The domain name queried
count Total number of historical changes available
registration_source Data source used (parsed_whois or parsed_domain_rdap)
changes Array of change events

Change event structure

Each change event contains:

Field Description
timestamp ISO 8601 timestamp when the change was detected
field The property that changed
before Complete state before the change (EnrichResult object)
after Complete state after the change (EnrichResult object)

EnrichResult objects

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)

Common workflows

Get all changes for a domain

Retrieve the complete change history without filtering:

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

Filter for infrastructure changes only

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

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

Track registration changes across lifecycles

Monitor registrar and registrant modifications:

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

Paginate through large result sets

Handle domains with extensive change history:

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

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

Combine with parsed WHOIS data

Include full parsed WHOIS records in the response:

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

Best practices

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.

Pagination strategies

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

Combining with other DomainTools APIs

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

Rate limits and quotas

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

curl -H 'X-Api-Key: YOUR_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

Troubleshooting

Understanding field names

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: YOUR_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.

Handling large response sets

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: YOUR_API_KEY' \
  'https://api.domaintools.com/v1/domain-history/?domain=example.com'

# Filter for specific change types
curl -H 'X-Api-Key: YOUR_API_KEY' \
  'https://api.domaintools.com/v1/domain-history/?domain=example.com&include_fields=ip,registrar'

Empty results

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.

Pagination issues

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.

Authentication errors

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

Rate limit errors

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

Additional resources

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