Newly Active Domains (NAD)¶
The NAD feed lists domains that have become active in passive DNS, either for the first time or after a period of inactivity (at least 10 days). This helps identify when a previously dormant domain is being repurposed, a common tactic for attackers.
Overview¶
Domains are apex-level (for example, example.com but not www.example.com), and the feed emits them as they're observed.
Use this feed when you need to:
- Detect the reactivation of previously dormant domains
- Identify potentially suspicious infrastructure
- Monitor domains that might be used for malicious activities
- Integrate as a blocklist into DNS resolvers via RPZ
Inclusion criteria: Domains observed in passive DNS to be newly active in the latest lifecycle of the domain, either for the first time or after an inactive period of at least 10 days.
Requirements¶
You need the following to access Threat Feeds:
- An Enterprise Account with DomainTools, accessible at https://account.domaintools.com/my-account/
- Authentication credentials (API key for header authentication, or API username and key for HMAC or open key authentication)
- A way to interact with a REST API delivered through AWS CloudFront
Obtain your API credentials from your group's API administrator. API administrators can manage their API keys at https://research.domaintools.com, selecting the drop-down account menu and choosing API admin.
For assistance, contact enterprisesupport@domaintools.com.
Authentication¶
You can authenticate to the NAD APIs using three different methods. Choose the method that best fits your security requirements and technical environment.
API key (header) authentication¶
Authenticate your requests by including the API key in the header of each HTTP request. The API key serves as a unique identifier and authenticates your requests.
Required header:
X-Api-Key: YOUR_API_KEY
Examples:
# Feed API request
curl -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/feed/nad/?sessionID=mySOC'
# Download API request
curl -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/download/nad/'
HMAC authentication¶
HMAC authentication is a secure alternative to API key-based methods. It requires signing each request with a SHA1 HMAC digest derived from your API secret, providing integrity and authenticity without exposing credentials directly in the request.
This method is recommended for systems where authentication credentials shouldn't be stored in plain text or included directly in request URLs.
DomainTools supports MD5, SHA1, and SHA256 for the hashing algorithm.
Required query parameters:
api_username: Your DomainTools API usernamesignature: HMAC-SHA1 signature ofapi_username + timestamp + uri_pathtimestamp: Current UTC timestamp in ISO 8601 format (for example,2025-06-01T15:30:00Z)
Constructing the HMAC signature:
URI path must include API version
The uri_path parameter must include the API version prefix. For example, use /v1/feed/nod/ not /feed/nod/.
Example Python signing function:
import hmac
import hashlib
def sign(api_username, api_key, timestamp, uri):
params = f"{api_username}{timestamp}{uri}"
return hmac.new(api_key.encode("utf-8"), params.encode("utf-8"), hashlib.sha1).hexdigest()
HMAC timestamp requirements
The timestamp parameter in HMAC authentication must be current (within a few minutes of the server time). The timestamps shown in these examples are static for demonstration purposes. In production, generate a fresh timestamp for each request using your system's current time in ISO 8601 UTC format (e.g., 2025-01-06T15:30:00Z).
Examples:
# Feed API request with HMAC
curl 'https://api.domaintools.com/v1/feed/nad/?api_username=YOUR_USERNAME&signature=HMAC_SIGNATURE×tamp=2025-01-06T15:30:00Z&sessionID=mySOC'
# Download API request with HMAC
curl 'https://api.domaintools.com/v1/download/nad/?api_username=YOUR_USERNAME&signature=HMAC_SIGNATURE×tamp=2025-01-06T15:30:00Z'
Open key authentication¶
This is the easiest authentication scheme to implement, but also the least secure. Each request contains the full API key and API username as query parameters. We recommend using API key header authentication or HMAC authentication instead.
If you're unsure about your authentication options, contact enterprisesupport@domaintools.com.
Required query parameters:
api_username: Your API usernameapi_key: Your API key
Examples:
# Feed API request
curl 'https://api.domaintools.com/v1/feed/nad/?api_username=YOUR_USERNAME&api_key=YOUR_API_KEY&sessionID=mySOC'
# Download API request
curl 'https://api.domaintools.com/v1/download/nad/?api_username=YOUR_USERNAME&api_key=YOUR_API_KEY'
Real-time Feed API¶
The Feed API provides real-time access to current NAD data. Use this API to poll for the latest feed updates at regular intervals, maintain a session to track your position in the feed, and filter results based on your specific needs.
Base URL¶
Rate limits¶
Real-time feeds have the following rate limits:
- 2 queries per minute
- 120 queries per hour
If you exceed these limits, the API returns an error.
Response formats¶
The API supports two response formats:
NDJSON (Newline-Delimited JSON)
- Default format when no
Acceptheader is specified - Also known as JSON Lines (JSONL)
- One JSON object per line
- Efficient for streaming and processing large datasets
- Set
Accept: application/x-ndjsonto explicitly request this format
CSV (Comma-Separated Values)
- Set
Accept: text/csvto request CSV format - Add
&headers=1to the query parameters to include column headers as the first line - Not available for all feeds (for example, the Parsed Domain RDAP feed doesn't support CSV)
Session management¶
Session management allows you to maintain your position in the feed data stream, ensuring you don't miss or duplicate events when polling the API.
How sessions work:
- Start a new session: Provide a unique
sessionIDparameter of your choosing. By default, the API returns the past hour of results. - Resume a session: Use the same
sessionIDin subsequent requests. The API returns all data since your last request. - Handle large result sets: If a single request exceeds 10M results, the API returns an HTTP
206response code. Repeat the same request with the samesessionIDto receive the next batch of data until you receive an HTTP200response code. - Delete a session: Use an HTTP
DELETErequest with yoursessionIDto clear the saved offset and start fresh.
Session ID requirements:
- 1 to 64 characters in length
- Alphanumeric characters and hyphens only (
[a-zA-Z0-9-]+) - Case-sensitive
Quick start¶
The standard access pattern is to periodically request the most recent feed data, as often as every 60 seconds.
This starts a new session and returns the last hour of data. Subsequent calls with the same sessionID return data since the last request.
Parameters¶
sessionID¶
Type: String
Valid values: 1-64 alphanumeric characters and hyphens ([a-zA-Z0-9-]+)
Description: A unique identifier for the session, used for resuming data retrieval from the last point. Use a new sessionID to begin a new session, fetching the most recent hour by default. Reuse the same sessionID to return all feed data since your last request. If omitted, time window parameters (such as after/before) are required.
Example: sessionID=mySOC
Required: Yes, to continue where you left off (or use after/before instead)
after¶
Type: Integer or string
Valid values:
- Integer: -1 to -432,000 (relative seconds before current time)
- String: ISO 8601 datetime in UTC format (
YYYY-MM-DDTHH:MM:SSZ)
Description: The start of the query window (inclusive). When using an integer, the value is in seconds relative to the current time. When using a string, provide an absolute timestamp. The timestamp must represent a point between 1 second ago and 5 days ago, relative to the current UTC time.
Example: after=-60 or after=2024-10-16T10:20:00Z
Required: Yes, if before or sessionID not provided
before¶
Type: Integer or string
Valid values:
- Integer: -1 to -432,000 (relative seconds before current time)
- String: ISO 8601 datetime in UTC format (
YYYY-MM-DDTHH:MM:SSZ)
Description: The end of the query window (inclusive). When using an integer, the value is in seconds relative to the current time. When using a string, provide an absolute timestamp. The timestamp must represent a point between 1 second ago and 5 days ago, relative to the current UTC time.
Example: before=-120 or before=2024-10-16T10:20:00Z
Required: Yes, if after or sessionID not provided
domain¶
Type: String
Valid values: Domain character set restricted by the DNS specification (letters, digits, hyphens). International characters should be specified in punycode. A trailing dot is acceptable.
Description: Filter for an exact domain or a domain substring by prefixing or suffixing your string with *. Multiple parameters are supported (for example, ?domain=*apple*&domain=*microsoft*). The URL-encoded version of * (%2A) may be required in some clients.
Example: domain=*bank* or domain=example.com
Required: No
fromBeginning¶
Type: Boolean
Valid values: true
Description: Functions with new session IDs to return the first hour (rather than the last). Returns an error if the session ID already exists. Only the value true is accepted; any other value (including false) will be ignored or treated as omitted.
Example: fromBeginning=true
Required: No
top¶
Type: Integer
Valid values: Positive integer, 1-1,000,000,000
Description: Limits the number of results in the response payload. Primarily intended for testing. When you apply this parameter to risk feeds, results are sorted by overall_risk (descending).
Example: top=10
Required: No
headers¶
Type: Integer
Valid values: 1
Description: Adds a header row as the first line of the response when text/csv is requested. Set headers=1 to enable. Only applies when requesting CSV format. Only the value 1 is accepted; any other value is invalid.
Example: headers=1
Required: No
Response structure¶
The API returns responses in NDJSON (Newline-Delimited JSON), with each response containing one domain entry per line. Each entry contains a timestamp in ISO 8601 UTC format, and the domain.
Response fields:
timestamp (string): The observation timestamp in ISO 8601 UTC format.
- Example:
"timestamp":"2024-11-15T16:14:39Z"
domain (string): The domain name without the trailing dot. Domain character set restricted by the DNS specification (letters, digits, hyphens).
- Example:
"domain":"example.com"
Example NDJSON response:
{"timestamp":"2024-11-15T16:14:39Z","domain":"domiantools.com"}
{"timestamp":"2024-11-15T16:14:38Z","domain":"domsintools.com"}
{"timestamp":"2024-11-15T16:14:36Z","domain":"edomaintools.com"}
{"timestamp":"2024-11-15T16:14:35Z","domain":"omaintools.com"}
{"timestamp":"2024-11-15T16:14:35Z","domain":"v-domaintools.com"}
Example CSV response:
timestamp,domain
2024-11-15T16:14:39Z,domiantools.com
2024-11-15T16:14:38Z,domsintools.com
2024-11-15T16:14:36Z,edomaintools.com
Response codes¶
| Code | Status | Description |
|---|---|---|
200 |
OK | The request was successful and all data has been delivered |
206 |
Partial content | The request was successful, but only a portion of the data was returned. The request exceeded 10M results or the 1-hour evaluation window. Repeat the same request with the same sessionID to receive the next batch of data until you receive an HTTP 200 response |
400 |
Bad request | The request is malformed |
403 |
Forbidden | Missing or invalid API credentials |
404 |
Not found | The requested resource (such as a sessionID) doesn't exist |
406 |
Not acceptable | The specified Accept header value isn't supported. Only application/x-ndjson and text/csv are accepted |
422 |
Unprocessable entity | The request is syntactically valid but violates semantic or domain-specific rules (for example, invalid query parameter values) |
Examples¶
Basic session polling:
# Start a new session
curl -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/feed/nad/?sessionID=mySOC'
# Resume the session (returns data since last request)
curl -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/feed/nad/?sessionID=mySOC'
Time window filtering:
# Get data from a specific time range
curl -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/feed/nad/?after=2025-01-06T10:00:00Z&before=2025-01-06T11:00:00Z'
Domain filtering:
# Filter for specific domain patterns
curl -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/feed/nad/?domain=*.example.com&sessionID=mySOC'
CSV format:
# Request CSV format with headers
curl -H 'Accept: text/csv' -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/feed/nad/?headers=1&sessionID=mySOC'
# Request CSV format without headers
curl -H 'Accept: text/csv' -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/feed/nad/?sessionID=mySOC'
Handling large result sets:
# If you receive HTTP 206, repeat the request to get the next batch
curl -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/feed/nad/?sessionID=mySOC'
# Repeat until you receive HTTP 200
curl -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/feed/nad/?sessionID=mySOC'
Delete a session:
# Clear the saved offset and start fresh
curl -X DELETE -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/feed/nad/?sessionID=mySOC'
Download API¶
The Download API provides access to historical NAD data through temporary AWS S3 file links. Use this API to retrieve archived data you may have missed or to backfill your systems with historical information. Files are organized by hour and available for 90 days.
Base URL¶
Parameters¶
limit¶
Type: Integer
Valid values: Positive integer
Description: Limits the number of files returned in the response, starting from the most recent. Use to control payload size or test specific cases.
Example: limit=10
Required: No
Response structure¶
The API returns a JSON response containing an array of downloadable files. Each file entry includes:
download_name (string): The feed identifier (nad)
files (array): List of downloadable file entries
Each file object contains:
name(string): Path and filename of the downloadable filelast_modified(string): Timestamp of last modification in ISO 8601 UTC formatetag(string): ETag (hash) used to verify file identity and versioningsize(integer): File size in bytesurl(string): Temporary signed URL to download the file from AWS CloudFront
File naming convention:
- Data file:
nad/{YYYY-MM-DD}/nad-{YYYYMMDD}.{HH00}-{HH00}.json.gz - Checksum file:
nad/{YYYY-MM-DD}/nad-{YYYYMMDD}.{HH00}-{HH00}.json.gz.sha256
Example response:
{
"response": {
"download_name": "nad",
"files": [
{
"name": "nad/2024-11-19/nad-20241119.1900-2000.json.gz.sha256",
"last_modified": "2024-11-19T20:00:11+00:00",
"etag": "\"67a6d9b0973b2d31ffb779dc8f7f8cfa\"",
"size": 64,
"url": "https://download.example.com/nad/2024-11-19/nad-20241119.1900-2000.json.gz.sha256?Expires=..."
},
{
"name": "nad/2024-11-19/nad-20241119.1900-2000.json.gz",
"last_modified": "2024-11-19T20:00:11+00:00",
"etag": "\"67a6d9b0973b2d31ffb779dc8f7f8cfa\"",
"size": 140725,
"url": "https://download.example.com/nad/2024-11-19/nad-20241119.1900-2000.json.gz?Expires=..."
}
]
}
}
Response codes¶
| Code | Status | Description |
|---|---|---|
200 |
OK | The request was successful |
400 |
Bad request | The request is malformed |
403 |
Forbidden | Missing or invalid API credentials |
422 |
Unprocessable entity | The request is syntactically valid but violates semantic or domain-specific rules (for example, invalid query parameter values) |
File contents¶
The *.json.gz.sha256 file is a checksum containing a SHA-256 hash value used to verify the integrity of the downloaded file.
The *.json.gz file, when uncompressed, contains JSON data in the same format as the Feed API response (NDJSON with timestamp and domain fields).
Examples¶
List available files:
# Get the most recent files
curl -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/download/nad/?limit=10'
Download and verify a file:
# Get the file list
curl -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/download/nad/?limit=2' > files.json
# Extract the URL and download the data file
curl -o nad-data.json.gz "$(jq -r '.response.files[1].url' files.json)"
# Download the checksum file
curl -o nad-data.json.gz.sha256 "$(jq -r '.response.files[0].url' files.json)"
# Verify the integrity
sha256sum -c nad-data.json.gz.sha256
Batch processing:
# Download multiple files in a loop
for url in $(curl -H 'X-Api-Key: YOUR_API_KEY' \
'https://api.domaintools.com/v1/download/nad/?limit=24' | \
jq -r '.response.files[].url' | grep '\.json\.gz$'); do
curl -O "$url"
done
RPZ Access¶
The NAD feed is available via Response Policy Zone (RPZ) for direct integration with DNS firewalls.
Overview¶
Response Policy Zone (RPZ) provides DNS-level blocking by integrating threat feeds directly into your DNS resolver. This allows you to automatically block or redirect DNS queries for domains in the feed, providing real-time protection before connections are established.
How RPZ works:
When a user attempts to access a domain in the RPZ feed, your DNS resolver responds with an NXDOMAIN ("no such domain") status code, effectively making the domain unavailable. This blocks malicious domains at the DNS layer, preventing endpoint communication before any connection is established.
Benefits:
- Real-time protection: Blocks threats at the DNS resolver level
- Automatic updates: Receives updates via DNS zone transfers (AXFR/IXFR)
- No client configuration: Works transparently for all clients using your DNS resolver
- Efficient: Minimal performance impact on DNS resolution
- Standard protocol: Uses DNS Response Policy Zones specification
Zone naming format:
RPZ zones are named using the pattern: [interval].[feed].rpz.domaintools.com
Available time intervals: 5m, 10m, 30m, 1h, 3h, 12h (and 24h for some feeds)
Larger time intervals are supersets that include smaller intervals. Smaller intervals have smaller zone sizes and may be available faster.
Available zones¶
The NAD feed is available in the following RPZ zones:
5m.nad.rpz.domaintools.com- Last 5 minutes10m.nad.rpz.domaintools.com- Last 10 minutes30m.nad.rpz.domaintools.com- Last 30 minutes1h.nad.rpz.domaintools.com- Last 1 hour3h.nad.rpz.domaintools.com- Last 3 hours12h.nad.rpz.domaintools.com- Last 12 hours
Configuration¶
Configuration requirements:
To access RPZ feeds, you need to:
- Provide IP addresses: Contact enterprisesupport@domaintools.com with:
- IP address(es) from which you connect to the RPZ provider DNS server
-
IP address(es) to receive DNS
NOTIFYmessages (typically the same) -
Configure firewall: Add rules to allow DomainTools hosts to send UDP packets to port
53: - IPv4:
104.244.14.88Port:53 -
IPv4:
104.244.14.89Port:53 -
Set up TSIG authentication: DomainTools uses TSIG (Secret Key Transaction Authentication) for authorization:
- TSIG key algorithm:
hmac-sha512 - TSIG key and key name: Provided by DomainTools Enterprise Support
Delivery method:
RPZ feeds are delivered via:
- Incremental Zone Transfers (IXFR)
- Full zone transfers (AXFR)
- DNS
NOTIFYmessages to trigger zone updates
For detailed configuration instructions, including DNS resolver setup, advanced features (allowlists, walled gardens, logging), and troubleshooting, see the Response Policy Zone documentation.
Testing¶
Testing your RPZ configuration:
When your DNS resolver blocks a domain using RPZ, the response includes an SOA (Start of Authority) record that identifies which RPZ feed was used.
Test domain:
Each RPZ feed includes a test domain entry: test.rpz.domaintools.test
Use this to verify the RPZ feed is loaded and working. A successful test returns:
NXDOMAINstatus codeSOArecord in theADDITIONALsection showing the specific feed name
Example SOA record:
;; ADDITIONAL SECTION:
3h.nad.rpz.domaintools.com. 86400 IN SOA rpz-ns1.domaintools.com. noc.domaintools.com. 946684799 600 300 86400 86400
The SOA SERIAL number (Unix epoch timestamp) indicates when the feed was last regenerated.
Troubleshooting:
If the SOA record appears in the AUTHORITY section instead of ADDITIONAL, or doesn't show the specific feed name, the response didn't come from RPZ. Check your DNS resolver's RPZ-related logs for additional debugging information.
Examples¶
Test the RPZ feed:
# Query the test domain
dig test.rpz.domaintools.test
# Expected response includes NXDOMAIN and SOA record showing the feed name
# Example SOA in ADDITIONAL section:
# 3h.nad.rpz.domaintools.com. 86400 IN SOA rpz-ns1.domaintools.com. ...
Verify a specific zone is loaded:
# Test with the 1-hour NAD zone
dig @your-dns-server test.rpz.domaintools.test
# Check the SOA record shows: 1h.nad.rpz.domaintools.com