io-developer/php-whois
PHP WHOIS client for looking up domain, IPv4/IPv6, and ASN registration data. It selects the right WHOIS servers, parses responses into clean objects, supports caching, rate limiting, retries, and PSR-18 HTTP clients, handles IDN and UTF-8, and works with no external dependencies.
Architecture fit. This is a framework-agnostic PHP library that does two things: (1) resolves and queries port-43 WHOIS servers, and (2) parses the raw text into a Domain/Asn value object (registrar, created/updated/expiry dates, nameservers, status codes, and — where the registry is "thick" and not redacted — registrant fields). It is a data-acquisition dependency, not application infrastructure. That makes it a good fit for domain portfolio monitoring, expiry alerting, ownership/registrant verification, abuse triage, and ASN enrichment; and a poor fit as the authoritative source of registration truth at high volume or for anything contractual. There is no Laravel coupling whatsoever — no service provider, facade, config file, or PSR-18/PSR-7 transport. It opens sockets directly, and its cache contract (WhoisCache) is its own interface, so it will not use Laravel's Cache repository without an adapter we write.
Integration feasibility. High. composer require plus ~50–100 lines of glue: a singleton binding, a config block (timeout, cache TTL, user agent), a cache adapter implementing the package's interface over Illuminate\Cache, and — most importantly — our own WhoisGateway interface wrapping the library so the rest of the codebase never imports vendor types. The library's API surface is small (lookupDomain, lookupAsn, raw-output access), which keeps the seam thin. Effort is days, not weeks.
Technical risk. Concentrated in three places, not in the code quality:
Secondary risks: registry rate limiting and IP bans, GDPR-driven redaction of registrant data (post-2018 thick WHOIS frequently returns nothing useful for contacts), and no upstream SLA for port-43 availability.
Key questions. Which specific fields does the product actually need — expiry dates only, or registrant identity? What query volume and QPS per TLD must we sustain? Is RDAP acceptable today for our priority TLDs (if yes, this package is a fallback, not a foundation)? Do we have a lawful basis to store registrant data? Who internally owns parser triage when a TLD breaks? And what's the contractual tolerance for a stale expiry date — 24 hours or 5 minutes?
Stack fit. Plain Composer package, PHP 8.0 declared (older branches back to 5.4), no Laravel version constraints and therefore no dependency conflicts. It needs the sockets extension only. On Laravel 10/11 with PHP 8.2 it will install and run; on 8.3/8.4 expect implicit-nullable and dynamic-property deprecations to surface in the parser classes and plan a small patch.
Migration path. Wrap first, migrate later. Define WhoisGateway with methods like lookup(string $domain): DomainRecord, implement it with this package, and feature-flag it against whatever we use today (registrar API, manual checks, or nothing). Because the consumer sees only our DTO, an RDAP implementation can be added behind the same interface and A/B'd by TLD with a config map — ['com' => 'rdap', 'io' => 'whois43']. Persist the raw response alongside the parsed record for every lookup; that single decision makes retroactive re-parsing and vendor swaps cheap.
Compatibility. MIT is compatible with proprietary use; no copyleft exposure. No global class collisions or framework hooks to conflict with. The one real compatibility concern is our own: pin the version exactly (or vendor-fork into a namespace we control) so an abandoned upstream cannot drift under us.
Sequencing.
WhoisGateway + DTO + a fake implementation for the test suite.Maintenance. The parsers are the maintenance surface, and they are maintained by upstream, which has not shipped since January 2023. Realistic expectation: budget a few engineer-days per quarter for a fork, parser patches, and new-TLD additions, concentrated right after ICANN/registry changes. Pin the version; do not float.
Support. Community-only — issues and stars, no vendor to escalate to, no security advisory process to rely on. This is acceptable for a read-only data enrichment dependency and unacceptable if it sits on a revenue-critical path without an internal owner. Name that owner before adoption.
Scaling. Every lookup is a blocking socket call, typically 200 ms–2 s, with no pooling. Throughput is bounded by queue workers on one side and registry rate limits on the other (commonly low single-digit QPS per source IP, with hard bans for violators). Design accordingly: never call this in a web request; use dedicated queue workers and named queues; spread egress across IPs if volume demands; cache aggressively by TLD-appropriate TTL (expiry data shifts slowly — a 12–24 hour cache is usually fine for monitoring, and it collapses volume by an order of magnitude). Add jitter and cache-warming to prevent cold-start stampedes.
Failure modes. Ranked by danger:
| Mode | Symptom | Detection |
|---|---|---|
| Silent parse drift | Null/empty fields, no exception | Field-completeness metrics per TLD |
| Rate-limit / IP ban | Empty or HTML-ish body, timeouts | Response-shape validation, error-rate alerts |
| Socket timeout / hang | Worker saturation | Job duration histograms |
| Unknown TLD | Fallback lookup or hard failure | Track miss rate by TLD |
| Redacted registrant | Expected nulls for contacts | Do not treat as error; do not promise registrant data |
| DNS/egress change | Sudden total failure | Synthetic canary per TLD |
The critical operational control is a per-TLD success-rate dashboard computed on parsed field population, not on "did the call return."
Ramp-up. Low. A competent PHP engineer is productive in half a day; the initial integration is 1–2 days including tests. The learning curve is not the library — it's WHOIS itself: thin vs thick registries, rate-limit etiquette, redaction, and the fact that "success" means "parsed plausible data," not "HTTP 200."
Recommendation. Adopt as a wrapped, queued, cached enrichment dependency with RDAP already on the roadmap and the interface designed to accept it. Do not adopt as the strategic source of domain registration data.
How can I help you explore Laravel packages today?