W3docs

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 the getdns extension, a third-party resolver library (such as react/dns), or the narrower helpers checkdnsrr() and gethostbyname() 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
ParameterDescription
$hostnameThe domain name to look up, e.g. "php.net".
$typeA DNS_* constant selecting the record type. Optional; defaults to DNS_ANY. You can OR constants together — `DNS_A
&$authoritative_name_serversFilled by reference with the authoritative nameserver (NS) records returned in the response's authority section.
&$additional_recordsFilled by reference with the additional (glue) records the server returns.
$rawWhen 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.

ConstantRecordType-specific keys
DNS_AIPv4 addressip
DNS_AAAAIPv6 addressipv6
DNS_MXMail exchangerpri, target
DNS_NSAuthoritative nameservertarget
DNS_CNAMECanonical name (alias)target
DNS_TXTText record (SPF, verification)txt, entries
DNS_SOAStart of authoritymname, rname, serial, …
DNS_ANYAny type the resolver returnsvaries

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_ANY vs combining constants. DNS_ANY issues a single ANY query, 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 on DNS_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.

Practice

Practice
What is the purpose of the dns_get_record() function in PHP?
What is the purpose of the dns_get_record() function in PHP?
Was this page helpful?