Library / SDK
weppos/whois avatar
weppos/whois

The whois gem picks the right server, parses the answer, and has done so since 2009

An intelligent — pure Ruby — WHOIS client and parser.

1,173 stars288 forksRubyMIT

At a glance

What is it?
weppos/whois is a pure Ruby WHOIS client and parser with no dependency outside Ruby itself. It guesses the correct WHOIS server for a domain, a TLD or an IP address, returns a record object that behaves like a string but can be parsed into structured fields, and it has been running queries in production at DNSimple since July 2009. The parser lives in a separate gem, and the README is candid about the cost of that split.
Who is it for?
whois fits a Ruby service that needs to answer questions about domains or IP addresses, whether that is a domain registrar, a phishing check or a reseller backend, and the pure Ruby dependency free property makes it easy to drop into a project with a strict dependency policy. It is the wrong choice if you need every registry covered, because the parsers are per server and the library says outright that it does not support all of them.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 9 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The client guesses which server to ask

The library describes itself as an intelligent, pure Ruby WHOIS client and parser, and the intelligence is in the server selection.

The client is smart enough to guess the best WHOIS server according to the given query, send the request and return the response. The queries it accepts are not only domain names. The feature list names IPv4, IPv6, TLDs and ICANN new gTLDs, so the same call works for a registered name, for the registry itself by asking about .com, and for an address in either protocol.

ruby
# Domain WHOIS
whois = Whois::Client.new
whois.lookup("google.com")
# => #<Whois::Record>

# TLD WHOIS
whois = Whois::Client.new
whois.lookup(".com")
# => #<Whois::Record>

The server definitions live in the data/ directory of the repository, and the interface is flexible and extensible, so you can define custom servers on the fly for a registry the library does not know about. The design is object oriented and the README says it features 10 different design patterns, which is a claim about the internal structure rather than something a user needs, but it does signal that the server selection is a considered piece of engineering rather than a lookup table bolted onto a socket.

There is also a shortcut for the common case. If you just need a WHOIS response and do not care about full control of the client, the Whois module provides an all-in-one method called Whois.whois, which the README calls the simplest way to send a WHOIS request.

ruby
Whois.whois("google.com")
# => #<Whois::Record>

The library also accepts a block, which is a tidy way to scope a batch of lookups to one client.

ruby
Whois::Client.new do |w|
  w.lookup("google.com")
  w.lookup(".com")
end

The parser is a separate gem, and the split has a cost

Since version 4, the WHOIS parser component is available in a separate repository called whois-parser and released as a separate gem called whois-parser. This repository contains the core whois library, which includes the WHOIS client, the server definitions and all the features required to perform WHOIS queries and obtain the record.

The reason for the split is a practical one about dependencies, and the README states it. The whois-parser gem already depends on the whois gem, so installing whois-parser installs whois as well, and it is automatically required when you require whois-parser. The parser is the heavier part, with the per registry rules, and keeping it separate means an application that only needs the raw record does not pull it in.

The cost of the split is the thing the README is candid about. Because of the lack of a global standard, each WHOIS server requires a specific parser, and for this reason the library does not support all existing WHOIS servers. There is no universal WHOIS format, so the library ships a set of parsers, one per registry family, and a registry without one is simply not parsed.

That is a coverage problem you have to check rather than assume, and the README asks contributors to consider releasing a new parser publicly so it can be included in a next version, which is a reasonable way to grow coverage in a project whose upstream source is scattered across dozens of registries.

The parsing side is also the part with a version history worth reading, because the upgrade from version 3 to version 4 changed where the parser lives. The README points at 4.0-Upgrade.md for the details, and for older Ruby versions it points at the CHANGELOG.

A record that looks like a string and behaves like an object

Any WHOIS query returns a Whois::Record, and the README's description of it is the best summary of the design. This object looks like a String, but it is way more powerful. It encapsulates a WHOIS record and provides the ability to parse the WHOIS response programmatically, when the whois-parser gem is installed and loaded.

So the record is the raw text when you need the raw text, and a parsed view when you need fields.

ruby
require 'whois-parser'

record = Whois.whois("google.it")
# => #<Whois::Record>

parser = record.parser
# => #<Whois::Parser>

parser.available?
# => false
parser.registered?
# => true

parser.created_on
# => Fri Dec 10 00:00:00 +0100 1999

The parser exposes the fields an application actually wants. available? and registered? answer the two questions a caller usually has, created_on gives a time zone aware date, and nameservers enumerates the delegation.

ruby
tech = parser.technical_contacts.first
# => #<Whois::Record::Contact>
tech.id
# => "TS7016-ITNIC"
tech.name
# => "Technical Services"

The contacts are objects of their own, Whois::Record::Contact, with an id and a name rather than a raw string, which is the difference between a record you can use and a record you have to parse again yourself.

One detail worth knowing is the order of operations. The parser only exists if the whois-parser gem is installed and loaded, which is why the require line is in the example. Without it you still get the record, you just get the text.

The client is stateless, and the timeout is not optional

Two operational details in the README decide how the library behaves in a server process.

The first is that the query method is stateless, and for this reason you can safely re-use the same client instance for multiple queries. That matters for a long running process, because a client per request means re-reading the server definitions and re-establishing the client state on every call.

ruby
whois = Whois::Client.new
whois.lookup("google.com")
whois.lookup(".com")
whois.lookup("74.125.67.100")
whois.lookup("2001:db8::1428:57ab")
whois.lookup("google.it")

The second is the timeout. By default each query run through the client has a timeout value of 5 seconds, and if the execution exceeds the timeout limit the client raises a Timeout::Error exception. The value can be customised, and there is a reader and a writer for it.

ruby
whois = Whois::Client.new(:timeout => 10)
whois.timeout # => 10
whois.timeout = 5
whois.timeout # => 5

The library also documents the option you should not take. If timeout is nil, the client will wait until the response is sent back from the server or the process is killed, and the README says not to disable the timeout unless you really know what you are doing.

That advice is not pedantic. A WHOIS server that accepts a connection and never answers is a real failure mode, and with a timeout the failure is an exception your code can handle, while without one a single unresponsive registry occupies a worker until something kills it.

The pure Ruby property is worth naming too, since the feature list calls it out specifically. There is no external dependency other than Ruby itself, and the library is successfully tested against different Ruby implementations, including Ruby and JRuby, with the test workflow visible as a GitHub Actions badge.

Seventeen years in production, and a code base with a governance layer

The history is a reasonable indicator of the state of the project. The library was extracted from RoboWhois and RoboDomain, and it is now in use at DNSimple, and it has been performing queries in production since July 2009.

That longevity matters for a library in this category, because WHOIS is a protocol of a thousand slightly different dialects, and the server definitions and the parse rules are the kind of knowledge that only accumulates through years of breakage reports. A parser that has not been updated since 2009 is a parser that does not work now.

The repository shows a mature project rather than a hobby. There is a spec/ directory with the RSpec suite and a .rspec file, a Rakefile, a whois.gemspec, a Gemfile, and a .simplecov file for coverage. The linting setup is three RuboCop configurations, a .rubocop.yml, a .rubocop_opinionated.yml and a .rubocop_todo.yml, which is the conventional way of introducing rules gradually, with the pending list as the record of what is not yet enforced. There is a .yardopts file for the API documentation, a .tool-versions file pinning the toolchain, a bin/ directory with the executables, a utils/ directory, and a SECURITY.md.

The requirements are Ruby 3.2 or newer, with the CHANGELOG covering older versions, and the project uses Semantic Versioning. The licence is MIT, with LICENSE.txt at the repository root, and the gems are published as whois and whois-parser on RubyGems.

The last push was on 2026-10-14, the project is not archived, and the repository publishes no GitHub releases, so the gem versions on RubyGems are the version record.

Editorial conclusion

whois fits a Ruby service that needs to answer questions about domains or IP addresses, whether that is a domain registrar, a phishing check or a reseller backend, and the pure Ruby dependency free property makes it easy to drop into a project with a strict dependency policy. It is the wrong choice if you need every registry covered, because the parsers are per server and the library says outright that it does not support all of them. Verify first that a parser exists for the registries you care about, and keep the timeout enabled.

Frequently asked questions

How do I install the whois Ruby gem?

With gem install whois, or by adding gem 'whois' to your Gemfile and using Bundler. To parse the responses you also need the separate whois-parser gem, which depends on whois and requires it automatically.

What can the whois gem look up?

The feature list names IPv4 addresses, IPv6 addresses, TLDs and ICANN new gTLDs, as well as ordinary domain names, and the client guesses the best WHOIS server for the query it is given.

Why does the whois library not support every WHOIS server?

Because of the lack of a global standard, each WHOIS server requires a specific parser, and the README says plainly that the library does not support all existing WHOIS servers. New parsers are contributed publicly so they can be included in a later version.

What is the default timeout for a whois query?

Each query has a timeout of 5 seconds by default, and the client raises a Timeout::Error if it is exceeded. The value can be set on the client, and setting it to nil makes the client wait until the response arrives or the process is killed, which the README warns against.

How do I parse a Whois::Record?

Require the whois-parser gem and call record.parser, which returns a Whois::Parser exposing available?, registered?, created_on, technical_contacts and nameservers. The record object behaves like a string, so you can still work with the raw response when you do not need the parser.

Official sources

  1. Issues
  2. License: MIT
  3. Project website
  4. README
  5. weppos/whois on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/weppos-whois.svg)](https://hysenlabs.com/projects/weppos-whois)

Was this useful?