spatie/dns
Fetch DNS records in PHP using dig. Query domains for A, AAAA, CNAME, MX, TXT, SRV and more, filter by type(s), and get structured record objects with handy accessors for record details.
Installation:
composer require spatie/dns
No additional configuration is required for basic usage.
First Use Case:
Fetch all DNS records for a domain (e.g., google.com):
use Spatie\Dns\Dns;
$records = Dns::getRecords('google.com');
dd($records); // Returns a collection of DNSRecord objects
Key Classes:
Dns: Main facade for querying DNS records.DNSRecord: Represents individual records (e.g., A, MX, TXT).DnsException: Handle DNS-related errors.Where to Look First:
src/DnsServiceProvider.php (service provider setup).src/Dns.php (core facade logic).Filter records by type (e.g., MX, TXT, A):
$mxRecords = Dns::getRecords('example.com')->whereType('MX');
$txtRecords = Dns::getRecords('example.com')->whereType('TXT');
Avoid repeated DNS lookups by caching results (e.g., for rate-limited APIs or slow DNS providers):
$records = Cache::remember("dns_records_{$domain}", now()->addHours(1), function () use ($domain) {
return Dns::getRecords($domain);
});
Use try-catch blocks for DNS resolution errors:
try {
$records = Dns::getRecords('nonexistent.example');
} catch (DnsException $e) {
Log::error("DNS lookup failed for nonexistent.example: " . $e->getMessage());
// Fallback logic (e.g., return cached data or default values)
}
Offload DNS lookups to background jobs (e.g., for bulk domain checks):
use Spatie\Dns\Jobs\GetRecords;
GetRecords::dispatch('example.com')
->afterCommit() // Optional: Run after DB commit
->onQueue('dns');
Extend the package to support custom DNS resolvers (e.g., internal DNS servers):
use Spatie\Dns\DnsProvider;
class CustomDnsProvider implements DnsProvider {
public function getRecords(string $domain): array {
// Implement custom logic (e.g., call internal API)
return ['type' => 'A', 'data' => '192.0.2.1'];
}
}
// Register in AppServiceProvider:
Dns::extend('custom', function () {
return new CustomDnsProvider();
});
// Usage:
Dns::onProvider('custom')->getRecords('example.com');
Process multiple domains efficiently:
$domains = ['google.com', 'github.com', 'spatie.be'];
$results = collect($domains)->map(fn ($domain) => Dns::getRecords($domain));
Validate domain ownership via DNS (e.g., check for TXT records):
$txtRecords = Dns::getRecords($domain)->whereType('TXT');
$hasVerification = $txtRecords->contains(fn ($record) =>
str_contains($record->data, 'verification-code=12345')
);
MX records).TXT entries).Spatie\Dns\Dns in unit tests:
$this->mock(Spatie\Dns\Dns::class, function ($mock) {
$mock->shouldReceive('getRecords')
->with('example.com')
->andReturn(collect([new DNSRecord(['type' => 'A', 'data' => '1.1.1.1'])]));
});
chunk() or cursor() for large datasets.Spatie\Async for concurrent DNS lookups:
use Spatie\Async\Parallel;
Parallel::make($domains)->each(function ($domain) {
return Dns::getRecords($domain);
});
Rate Limiting:
8.8.8.8) throttle requests.use Symfony\Component\Process\Exception\ProcessTimedOutException;
try {
$records = Dns::getRecords($domain);
} catch (ProcessTimedOutException $e) {
sleep(2); // Wait before retry
retry();
}
TTL (Time-to-Live) Caching:
Dns::flushCache() (if supported) or implement local caching with short TTLs.DNSSEC Validation:
rubensworks/dnssec-validator for additional checks.Non-Standard Record Types:
CAA, SRV) may not be parsed correctly.DNSRecord or pre-process raw data:
$rawRecords = Dns::getRecords($domain, true); // Get raw output
Local Development:
/etc/hosts or C:\Windows\System32\drivers\etc\hosts overrides are present.google.com) or mock DNS responses.Case Sensitivity:
$domain = strtolower($domain);
Enable Verbose Output:
Dns::enableVerboseOutput(); // Logs raw DNS queries/responses
Check Underlying Process:
The package uses exec() to call dig or nslookup. Verify these tools are installed:
dig google.com
nslookup google.com
Inspect Raw Data: Access raw DNS output for debugging:
$rawOutput = Dns::getRecords($domain, true);
dd($rawOutput);
Common Errors:
dig/nslookup is installed.
Fix: Install via brew install bind (macOS) or apt-get install dnsutils (Linux).max_execution_time or use a faster DNS provider.Default DNS Provider:
The package defaults to dig on Unix-like systems and nslookup on Windows. Override in config/dns.php:
'provider' => 'custom', // Must match a registered provider
Custom DNS Servers: Configure a specific DNS server (e.g., Cloudflare):
Dns::setDnsServer('1.1.1.1'); // Cloudflare
$records = Dns::getRecords('example.com');
Environment-Specific Settings: Use Laravel's config caching to switch providers per environment:
// config/dns.php
'provider' => env('DNS_PROVIDER', 'dig'),
Spatie\Dns\DnsProvider for APIs (e.g., AWS Route 53, Cloudflare):
class CloudflareDnsProvider implements DnsProvider {
public function getRecords(string $domain): array {
$response = Http::get("https://
How can I help you explore Laravel packages today?