PHP dns_get_record() Function: Everything You Need to Know
As a PHP developer, you may need to obtain various types of DNS records for a domain name. In such scenarios, the PHP dns_get_record() function comes in handy.
When your code needs to look up the mail server for a domain, verify that a hostname resolves, or read the SPF/TXT records behind an email-deliverability check, you need access to the Domain Name System (DNS). PHP's built-in dns_get_record() function performs that lookup at the protocol level and hands you the records back as a PHP array — no shelling out to dig required.
This chapter covers the function's signature, the record types it can fetch, the exact shape of the array it returns, how to read the authoritative and additional sections of a DNS response, and the gotchas that trip people up (especially the difference between DNS_ANY and combining specific constants).
Deprecation notice.
dns_get_record()was deprecated in PHP 8.3 and is scheduled for removal in a later release. For new code, prefer thegetdnsextension, a third-party resolver library (such asreact/dns), or the narrower helperscheckdnsrr()andgethostbyname()when you only need a yes/no answer or a single A record. The concepts below still apply to those alternatives.
What dns_get_record() does
dns_get_record() queries DNS for one domain name and returns the matching resource records as an array of associative arrays. You choose which record type to fetch (A, MX, TXT, etc.). Unlike gethostbyname(), which only resolves a hostname to a single IPv4 address, dns_get_record() exposes the full record — TTL, priority, target, and type-specific fields.
Syntax
dns_get_record(
string $hostname,
int $type = DNS_ANY,
array &$authoritative_name_servers = null,
array &$additional_records = null,
bool $raw = false
): array|false| Parameter | Description |
|---|---|
$hostname | The domain name to look up, e.g. "php.net". |
$type | A DNS_* constant selecting the record type. Optional; defaults to DNS_ANY. You can OR constants together — `DNS_A |
&$authoritative_name_servers | Filled by reference with the authoritative nameserver (NS) records returned in the response's authority section. |
&$additional_records | Filled by reference with the additional (glue) records the server returns. |
$raw | When true, queries only the exact $type and returns records in raw form. Defaults to false. |
It returns an array of records, or false on failure (for example, when the hostname does not exist or the resolver is unreachable).
A basic lookup
Each returned record is an associative array. Every record carries the keys host, class, type, and ttl; the remaining keys depend on the record type.
<?php
$records = dns_get_record("php.net", DNS_A);
print_r($records);A typical result looks like this (the IP and TTL will vary):
Array
(
[0] => Array
(
[host] => php.net
[class] => IN
[ttl] => 3600
[type] => A
[ip] => 185.85.0.29
)
)Because the result is a plain array, you iterate it with foreach and read each record's fields directly:
<?php
foreach (dns_get_record("php.net", DNS_A) as $record) {
echo $record['host'] . " -> " . $record['ip'] . "\n";
}Common record types
Pass one of these DNS_* constants as the $type argument. The type-specific keys you can expect are listed alongside each.
| Constant | Record | Type-specific keys |
|---|---|---|
DNS_A | IPv4 address | ip |
DNS_AAAA | IPv6 address | ipv6 |
DNS_MX | Mail exchanger | pri, target |
DNS_NS | Authoritative nameserver | target |
DNS_CNAME | Canonical name (alias) | target |
DNS_TXT | Text record (SPF, verification) | txt, entries |
DNS_SOA | Start of authority | mname, rname, serial, … |
DNS_ANY | Any type the resolver returns | varies |
To fetch several types at once, combine the constants with the bitwise OR operator (|):
<?php
// A + MX records in a single call
$records = dns_get_record("php.net", DNS_A | DNS_MX);
foreach ($records as $record) {
echo $record['type'] . "\n";
}Gotcha —
DNS_ANYvs combining constants.DNS_ANYissues a singleANYquery, and many resolvers and authoritative servers now refuse or truncate it (RFC 8482). If you want specific records, OR the precise constants together (DNS_A | DNS_MX | DNS_TXT) rather than relying onDNS_ANY— it is more reliable and more efficient.
Reading authoritative and additional records
The third and fourth parameters are filled by reference. They expose the authority and additional sections of the DNS response, which is useful when you need the nameservers that answered or the glue A-records for an MX target:
<?php
$authns = [];
$addtl = [];
$records = dns_get_record("php.net", DNS_MX, $authns, $addtl);
echo "MX records: " . count($records) . "\n";
echo "Authoritative NS: " . count($authns) . "\n";
echo "Additional records: " . count($addtl) . "\n";Handling failure
dns_get_record() returns false when the lookup fails. Always check for it before iterating, otherwise a foreach over false triggers a warning:
<?php
$records = dns_get_record("definitely-not-a-real-domain.invalid", DNS_A);
if ($records === false || $records === []) {
echo "No records found.\n";
} else {
print_r($records);
}For a simple "does this record exist?" check, checkdnsrr() is lighter weight, since it returns a boolean instead of building the full record array.
Practical example: validate an email domain's MX
A common real-world use is confirming that an email address belongs to a domain that can actually receive mail — handy after filter_var() has validated the address format:
<?php
function domainCanReceiveMail(string $email): bool
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return false;
}
$domain = substr(strrchr($email, "@"), 1);
$mx = dns_get_record($domain, DNS_MX);
return is_array($mx) && count($mx) > 0;
}
var_dump(domainCanReceiveMail("[email protected]")); // bool(true)Format validation and MX existence are necessary but not sufficient — they don't prove the specific mailbox exists. They are a cheap first filter that catches typos and throwaway domains before you attempt to send.
Conclusion
dns_get_record() gives PHP direct, structured access to DNS data: pick a record type with a DNS_* constant, iterate the returned array, and read the type-specific fields. Prefer ORing precise constants over DNS_ANY, always guard against a false return, and reach for checkdnsrr() or gethostbyname() when you need a narrower answer. Because the function is on its way out of PHP, isolate DNS lookups behind a small helper so you can swap in the getdns extension or a resolver library later without touching the rest of your code.