Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Rdap Laravel Package

spatie/laravel-rdap

Query domain registration data in Laravel with RDAP, the structured JSON successor to WHOIS. This package wraps basic RDAP lookups and adds response caching, configurable TLD server caching, and automatic retries with timeouts for unreliable endpoints.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its config:

composer require spatie/laravel-rdap
php artisan vendor:publish --tag="rdap-config"

Start by reviewing config/rdap.php. The important knobs are:

  • tld_servers_cache.store_name and duration_in_seconds for the IANA TLD-to-RDAP-server mapping.
  • domain_queries.timeout_in_seconds, retry_times, and sleep_in_milliseconds_between_retries.
  • ip_queries equivalents for IP lookups.

The first practical use case is a domain lookup:

use Spatie\Rdap\Facades\Rdap;

$domain = Rdap::domain('google.com'); // DomainResponse|null

if ($domain === null) {
    // Domain does not exist, or RDAP could not return a usable response.
}

$domain->registrationDate();
$domain->expirationDate();
$domain->lastChangedDate();
$domain->lastUpdateOfRdapDb();

Before building UI around lookups, inspect the raw shape with $domain->all(). The package intentionally exposes the standardized RDAP JSON via all() and get('dot.path'), so most day-to-day work is understanding that payload rather than relying only on the convenience date methods. The test fixture for google.com is the best first reference for the response structure.

A sensible first integration is an artisan command or queued job that enriches a list of domains with registration/expiration dates and status flags. Do not start by calling RDAP synchronously from a user-facing controller for many domains.

Implementation Patterns

Wrap the facade behind your own service. The package is small and the facade is convenient, but wrapping it gives you one place to normalize nulls, catch exceptions, add your own caching, and swap implementations in tests.

final class DomainLookup
{
    public function find(string $domain): ?array
    {
        if (! Rdap::domainIsSupported($domain)) {
            return null;
        }

        try {
            $response = Rdap::domain($domain);
        } catch (\Spatie\Rdap\Exceptions\RdapException $e) {
            report($e);
            return null;
        }

        return $response?->all();
    }
}

Use domainIsSupported() as a preflight check, not a guarantee. It checks whether the TLD has a known RDAP server. A supported TLD can still fail at query time or return null. Treat it as a cheap way to avoid obviously unsupported domains and to drive UI messaging such as “RDAP is not available for .be domains.”

Persist raw responses plus normalized columns. For a domain monitoring feature, store the full all() JSON for audit/debugging, and also extract the fields you query often:

$domain = Rdap::domain($domainName);

DomainCheck::updateOrCreate(
    ['domain' => $domainName],
    [
        'raw' => $domain?->all(),
        'registered_at' => $domain?->registrationDate(),
        'expires_at' => $domain?->expirationDate(),
        'changed_at' => $domain?->lastChangedDate(),
        'checked_at' => now(),
    ],
);

This avoids repeatedly hitting RDAP for dashboard rendering and lets you handle schema differences across registries later.

Use status checks for compliance or risk workflows. The DomainStatus enum makes status checks readable:

use Spatie\Rdap\Enums\DomainStatus;

$isTransferLocked = $domain->hasStatus(DomainStatus::ClientTransferProhibited);

This is useful for domain expiry monitoring, transfer readiness checks, and registrar/account audits.

Use custom RDAP servers deliberately. If you know the registry endpoint, bypass TLD discovery:

$domain = Rdap::domain(
    'google.com',
    dnsServer: 'https://rdap.verisign.com/com/v1/',
);

This is useful for testing against a controlled endpoint, working with a private RDAP server, or avoiding TLD cache issues during debugging. It also means you own the server choice and must pass a valid base URL.

Use the DNS helper for validation and diagnostics. Rdap::dns() exposes the IANA-derived mapping:

$dns = Rdap::dns();

$dns->getServerForDomain('google.com');
$dns->getServerForTld('com');
$dns->supportedTlds();

