Skip to content

Instantly share code, notes, and snippets.

@Lissy93
Last active October 19, 2024 19:56
Show Gist options
  • Save Lissy93/e33a6b2218f57c51127bbbe7046f5c83 to your computer and use it in GitHub Desktop.
Save Lissy93/e33a6b2218f57c51127bbbe7046f5c83 to your computer and use it in GitHub Desktop.
/**
* A quick and simple JS WHOIS lookup to return JSON
* Docs and usage instructions are below...
**/
import * as whois from 'whois';
import * as changeCase from 'change-case';
import { decodeEntity } from 'html-entities';
const DELIMITER = ':';
/**
* Promisified version of the whois lookup function for async/await usage.
*/
const whoisLookup = async (domain, options = {}) => {
return new Promise((resolve, reject) => {
whois.default.lookup(domain, options, (error, data) => {
if (error) {
return reject(error);
}
resolve(data);
});
});
};
/**
* Main function to handle the WHOIS lookup and parse raw data.
*
* @param {string} domain - Domain name to lookup
* @param {object} options - Options for the lookup (optional)
* @returns {object} Parsed WHOIS data
*/
export const getWhoisData = async (domain, options = {}) => {
try {
const rawData = await whoisLookup(domain, options);
return Array.isArray(rawData)
? rawData.map(data => ({ ...data, data: parseRawData(data.data) }))
: parseRawData(rawData);
} catch (error) {
console.error('Error during WHOIS lookup:', error);
throw new Error('Failed to fetch WHOIS data');
}
};
/**
* Strip HTML entities from the raw data.
*
* @param {string} rawData - The raw WHOIS data
* @returns {string} Decoded string with HTML entities stripped
*/
const stripHTMLEntities = (rawData) => decodeEntity(rawData);
/**
* Determines the most common delimiter form in the raw data (e.g., `: ` or `:`).
*
* @param {string} rawData - The raw WHOIS data
* @param {string} delimiter - The delimiter to search for
* @returns {string} The most common delimiter found in the data
*/
const getCommonDelimiterForm = (rawData, delimiter) => {
const delimiterPattern = new RegExp(`${delimiter}\\S+`, 'g');
const delimiterWithSpacePattern = new RegExp(`${delimiter} `, 'g');
const delimiterMatches = rawData.match(delimiterPattern) || [];
const delimiterWithSpaceMatches = rawData.match(delimiterWithSpacePattern) || [];
return delimiterMatches.length > delimiterWithSpaceMatches.length
? delimiter
: `${delimiter} `;
};
/**
* Parses raw WHOIS data and converts it into a key-value object format.
*
* @param {string} rawData - The raw WHOIS data
* @returns {object} Parsed key-value data
*/
const parseRawData = (rawData) => {
const result = {};
rawData = stripHTMLEntities(rawData)
.replace(/:\s*\r?\n/g, ': '); // Normalize colon space formatting
const lines = rawData.split('\n');
const delimiter = getCommonDelimiterForm(rawData, DELIMITER);
lines.forEach(line => {
const trimmedLine = line.trim();
if (trimmedLine && trimmedLine.includes(delimiter)) {
const [key, ...valueParts] = trimmedLine.split(DELIMITER);
const value = valueParts.join(DELIMITER).trim();
const formattedKey = changeCase.camelCase(key);
// Combine values for the same key across multiple lines
if (formattedKey in result) {
result[formattedKey] = `${result[formattedKey]} ${value}`;
} else {
result[formattedKey] = value;
}
}
});
return result;
};

A really quick script to run a whois lookup, and format the response into JSON.
Inspired by whois-json by @mikemaccana.

Usage

Prerequisites

  1. Paste the above code in a file, like whois-lookup.js
  2. And then run npm i html-entities change-case whois

Usage Example 1: In your code
import { getWhoisData } from './whois-lookup.js';
    
getWhoisData('google.com').then(data => {
  console.log(data); // Outputs a JSON WHOIS response
}).catch(error => {
  console.error(error);
});

Usage Example 2: As an API
  1. Create a file named server.js, and paste the code below into it
  2. Run node server
  3. Open localhost:3000/duck.com to return the WHOIS JSON
import { getWhoisData } from './whois-lookup.js';
import http from 'http';

const server = http.createServer((req, res) => {
  const urlParts = req.url.split('/');
  const domain = urlParts[1];
  
  if (domain) {
    getWhoisData(domain).then(data => {
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify(data, null, 2));
    }).catch(error => {
      res.writeHead(500, { 'Content-Type': 'text/plain' });
      res.end(`Error: ${error.message}`);
    });
  } else {
    res.writeHead(400, { 'Content-Type': 'text/plain' });
    res.end('Please specify a domain in the URL. For example: /example.com');
  }
});

server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

Usage Example 3: As a CLI
  1. Create a file named whois-cli.js, and paste the code below into it
  2. In your terminal, run node ./whois-cli.js --url='google.com' to get WHOIS JSON
import { getWhoisData } from './whois-lookup.js';

const args = process.argv.slice(2);
const domainArg = args.find(arg => arg.startsWith('--url='));

if (domainArg) {
  const domain = domainArg.split('=')[1];
  getWhoisData(domain).then(data => {
    console.log(data);
  }).catch(error => {
    console.error('Error:', error);
  });
} else {
  console.log('Usage: node ./example.js --url="example.com"');
}

Example Output (JSON)
{
  "domainName": "google.com",
  "registryDomainId": "2138514_DOMAIN_COM-VRSN",
  "registrarWhoisServer": "whois.markmonitor.com",
  "registrarUrl": "http://www.markmonitor.com",
  "updatedDate": "2024-08-02T02:17:33+0000",
  "creationDate": "1997-09-15T07:00:00+0000",
  "registrarRegistrationExpirationDate": "2028-09-13T07:00:00+0000",
  "registrar": "MarkMonitor, Inc.",
  "registrarIanaId": "292",
  "registrarAbuseContactEmail": "[email protected]",
  "registrarAbuseContactPhone": "+1.2086851750",
  "domainStatus": "clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited) clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited) clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited) serverUpdateProhibited (https://www.icann.org/epp#serverUpdateProhibited) serverTransferProhibited (https://www.icann.org/epp#serverTransferProhibited) serverDeleteProhibited (https://www.icann.org/epp#serverDeleteProhibited)",
  "registrantOrganization": "Google LLC",
  "registrantStateProvince": "CA",
  "registrantCountry": "US",
  "registrantEmail": "Select Request Email Form at https://domains.markmonitor.com/whois/google.com",
  "adminOrganization": "Google LLC",
  "adminStateProvince": "CA",
  "adminCountry": "US",
  "adminEmail": "Select Request Email Form at https://domains.markmonitor.com/whois/google.com",
  "techOrganization": "Google LLC",
  "techStateProvince": "CA",
  "techCountry": "US",
  "techEmail": "Select Request Email Form at https://domains.markmonitor.com/whois/google.com",
  "nameServer": "ns4.google.com ns3.google.com ns2.google.com ns1.google.com",
  "dnssec": "unsigned",
  "urlOfTheIcannWhoisDataProblemReportingSystem": "http://wdprs.internic.net/",
  "lastUpdateOfWhoisDatabase": "2024-10-19T14:27:44+0000 <<<",
  "forMoreInformationOnWhoisStatusCodesPleaseVisit": "https://www.icann.org/resources/pages/epp-status-codes",
  "webBasedWhois": "https://domains.markmonitor.com/whois",
  "lawfulPurposesAndThatUnderNoCircumstancesWillYouUseThisDataTo": "(1) allow, enable, or otherwise support the transmission by email, telephone,"
}

Note

Hate JavaScript? Me too. I've written a Go Lang version, here: github.com/Lissy93/who-dat. Much better 😎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment