SecurityTrails
SecurityTrails provides comprehensive DNS and domain intelligence for attack surface mapping and reconnaissance. It combines historical DNS data, subdomain discovery, WHOIS information, and IP intelligence into a single platform with both web interface and RESTful API for automation.
Overview
섹션 제목: “Overview”SecurityTrails aggregates DNS resolution history, domain relationships, and IP intelligence to help identify exposed infrastructure. The platform maintains 20+ years of DNS records and enables attackers/defenders to map attack surfaces, discover forgotten subdomains, and track infrastructure changes over time.
Free vs Paid Tiers:
- Free: Limited lookups, basic domain/IP search, restricted API calls
- Researcher: 10K API calls/month, full historical DNS, WHOIS, subdomains
- Professional: 100K+ API calls/month, priority support, custom integrations
- Enterprise: Custom limits, dedicated support, white-label options
API Access:
- REST API with JSON responses
- Rate limiting based on tier (typically 1-10 requests/second)
- API key authentication required for all endpoints
- No OAuth/complex auth — simple header-based API keys
Web Interface
섹션 제목: “Web Interface”Domain Lookup
섹션 제목: “Domain Lookup”Navigate to the search bar and enter a domain (e.g., example.com). Results show:
- Current DNS records (A, AAAA, MX, NS, SOA, TXT)
- Subdomain list with record counts
- Historical snapshots (hover over dates)
- WHOIS details
- IP neighbors and related infrastructure
Subdomain Discovery
섹션 제목: “Subdomain Discovery”Click Subdomains tab on any domain to view:
- Complete subdomain enumeration
- DNS record types per subdomain
- Last seen date and first seen date
- Filter by record type (A, CNAME, MX, etc.)
- Export as CSV or JSON
Historical DNS Data
섹션 제목: “Historical DNS Data”Switch to History tab to examine:
- DNS changes over years/months/days
- Multiple historical snapshots
- IP address migration patterns
- DNS provider changes
- Deleted or inactive records
- Timeline view showing infrastructure evolution
Associated Domains
섹션 제목: “Associated Domains”Expand Associated Domains section to find:
- Domains sharing the same IP address
- Shared nameservers (NS lookup reverse)
- Shared MX records
- Parent/child domain relationships
- Domains registered to same entity
IP Explorer
섹션 제목: “IP Explorer”From any result, click an IP to access IP intelligence:
- All domains pointing to that IP
- Reverse DNS (PTR records)
- CIDR block ownership
- Autonomous System (AS) information
- Geolocation and ISP details
- Open ports and services (if available)
API Authentication
섹션 제목: “API Authentication”All SecurityTrails API requests require authentication via API key in the APIKEY header.
Get Your API Key:
- Create account at SecurityTrails website
- Navigate to API section in account settings
- Generate or view existing API key
- Keep key private — regenerate if exposed
Rate Limits:
- Free: 50 requests/month
- Researcher: 10,000 requests/month (~330/day)
- Professional: 100,000 requests/month
- Enterprise: Custom limits
- All plans: 10 requests/second max
Basic cURL Syntax:
curl -H "APIKEY: your_api_key_here" \
"https://api.securitytrails.com/v1/domain/example.com/details"
Check Rate Limit Status:
curl -I -H "APIKEY: your_api_key" \
"https://api.securitytrails.com/v1/domain/example.com/details" | \
grep "X-RateLimit"
Handle Rate Limit Errors:
# Check headers for remaining quota
# X-RateLimit-Remaining: 499
# X-RateLimit-Reset: 1609459200 (Unix timestamp)
# HTTP 429: Too Many Requests — wait until reset time
Domain Information API
섹션 제목: “Domain Information API”GET /domain/{hostname}/details
섹션 제목: “GET /domain/{hostname}/details”Retrieve comprehensive information about a domain in a single request.
curl -H "APIKEY: your_api_key" \
"https://api.securitytrails.com/v1/domain/example.com/details" | jq
Response Structure:
{
"domain": "example.com",
"last_dns_records": {
"a": [{"value": "93.184.216.34"}],
"aaaa": [{"value": "2606:2800:220:1:248:1893:25c8:1946"}],
"mx": [{"value": "mail.example.com", "priority": 10}],
"ns": [{"value": "a.iana-servers.net"}],
"soa": [{"value": "a.iana-servers.net hostmaster.iana.org 1 7200 3600 1209600 3600"}],
"txt": [{"value": "v=spf1 -all"}]
},
"subdomains": ["www", "mail", "ftp"],
"whois": {
"created": "1995-08-15",
"updated": "2021-08-06",
"expires": "2025-08-14",
"registrar": "VeriSign Global Registry Services"
}
}
Extract Specific Data:
# Get only A records
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/details" | \
jq '.last_dns_records.a[].value'
# Get all subdomains
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/details" | \
jq '.subdomains[]'
Subdomain Discovery
섹션 제목: “Subdomain Discovery”GET /domain/{hostname}/subdomains
섹션 제목: “GET /domain/{hostname}/subdomains”List all known subdomains for a domain with optional filtering.
curl -H "APIKEY: your_api_key" \
"https://api.securitytrails.com/v1/domain/example.com/subdomains?query=api"
Parameters:
query: Filter subdomains by string (e.g.,api,admin,dev)page: Pagination (default 1, max 100 results per page)limit: Results per page (1-100, default 100)
Example — Find Development Subdomains:
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/subdomains?query=dev" | \
jq '.subdomains[] | .subdomain'
# Output: api-dev.example.com, staging-dev.example.com, etc.
Pagination Example:
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/subdomains?page=2&limit=50"
Detect Wildcard DNS:
# If wildcard exists, *.example.com resolves
# Look for unusual subdomains that shouldn't exist
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/subdomains" | \
jq '.subdomains | length'
Historical DNS
섹션 제목: “Historical DNS”GET /history/{hostname}/dns/{type}
섹션 제목: “GET /history/{hostname}/dns/{type}”Retrieve historical DNS records (supports A, AAAA, MX, NS, SOA, TXT, CNAME, PTR).
curl -H "APIKEY: your_api_key" \
"https://api.securitytrails.com/v1/history/example.com/dns/a"
Track A Record Changes Over Time:
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/history/example.com/dns/a" | \
jq '.records[] | {first_seen: .first_seen, last_seen: .last_seen, values: .values[]}'
Monitor Infrastructure Changes:
# Check if domain moved to CDN
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/history/example.com/dns/a" | \
jq '.records[].values[] | .ip' | sort | uniq -c
# Identify IP pattern (CloudFlare IPs all start with 104.*)
MX Record History (Email Provider Changes):
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/history/example.com/dns/mx" | \
jq '.records[] | {first_seen, last_seen, value: .values[].exchange}'
NS Record Changes (Registrar Migrations):
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/history/example.com/dns/ns" | \
jq '.records[] | {seen: .first_seen, nameservers: .values[].nameserver}'
IP Intelligence
섹션 제목: “IP Intelligence”GET /ips/nearby/{ip}
섹션 제목: “GET /ips/nearby/{ip}”Find other IP addresses near a target IP (useful for discovering related infrastructure).
curl -H "APIKEY: your_api_key" \
"https://api.securitytrails.com/v1/ips/nearby/93.184.216.34"
Example Output:
{
"ips": [
{"ip": "93.184.216.33", "domains": ["example-mirror.com"]},
{"ip": "93.184.216.34", "domains": ["example.com", "www.example.com"]},
{"ip": "93.184.216.35", "domains": ["example-test.com"]}
]
}
Reverse DNS Lookup:
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/ips/nearby/93.184.216.34" | \
jq '.ips[] | select(.ip=="93.184.216.34") | .domains'
Map IP Neighbors:
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/ips/nearby/93.184.216.34" | \
jq '.ips[] | "\(.ip) — \(.domains | join(", "))"'
WHOIS Data
섹션 제목: “WHOIS Data”GET /domain/{hostname}/whois
섹션 제목: “GET /domain/{hostname}/whois”Retrieve WHOIS information including registrar, dates, and name servers.
curl -H "APIKEY: your_api_key" \
"https://api.securitytrails.com/v1/domain/example.com/whois"
Extract Key WHOIS Fields:
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/whois" | \
jq '{
created: .created_date,
expires: .expires_date,
updated: .updated_date,
registrar: .registrar,
registrant: .registrant,
nameservers: .nameservers
}'
Check Domain Expiration:
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/whois" | \
jq '.expires_date'
# Output: 2025-08-14 or similar
Find Domains by Registrar:
# Use bulk WHOIS API (if available in your plan)
# Pivot on registrar name to find related domains
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/whois" | \
jq '.registrar'
Associated Domains
섹션 제목: “Associated Domains”GET /domain/{hostname}/associated
섹션 제목: “GET /domain/{hostname}/associated”Find domains related via shared infrastructure (same IP, nameservers, MX records).
curl -H "APIKEY: your_api_key" \
"https://api.securitytrails.com/v1/domain/example.com/associated"
Reverse Nameserver Lookup (Shared NS):
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/whois" | \
jq '.nameservers[]'
# Then search for other domains using same nameservers
Find Sibling Domains (Same Organization):
# Use registrant info to pivot
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/whois" | \
jq '{registrant_org: .registrant_organization, admin: .admin_name}'
Shared IP Discovery:
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/details" | \
jq '.last_dns_records.a[0].value' | \
xargs -I {} curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/ips/nearby/{}"
Python Integration
섹션 제목: “Python Integration”Using Requests Library
섹션 제목: “Using Requests Library”import requests
import json
API_KEY = "your_api_key_here"
HEADERS = {"APIKEY": API_KEY}
def get_domain_info(domain):
url = f"https://api.securitytrails.com/v1/domain/{domain}/details"
resp = requests.get(url, headers=HEADERS)
return resp.json()
def get_subdomains(domain, query=""):
url = f"https://api.securitytrails.com/v1/domain/{domain}/subdomains"
params = {"query": query}
resp = requests.get(url, headers=HEADERS, params=params)
return resp.json()["subdomains"]
# Example usage
info = get_domain_info("example.com")
print(f"Subdomains: {info['subdomains']}")
subs = get_subdomains("example.com", query="api")
for sub in subs:
print(sub["subdomain"])
Bulk Enumeration Script
섹션 제목: “Bulk Enumeration Script”import requests
import time
API_KEY = "your_api_key"
HEADERS = {"APIKEY": API_KEY}
DOMAINS = ["example.com", "example.org", "example.net"]
def enumerate_all(domain):
results = {}
url = f"https://api.securitytrails.com/v1/domain/{domain}/details"
resp = requests.get(url, headers=HEADERS)
data = resp.json()
results["domain"] = domain
results["subdomains"] = data.get("subdomains", [])
results["a_records"] = [r["value"] for r in data["last_dns_records"].get("a", [])]
results["mx_records"] = [r["value"] for r in data["last_dns_records"].get("mx", [])]
time.sleep(0.5) # Rate limiting
return results
for domain in DOMAINS:
data = enumerate_all(domain)
print(json.dumps(data, indent=2))
Using securitytrails-py Wrapper
섹션 제목: “Using securitytrails-py Wrapper”pip install securitytrails
from securitytrails import SecurityTrails
st = SecurityTrails(api_key="your_api_key")
# Domain lookup
domain = st.get_domain("example.com")
print(domain.subdomains)
print(domain.dns)
# Subdomain enumeration
subs = st.get_subdomains("example.com", query="api")
# Historical DNS
history = st.get_dns_history("example.com", "a")
# IP intelligence
ip_data = st.get_ips_nearby("93.184.216.34")
Attack Surface Mapping Workflows
섹션 제목: “Attack Surface Mapping Workflows”Subdomain Enumeration
섹션 제목: “Subdomain Enumeration”#!/bin/bash
API_KEY="your_api_key"
TARGET="example.com"
# Get all subdomains
curl -s -H "APIKEY: $API_KEY" \
"https://api.securitytrails.com/v1/domain/$TARGET/subdomains?limit=100" | \
jq -r '.subdomains[] | .subdomain' > subdomains.txt
# Count results
wc -l subdomains.txt
Infrastructure Discovery
섹션 제목: “Infrastructure Discovery”#!/bin/bash
# Map IP space of target organization
API_KEY="your_api_key"
DOMAIN="example.com"
# Get main IP
IP=$(curl -s -H "APIKEY: $API_KEY" \
"https://api.securitytrails.com/v1/domain/$DOMAIN/details" | \
jq -r '.last_dns_records.a[0].value')
echo "Main IP: $IP"
# Find nearby IPs
curl -s -H "APIKEY: $API_KEY" \
"https://api.securitytrails.com/v1/ips/nearby/$IP" | \
jq '.ips[] | {ip, domains}' | tee infrastructure.json
DNS Change Monitoring
섹션 제목: “DNS Change Monitoring”import requests
import json
from datetime import datetime
API_KEY = "your_api_key"
DOMAIN = "example.com"
HEADERS = {"APIKEY": API_KEY}
def track_dns_changes(domain, record_type="a"):
url = f"https://api.securitytrails.com/v1/history/{domain}/dns/{record_type}"
resp = requests.get(url, headers=HEADERS)
records = resp.json()["records"]
for record in records:
print(f"Record: {record['values']}")
print(f"First seen: {record['first_seen']}")
print(f"Last seen: {record['last_seen']}")
print()
track_dns_changes(DOMAIN)
Certificate Transparency Feed
섹션 제목: “Certificate Transparency Feed”# Combine SecurityTrails with crt.sh data
# Get subdomains from SecurityTrails
SUBS=$(curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/subdomains" | \
jq -r '.subdomains[] | .subdomain')
# Cross-reference with CT logs
for sub in $SUBS; do
echo "Checking CT logs for: $sub.example.com"
# Use curl to query crt.sh API
done
Integration with Other Tools
섹션 제목: “Integration with Other Tools”Feed Subfinder
섹션 제목: “Feed Subfinder”# SecurityTrails data enriches Subfinder results
# Use API to get subdomains, then validate with Subfinder
API_KEY="your_api_key"
DOMAIN="example.com"
curl -s -H "APIKEY: $API_KEY" \
"https://api.securitytrails.com/v1/domain/$DOMAIN/subdomains" | \
jq -r '.subdomains[] | .subdomain' | \
sed "s/^/$DOMAIN/" > st_subs.txt
# Combine with Subfinder
subfinder -d $DOMAIN -o subfinder_subs.txt
cat st_subs.txt subfinder_subs.txt | sort -u > all_subs.txt
Enrich Maltego Graphs
섹션 제목: “Enrich Maltego Graphs”# Export SecurityTrails data to Maltego-compatible format
import requests
import csv
API_KEY = "key"
DOMAIN = "example.com"
HEADERS = {"APIKEY": API_KEY}
url = f"https://api.securitytrails.com/v1/domain/{DOMAIN}/details"
data = requests.get(url, headers=HEADERS).json()
with open("maltego_import.csv", "w") as f:
writer = csv.writer(f)
writer.writerow(["Entity Type", "Value", "Notes"])
for sub in data["subdomains"]:
writer.writerow(["Domain", sub, "SecurityTrails"])
for ip in [r["value"] for r in data["last_dns_records"]["a"]]:
writer.writerow(["IPv4Address", ip, "SecurityTrails"])
Combine with Shodan
섹션 제목: “Combine with Shodan”#!/bin/bash
# Find open ports on SecurityTrails IPs using Shodan
API_KEY_ST="securitytrails_key"
API_KEY_SHODAN="shodan_key"
DOMAIN="example.com"
# Get IPs from SecurityTrails
IPS=$(curl -s -H "APIKEY: $API_KEY_ST" \
"https://api.securitytrails.com/v1/domain/$DOMAIN/details" | \
jq -r '.last_dns_records.a[].value')
for IP in $IPS; do
echo "Searching Shodan for: $IP"
curl -s "https://api.shodan.io/shodan/host/$IP?key=$API_KEY_SHODAN" | \
jq '.ports[]'
done
Troubleshooting
섹션 제목: “Troubleshooting”API Key Not Working:
- Verify key in account settings (may have been regenerated)
- Check for leading/trailing whitespace in key
- Ensure APIKEY header is exact case (not apikey or Api-Key)
Rate Limit Exceeded:
# Check when limit resets
curl -I -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/details" | \
grep -i ratelimit
# Wait until X-RateLimit-Reset timestamp
# Implement exponential backoff in automation
No Subdomains Found:
- Domain may be private/protected
- SecurityTrails may not have indexed it yet
- Use multiple enumeration sources (Subfinder, Amass, crt.sh)
Missing Historical Data:
- Not all domains have complete history
- Paid tiers have access to more snapshots
- Older records (pre-2010) may not be available
JSON Parse Errors:
# Check raw response
curl -v -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/details"
# Validate with jq
curl -s -H "APIKEY: key" \
"https://api.securitytrails.com/v1/domain/example.com/details" | jq . > /dev/null
Best Practices
섹션 제목: “Best Practices”| Practice | Details |
|---|---|
| API Key Security | Never commit keys to Git; use environment variables or .env files |
| Rate Limiting | Implement delays between requests; use time.sleep(0.5) in Python |
| Caching | Cache results locally; don’t repeat API calls for same domain |
| Error Handling | Check HTTP status codes; handle 429 (rate limit) gracefully |
| Data Validation | Verify DNS records with live queries before using in tests |
| Pagination | Use page/limit parameters for domains with many subdomains (>100) |
| Historical Pivots | Track IP/NS/MX changes over time to identify infrastructure evolution |
| Combine Sources | Use SecurityTrails + Subfinder + crt.sh for comprehensive enumeration |
| Bulk Operations | Use batch/script mode; avoid manual lookup loops |
| Documentation | Log which tool discovered which subdomain for reporting |
Related Tools
섹션 제목: “Related Tools”| Tool | Purpose | Complementary Use |
|---|---|---|
| Subfinder | Fast subdomain enumeration | Validate SecurityTrails findings |
| Amass | Deep OSINT + subdomain intel | Combine results from both sources |
| DNSDumpster | Visual DNS reconnaissance | Compare against SecurityTrails |
| crt.sh | Certificate transparency logs | Find new subdomains from CT |
| Censys | IP/certificate database | Enrich IP intelligence data |
| Shodan | Open port discovery | Find services on SecurityTrails IPs |
| Maltego | Graph visualization | Import SecurityTrails data for mapping |
| WHOIS CLI | Direct WHOIS lookups | Validate SecurityTrails WHOIS data |
| dig/nslookup | Live DNS queries | Verify SecurityTrails historical data |
| Burp Suite | Web scanning | Use SecurityTrails scope for enumeration |