This is useful for building an “is this domain checkable?” validator, debugging why a lookup returns null, or showing supported TLDs in an admin panel. For IP lookups, the documented helper is RdapIpV4:

use Spatie\Rdap\RdapIpV4;

$ipv4 = new RdapIpV4();
$ipv4->getServerForIp('216.58.207.206');

Run bulk lookups in jobs or commands with explicit retry policy. RDAP endpoints are inconsistent. For batch enrichment, override the retry settings per call where needed and catch RdapException at the job boundary:

$domain = Rdap::domain(
    'example.com',
    timeoutInSeconds: 10,
    retryTimes: 4,
    sleepInMillisecondsBetweenRetries: 2000,
);

For many domains, add your own rate limiting and backoff. The package’s retry logic handles transient failures, but it does not make bulk querying polite or cheap.

Test behind your own abstraction. Because the package returns arrays and simple response objects, your application tests can fake your DomainLookup service rather than hitting RDAP. If you need package-level tests, use stored RDAP JSON fixtures from the package’s test support and feed them through your own parser/service. Avoid depending on live RDAP endpoints in CI.

Gotchas and Tips

Not all TLDs are supported. The README explicitly uses .be as an unsupported example. domainIsSupported() returning false is expected for those TLDs, but domain() returning null can also mean the domain does not exist. If the distinction matters, check domainIsSupported() first and treat later null as “no usable RDAP result.”

Do not assume domain query results are cached. The config exposes caching for the TLD server mapping, not for Rdap::domain() responses. The README’s caching claim is easy to over-read. Cache your own domain/IP results if you need repeatable performance.

The default retry policy can make a web request very slow. With a 5-second timeout, 3 retries, and 1-second sleeps, a failing lookup can tie up a request for many seconds. In HTTP controllers, use a shorter timeout or move lookups to a queue. In jobs, use longer retries and let the queue handle failure.

Catch the base exception. RdapRequestTimedOut and InvalidRdapResponse both implement Spatie\Rdap\Exceptions\RdapException. Catch the base class for a single failure path:

try {
    $domain = Rdap::domain($domainName);
} catch (\Spatie\Rdap\Exceptions\RdapException $e) {
    // timeout or invalid response
}

Beware named-argument typos in the README. The README shows timeoutInSecons, which looks like a documentation typo. Verify the actual method signature before using named arguments, or use positional arguments if you are unsure. This is exactly the kind of thing to check when pinning a package version.

Inspect all() before writing extraction code. RDAP responses vary by registry. Convenience methods cover dates and statuses, but registrar, registrant, nameserver, notices, and remarks data usually need get() or raw array traversal. Use all() once for a representative domain and write extraction against that fixture.

Use dot notation carefully. get('links.0.value') works for nested arrays, but keys containing literal dots would be ambiguous. RDAP property names generally do not contain dots, so this is usually fine, but normalize data before storing it in formats that also use dots as separators.

Clear the cache when changing TLD server config. If you change tld_servers_cache.store_name or duration, clear the relevant cache store. Otherwise you may keep an old IANA mapping for up to the configured duration, which can make new TLDs appear unsupported or point at stale servers.

Use dnsServer for debugging. If a lookup fails and you are unsure whether the problem is TLD discovery or the registry endpoint, pass a known RDAP server directly. If that works, investigate the cached TLD mapping or IANA data. If it still fails, inspect timeouts, response validity, and the registry’s availability.

Check IPv6 support before relying on it. The README discusses IPv4/IPv6 registries but documents RdapIpV4 with getServerForIp(). If your application handles IPv6, verify the available API in the installed version rather than assuming a symmetric RdapIpV6 class exists.

Pin and wrap the package. This is a small, low-dependent package with a narrow API. Pinning the version and using your own service wrapper protects your application from facade signature changes, README inconsistencies, and future response-shape assumptions.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core