Skip to content

Repository files navigation

@mono-vm/whois

npm CI license

Domain availability checks and WHOIS records for Node.js, over port 43 WHOIS and RDAP. Servers for 1651 extensions are bundled, so there is nothing to configure.

npm install @mono-vm/whois
import { Checker } from '@mono-vm/whois';

await Checker.whois('monovm.com');
// { 'monovm.com': 'unavailable' }

Node 18+. No runtime dependencies. Ships ESM and CommonJS builds with type declarations.

Checking availability

Checker.whois() takes one domain or a list, and answers with a status per domain.

import { Checker } from '@mono-vm/whois';

await Checker.whois('monovm.com');
// { 'monovm.com': 'unavailable' }

await Checker.whois(['monovm.com', 'wikipedia.org', 'some-name-nobody-took.com']);
// {
//   'monovm.com': 'unavailable',
//   'wikipedia.org': 'unavailable',
//   'some-name-nobody-took.com': 'available'
// }

Leave the extension off and the name is checked against a list of popular TLDs instead:

await Checker.whois('monovm');
// { 'monovm.com': 'unavailable', 'monovm.net': 'available', 'monovm.org': 'unavailable', ... }

CommonJS is the same thing with require:

const { Checker } = require('@mono-vm/whois');

Checker.whois('monovm.com').then(console.log);

Statuses

Status Meaning
available Free to register
unavailable Taken
premium Exists in the registry but is reserved, restricted or premium priced
invalid No server is known for that extension
error The registry could not be queried, or refused

error and invalid are not failures to paper over. They mean the answer is unknown, and that is deliberately different from available.

Options

await Checker.whois('monovm', {
  popularTLDs: ['.com', '.net', '.org'], // used when the input has no extension
  concurrency: 10,                       // parallel lookups, default 5
  verifyWithDns: true,                   // default, see "Accuracy" below
  socketTimeout: 10_000,                 // port 43, ms
  httpTimeout: 60_000,                   // HTTP/RDAP, ms
  dnsTimeout: 3_000,
  definitions: [                         // add or replace a server
    { extensions: '.example', uri: 'socket://whois.nic.example', available: 'No match' },
  ],
});

Building the server table costs a few milliseconds, so keep an instance around if you check domains often:

const checker = new Checker({ concurrency: 20 });

await checker.check(['a.com', 'b.com']);
await checker.check('c.com');

A domain that appears twice in one call is only queried once, and input is normalised first: MonoVM.COM., monovm.com and monovm.com. are one lookup. International names are converted to punycode, so bücher.de works as you would expect.

Reading the WHOIS record

WhoisHandler gives you the record itself alongside the verdict.

import { WhoisHandler } from '@mono-vm/whois';

const result = await WhoisHandler.whois('monovm.com');

result.getStatus();        // 'unavailable'
result.isAvailable();      // false
result.isValid();          // true
result.getSld();           // 'monovm'
result.getTld();           // '.com'
result.getWhoisMessage();  // 'Domain Name: MONOVM.COM\nRegistrar: ...'
Method Returns
getStatus() The full verdict, same values as Checker
isAvailable() true only for available
isValid() false when the extension is unknown or the registry could not be reached
getWhoisMessage() The raw record, or a readable sentence when there is no record to show
getSld() / getTld() / getDomain() The parsed name
getAvailabilityDetails() Which detection rules fired, for debugging
toJSON() Plain object, useful in API responses

It does not throw on network trouble. A registry that times out gives you isValid() === false and the reason in getWhoisMessage().

CLI

npx @mono-vm/whois monovm.com
Usage: monovm-whois <domain...> [options]

  -t, --tlds <list>      TLDs to try for names without an extension
  -c, --concurrency <n>  parallel lookups (default 5)
  -r, --raw              print the raw WHOIS record
  -j, --json             print JSON
  -h, --help
  -v, --version
$ monovm-whois example.com monovm --tlds .com,.net
example.com  unavailable
monovm.com   unavailable
monovm.net   available

Exit code is 1 if any lookup errored.

Accuracy

