npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@xyz/whois

v2.5.2

Published

A powerful TypeScript/JavaScript tool for comprehensive domain analysis, featuring detailed WHOIS data with registration dates, registrars, and domain status. Offers SSL certificate extraction (with PEM support), DNS records, and server details. Includes

Readme

@xyz/whois

Build npm GitHub release License Known Vulnerabilities GitHub issues

A powerful TypeScript/JavaScript tool for comprehensive domain analysis, featuring detailed WHOIS data with registration dates, registrars, and domain status. Offers SSL certificate extraction (with PEM support), DNS records, and server details. Includes a feature-rich CLI with colorized output, full TypeScript support, and flexible data export options. Perfect for domain monitoring, security analysis, and compliance checks.

Table of Contents

Features

  • 📋 Comprehensive WHOIS Information:
    • Registrar details with IANA IDs and URLs
    • Registration, update, and expiration dates with expiry warnings
    • Domain status codes with human-readable descriptions
    • Registrant information (when available)
    • Name servers and raw WHOIS data access
  • 🔒 SSL/TLS certificate data including validity and expiration
  • 🖥️ Server information and HTTP status codes
  • 🌐 Comprehensive DNS records (A, CNAME, MX, TXT, NS, SOA)
  • 🧩 Intelligent subdomain support with automatic root domain recognition
  • 💻 Feature-rich CLI with colorized, structured output
  • 🏗️ Full TypeScript support with detailed typings
  • 🔄 Promise-based API for easy async/await usage
  • 🚀 Simple, lightweight with minimal dependencies
  • 📋 PEM-encoded certificates for direct use in other applications
  • 🔍 Detailed error messages with helpful troubleshooting suggestions
  • 🛡️ Robust error handling with specific error types

Installation

Install with your preferred package manager:

# npm
npm install @xyz/whois

# yarn
yarn add @xyz/whois

# pnpm
pnpm add @xyz/whois

Quick Start

import { fetchDomainInfo } from "@xyz/whois";

// Async/Await syntax
async function checkDomain() {
  try {
    const info = await fetchDomainInfo("example.com");

    // Check SSL certificate validity
    console.log(`SSL Valid: ${info.sslData.valid ? "Yes" : "No"}`);
    console.log(
      `Expires: ${new Date(info.sslData.validTo).toLocaleDateString()}`
    );

    // Display server & HTTP info
    console.log(`Server: ${info.serverData || "Unknown"}`);
    console.log(`HTTP Status: ${info.httpStatus}`);

    // Show IP addresses
    console.log(`IP Addresses: ${info.dnsData?.A.join(", ")}`);

    // Show WHOIS information (v2.3.0+)
    if (info.whoisData) {
      console.log(`Registrar: ${info.whoisData.registrar || "Unknown"}`);
      console.log(
        `Creation Date: ${
          info.whoisData.creationDate
            ? new Date(info.whoisData.creationDate).toLocaleDateString()
            : "Unknown"
        }`
      );
      console.log(
        `Expiration Date: ${
          info.whoisData.expirationDate
            ? new Date(info.whoisData.expirationDate).toLocaleDateString()
            : "Unknown"
        }`
      );

      // Check domain status codes
      if (info.whoisData.statusCodes && info.whoisData.statusCodes.length > 0) {
        console.log("Domain Status Codes:");
        info.whoisData.statusCodes.forEach((status) =>
          console.log(`- ${status}`)
        );
      }
    }
  } catch (error) {
    console.error("Error:", error.message);
  }
}

checkDomain();

Command Line Interface

The package includes a feature-rich CLI for quick domain analysis from the terminal, with colorized output for better readability:

# Install globally
npm install -g @xyz/whois

# Run a quick domain check
domain-info-fetcher example.com

# Check a subdomain
domain-info-fetcher blog.example.com

# Set request timeout and get JSON output
domain-info-fetcher example.com --timeout 5000 --json

CLI Output

The CLI provides a comprehensive, color-coded output with sections for:

  • 🔒 SSL Certificate: Validity, issuer, expiration dates, and PEM availability
  • 🖥️ Server Information: Server software and HTTP status codes
  • 🌐 DNS Records: A, CNAME, MX, TXT, and NS records with formatted display
  • 📋 WHOIS Information:
    • Registrar details and IANA IDs
    • ⏰ Important dates (creation, update, expiration) with color-coded warnings
    • 👤 Registrant information (when not privacy-protected)
    • 🔒 Domain status codes with human-readable descriptions
    • 🌐 Name servers
    • Sample of the raw WHOIS data with tip for viewing full data

CLI Options

| Option | Description | | ---------------- | ---------------------------------------------------- | | --timeout <ms> | Set request timeout in milliseconds (default: 10000) | | --json | Output results as JSON | | --help | Show help information |

API Documentation

Main Functions

fetchDomainInfo(domain: string, options?: RequestOptions): Promise<DomainInfo | undefined>

Fetches comprehensive information about a domain including SSL/TLS certificate, server details, DNS records, and HTTP status.

Parameters:

  • domain: The domain to analyze (e.g., "example.com" or "blog.example.com")
  • options: Optional request configuration

Returns: A Promise resolving to a DomainInfo object or undefined if an error occurs.

Helper Functions

extractSubdomain(domain: string): string | null

Extracts the subdomain part from a given domain.

const subdomain = extractSubdomain("blog.example.com"); // Returns "blog"
const none = extractSubdomain("example.com"); // Returns null

getRootDomain(domain: string): string

Extracts the root domain from a given domain that may include a subdomain.

const root = getRootDomain("blog.example.com"); // Returns "example.com"
const same = getRootDomain("example.com"); // Returns "example.com"

TypeScript Interfaces

DomainInfo

The main interface returned by fetchDomainInfo:

interface DomainInfo {
  // SSL/TLS certificate data
  sslData: {
    subject: { [key: string]: string | string[] };
    issuer: { [key: string]: string | string[] };
    valid: boolean;
    validFrom: number; // Timestamp
    validTo: number; // Timestamp
    // PEM-encoded certificates (available since v2.1.0)
    certificate?: string; // PEM-encoded server certificate
    intermediateCertificate?: string; // PEM-encoded intermediate certificate
    rootCertificate?: string; // PEM-encoded root certificate
    // Human-readable details (available since v2.1.0)
    details?: {
      subject: string; // Formatted subject name
      issuer: string; // Formatted issuer name (prioritizes Organization name over Common Name)
      validFrom: Date; // Validity start date as Date object
      validTo: Date; // Validity end date as Date object
    };
  };

  // Server software (if available)
  serverData: string | undefined;

  // DNS records
  dnsData:
    | {
        A: string[]; // IP addresses
        CNAME: string | null;
        TXT: string[];
        MX: Array<{ exchange: string; priority: number }>;
        NS: string[];
        SOA: dns.SoaRecord | null;
      }
    | undefined;

  // HTTP status code
  httpStatus: number | undefined;

  // WHOIS data (available since v2.3.0)
  whoisData?: {
    // Registration information
    registrar?: string;
    registrarUrl?: string;
    registrarIanaId?: string;

    // Dates
    creationDate?: Date;
    updatedDate?: Date;
    expirationDate?: Date;

    // Contact information (redacted in many cases due to privacy)
    registrant?: {
      organization?: string;
      country?: string;
      email?: string;
    };

    // Status codes
    statusCodes?: string[];

    // Name servers
    nameServers?: string[];

    // Raw WHOIS response
    rawText: string;
  };
}

RequestOptions

Options for configuring the fetch request:

interface RequestOptions {
  /** Timeout in milliseconds (default: 10000) */
  timeout?: number;
  /** Custom headers to include in HTTP requests */
  headers?: Record<string, string>;
  /** Whether to follow redirects (default: true) */
  followRedirects?: boolean;
  /** Maximum number of redirects to follow (default: 5) */
  maxRedirects?: number;
}

Advanced Usage

Subdomain Support

The package intelligently handles subdomains such as blog.example.com:

import {
  fetchDomainInfo,
  extractSubdomain,
  getRootDomain,
} from "@xyz/whois";

async function analyzeSubdomain() {
  const domain = "blog.example.com";
  const subdomain = extractSubdomain(domain); // Returns "blog"
  const rootDomain = getRootDomain(domain); // Returns "example.com"

  const info = await fetchDomainInfo(domain);

  // For subdomains:
  // - A and CNAME records are fetched for the subdomain
  // - MX, TXT, NS, and SOA records are fetched from the root domain
  console.log(`Subdomain A Records: ${info.dnsData?.A.join(", ")}`);
  console.log(
    `Root Domain MX Records: ${info.dnsData?.MX.length} records found`
  );
}

Custom Request Options

Customize the request behavior with options:

import { fetchDomainInfo } from "@xyz/whois";

const options = {
  timeout: 5000, // 5 second timeout
  headers: {
    "User-Agent": "Custom UA", // Custom user agent
  },
  followRedirects: true, // Follow redirects
  maxRedirects: 3, // Max redirects to follow
};

const info = await fetchDomainInfo("example.com", options);

Processing Multiple Domains

Check multiple domains in parallel:

import { fetchDomainInfo } from "@xyz/whois";

async function checkMultipleDomains(domains: string[]) {
  const results = await Promise.allSettled(
    domains.map((domain) => fetchDomainInfo(domain))
  );

  // Process results
  results.forEach((result, index) => {
    const domain = domains[index];
    if (result.status === "fulfilled") {
      const info = result.value;
      console.log(
        `✅ ${domain}: SSL valid until ${new Date(
          info.sslData.validTo
        ).toLocaleDateString()}`
      );
    } else {
      console.log(`❌ ${domain}: Error - ${result.reason.message}`);
    }
  });
}

// Example usage
checkMultipleDomains(["example.com", "github.com", "blog.medium.com"]);

Working with WHOIS Data

The package provides comprehensive WHOIS information for domains (added in v2.3.0):

import { fetchDomainInfo, WhoisData } from "@xyz/whois";

async function analyzeWhoisData() {
  try {
    const domain = "example.com";
    const info = await fetchDomainInfo(domain);

    if (info.whoisData) {
      // Display key WHOIS data
      console.log(`Domain: ${domain}`);
      console.log(`Registrar: ${info.whoisData.registrar || "N/A"}`);
      console.log(`Registrar URL: ${info.whoisData.registrarUrl || "N/A"}`);

      if (info.whoisData.registrarIanaId) {
        console.log(`Registrar IANA ID: ${info.whoisData.registrarIanaId}`);
      }

      // Format and display dates
      if (info.whoisData.creationDate) {
        console.log(
          `Registration Date: ${info.whoisData.creationDate.toLocaleDateString()}`
        );
      }

      if (info.whoisData.updatedDate) {
        console.log(
          `Last Updated: ${info.whoisData.updatedDate.toLocaleDateString()}`
        );
      }

      if (info.whoisData.expirationDate) {
        console.log(
          `Expiration Date: ${info.whoisData.expirationDate.toLocaleDateString()}`
        );

        // Calculate days until expiration
        const now = new Date();
        const expiry = info.whoisData.expirationDate;
        const daysRemaining = Math.ceil(
          (expiry.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)
        );

        // Color code based on proximity to expiration
        let status = "✅";
        if (daysRemaining < 30) {
          status = "⚠️ EXPIRING SOON";
        } else if (daysRemaining < 0) {
          status = "❌ EXPIRED";
        }

        console.log(`Days until expiration: ${daysRemaining} ${status}`);
      }

      // Display domain status codes
      if (info.whoisData.statusCodes && info.whoisData.statusCodes.length > 0) {
        console.log("\nDomain Status Codes:");
        info.whoisData.statusCodes.forEach((status) => {
          // Add helpful descriptions for common status codes
          let description = "";
          if (status.includes("clientTransferProhibited")) {
            description = " (Transfer locked by registrar)";
          } else if (status.includes("clientDeleteProhibited")) {
            description = " (Deletion protected)";
          } else if (status.includes("clientUpdateProhibited")) {
            description = " (Updates restricted)";
          }

          console.log(`- ${status}${description}`);
        });
      }

      // Display registrant information if available
      if (info.whoisData.registrant) {
        console.log("\nRegistrant Information:");

        if (info.whoisData.registrant.organization) {
          console.log(
            `- Organization: ${info.whoisData.registrant.organization}`
          );
        }

        if (info.whoisData.registrant.country) {
          console.log(`- Country: ${info.whoisData.registrant.country}`);
        }

        if (info.whoisData.registrant.email) {
          console.log(`- Email: ${info.whoisData.registrant.email}`);
        }
      }

      // Display nameservers
      if (info.whoisData.nameServers && info.whoisData.nameServers.length > 0) {
        console.log("\nNameservers:");
        info.whoisData.nameServers.forEach((ns) => console.log(`- ${ns}`));
      }

      // Access raw WHOIS text for custom parsing
      if (info.whoisData.rawText) {
        console.log("\nRaw WHOIS data excerpt:");
        // Display first 5 lines
        const excerpt = info.whoisData.rawText
          .split("\n")
          .filter((line) => line.trim() !== "")
          .slice(0, 5)
          .join("\n");
        console.log(excerpt + "...");
      }
    } else {
      console.log(`No WHOIS data available for ${domain}`);
    }
  } catch (error) {
    console.error("Error:", error.message);
  }
}

analyzeWhoisData();

The enhanced WHOIS data is particularly useful for:

  • Monitoring domain expiration dates with visual alerts
  • Verifying domain ownership information
  • Checking domain status codes with human-readable explanations
  • Retrieving detailed registrar information including IANA IDs
  • Identifying registration and update history
  • Analyzing domain transfer and security settings

Error Handling

The package provides specific error messages for different failure scenarios with helpful suggestions for troubleshooting:

import { fetchDomainInfo } from "@xyz/whois";

try {
  const info = await fetchDomainInfo("example.com");
  // Process successful result
} catch (error) {
  // Handle specific errors
  if (error.message.includes("Invalid domain name format")) {
    console.error("Please provide a valid domain format (e.g., example.com)");
  } else if (error.message.includes("Could not fetch SSL data")) {
    console.error("SSL certificate issue or HTTPS not supported");
    console.error(
      "Try increasing the timeout or check if the domain supports HTTPS"
    );
  } else if (error.message.includes("Could not fetch DNS data")) {
    console.error(
      "DNS resolution failed - check domain spelling or DNS connectivity"
    );
  } else if (error.message.includes("Could not fetch WHOIS data")) {
    console.error(
      "WHOIS lookup failed - server may be unavailable or rate limiting"
    );
  } else if (error.message.includes("ETIMEDOUT")) {
    console.error("Connection timed out - try increasing the timeout value");
  } else {
    console.error("Unknown error:", error.message);
  }
}

When using the CLI, detailed error suggestions are automatically provided:

❌ Error fetching domain information:
   Could not fetch SSL data for domain invalid.site. Error code: ENOTFOUND

Suggestion: Domain not found. This could be because:
  - The domain doesn't exist or is misspelled
  - Your DNS resolver can't resolve this domain
  - Check for typos in the domain name

Examples

The package includes ready-to-run examples:

# Clone the repository
git clone https://github.com/xyzhub/whois.git
cd whois

# Install dependencies
npm install

# Run examples
npm run example          # Basic domain info
npm run example:multi    # Multiple domains
npm run example:subdomain # Subdomain analysis
npm run example:certificate # Certificate extraction
npm run example:whois    # WHOIS data analysis with detailed output

For detailed information about our development plans, implementation timeline, and how to contribute to specific features, please see our ROADMAP.md document.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Please make sure to update tests as appropriate and adhere to the existing coding style.

License

This project is licensed under the MIT License - see the LICENSE file for details.