WHOIS has no schema. Every registry invents its own wording for "this name is free", in its own language, wrapped in its own legal boilerplate. So the response goes through a series of checks, most specific first: server error messages, then explicit "taken" wording, then registration data such as name servers and dates, then free-domain phrases, then per-registry patterns, and only at the very end the weak signal of a short response with no registry fields in it.

A few things that sound like good signals are deliberately not treated as any:

  • The bare word available. Finnish records print available....: 15.9.2029, the date the name is released again — that is a registered domain.
  • The bare word registered. Nominet answers This domain name has not been registered.
  • The bare word free, which shows up in footers like "provided for free by Nominet UK".
  • A bare 404 anywhere in the text. Object ids and street numbers contain those digits.
  • An empty response. A server that hangs up has told you nothing.

DNS cross-check. Before any available is returned, the name is checked for name servers in the parent zone. If it is delegated, it exists, whatever WHOIS said, and the answer is corrected to unavailable. This is what catches registries whose WHOIS service was retired, mismapped or is simply answering "not found" for names it does not serve. It never runs the other way round, and a resolver that cannot be reached never changes a verdict. Turn it off with verifyWithDns: false.

How this was checked. Every bundled extension was swept in both directions — a name DNS confirms is delegated, and a random name nobody has registered — with the DNS cross-check switched off, so the numbers describe the detection logic on its own. Of 3080 lookups, 11 came back wrong; most of those were nic.<tld> names that registries keep out of their own WHOIS database. With the cross-check on, the "taken reported as free" cases are corrected. Registries that were unreachable or refused to answer are reported as error, not guessed.

The whole detector is exported if you want to re-evaluate a stored record offline:

import { AvailabilityDetector } from '@mono-vm/whois';

AvailabilityDetector.isAvailable(rawWhoisText, '.com');
AvailabilityDetector.getAvailabilityDetails(rawWhoisText, '.com');

Server data

Two sources are merged at build time:

Source Extensions File
Curated servers with hand-checked match strings 835 src/data/dist.whois.json
IANA RDAP bootstrap registry 816 src/data/rdap-bootstrap.json

The curated list wins wherever the two overlap; the bootstrap fills in everything else. Run npm run update:rdap to pull a fresh snapshot from IANA and regenerate the table.

To add or override a server without waiting for a release, pass it in:

await Checker.whois('name.example', {
  definitions: [
    { extensions: '.example,.example.co', uri: 'socket://whois.nic.example', available: 'No match' },
    { extensions: '.otherexample', uri: 'https://rdap.nic.example/domain/', available: '' },
  ],
});

An empty available is fine for RDAP endpoints: those answers are recognised by structure, not by string matching.

import { Whois, whoisDefinitions } from '@mono-vm/whois';

new Whois().getSupportedTlds();  // ['.ac', '.academy', ...]
whoisDefinitions.length;         // server entries

Known gaps

Some of this is out of our hands and worth knowing before you file an issue:

  • .es, .vn and parts of .za publish no queryable WHOIS or RDAP service. They report invalid or error rather than a guess.
  • A handful of registries refuse queries from outside their own country, and a few (.shop) block unknown clients outright. Those come back as error.
  • gTLD registries are retiring port 43 during 2026 under ICANN's RDAP transition. When one does, its lookups move to RDAP; if you hit a stale entry, npm run update:rdap and a pull request are welcome.
  • Rate limits are real. Verisign and PIR in particular will start refusing if you hammer them; keep concurrency sane and cache results on your side.

Development

npm install
npm test              # unit tests, no network
npm run test:network  # adds live lookups against real registries
npm run typecheck
npm run build

The unit tests spin up a local WHOIS socket server and a local RDAP endpoint, so the suite runs offline and in a couple of hundred milliseconds.

Contributing

Pull requests for new extensions, corrected match strings or bug fixes are welcome at github.com/monovm/whois-js. If you are adding a server, please include the raw answer it gives for a registered and an unregistered name.

License

MIT

Support

dev@monovm.comMonoVM.com

About

This Javascript whois package enables developers to retrieve domain registration information and check domain availability via socket protocol. It's a useful tool for web developers and domain name registrars.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages