Derek Sivers

Find a good available .com domain

2022-06-08

If you need a new domain name, you want a .com, and you don’t want to type random ideas into a registrar search, here’s a way to do it.

Download the list of all registered .com domains

First, apply for access to the zone file, using ICANN’s Centralized Zone Data Service (CZDS) at https://czds.icann.org/. It’s free, but takes a few days to get approved. Read more about it here.

Once approved, they email you a password to log in and download the file called com.txt.gz.

$ du -hs com.txt.gz # 4.6GB compressed
4.6G    com.txt.gz
$ gunzip com.txt.gz # uncompress and wait
$ du -hs com.txt
23.0G   com.txt     # 23 gigs uncompressed
$ wc -l com.txt
404261754 com.txt   # 404 million lines

Extract the unique names

com.txt has 404 million lines like this:

zombahomes.com. 172800  in      ns      ns2.tierra.net.
zombai.com.     172800  in      ns      ns1.parkingcrew.net.
zombai.com.     172800  in      ns      ns2.parkingcrew.net.
zombaid.com.    172800  in      ns      nsg1.namebrightdns.com.
zombaid.com.    172800  in      ns      nsg2.namebrightdns.com.
zombaimmo.com.  172800  in      ns      ns10.lwsdns.com.
zombaimmo.com.  172800  in      ns      ns11.lwsdns.com.
zombaimmo.com.  172800  in      ns      ns12.lwsdns.com.
zombaimmo.com.  172800  in      ns      ns17.lwsdns.com.
zombaio.com.    172800  in      ns      ns-1073.awsdns-06.org.

Domains usually have more than one entry. You need to extract the unique entries. And you only need the part before the “.com”.

Here’s a Ruby script that loops through com.txt, gets the part before .com, skips it if duplicate, and outputs it if unique.

domain = ''
File.open('com.txt', 'r') do |infile|
  File.open('domains.txt', 'w') do |outfile|
    while line = infile.gets
      temp = line[0...(line.index('.com'))]
      next if temp == domain
      domain = temp
      outfile.puts domain
    end
  end
end
download code

“domains.txt” should now be about 162 million lines - (about 2.2GB) - that look like this:

zombahomes
zombai
zombaid
zombaimmo
zombaio

Load it into SQLite, and index it.

$ sqlite3 domains.db 
sqlite> create table domains(domain text);
sqlite> .import "domains.txt" domains
sqlite> create index dd on domains(domain);

Find available dictionary words

If you’re on Mac, Linux, or BSD, you should have a dictionary of words at /usr/share/dict/words. See which of those words are available:

require 'sqlite3'
db = SQLite3::Database.new('domains.db')
query = db.prepare('select domain from domains where domain = ?')
File.readlines('/usr/share/dict/words').each do |word|
  rows = query.execute(word.downcase)
  puts word unless rows.next
end
download code

Run that, and you’ll have a list of 93,000 dictionary words that are available with the .com extension. Congratulations! Go to porkbun.com (a great little registrar) to register yours.

You’ll find that some are not actually available because that “com.txt” file doesn’t list domains on hold, pending deletion, or without name servers.

Combine short dictionary words

If you are not excited that “electrotelethermometer.com” or “counterexcommunication.com” is available, maybe you would like a combination of two short words? Select only dictionary words up to four letters, then search for the combination.

require 'sqlite3'
words = File.readlines('/usr/share/dict/words').map(&:strip)
words.select! {|w| w.size <= 4}
db = SQLite3::Database.new('domains.db')
query = db.prepare('select domain from domains where domain = ?')
words.each do |word1|
  words.each do |word2|
    combo = (word1 + word2).downcase
    rows = query.execute(combo)
    puts combo unless rows.next
  end
end
download code

Narrow it down to good words

If you ran that last script, you’ll get tens of millions of available domains like “knabtuik.com” because there are many unknown, ugly, and useless short words.

So make a new file called “goodwords.txt” of only three and four letter words, using grep:

$ grep "^...$" /usr/share/dict/words >> goodwords.txt
$ grep "^....$" /usr/share/dict/words >> goodwords.txt

Edit that file by hand, deleting every word you would never want. (The less you keep, the better.) Then run that Ruby script again, combining just the good words:

require 'sqlite3'
words = File.readlines('goodwords.txt').map(&:strip)
db = SQLite3::Database.new('domains.db')
query = db.prepare('select domain from domains where domain = ?')
words.each do |word1|
  words.each do |word2|
    combo = (word1 + word2).downcase
    rows = query.execute(combo)
    puts combo unless rows.next
  end
end
download code

Much better, right? A little time consuming, but worth it. This is how I found the name of my new translation service, Inchword.

Need it super-short and nerdy?

One final hack is that there are tons of very-short .com domain names available in the format “letter-number-letter-number”. For example: q7r7.com or e3p3.com.

require 'sqlite3'
db = SQLite3::Database.new('domains.db')
query = db.prepare('select domain from domains where domain = ?')
('a'..'z').each do |a|
  ('0'..'9').each do |b|
    ('a'..'z').each do |c|
      ('0'..'9').each do |d|
        combo = a + b + c + d
        rows = query.execute(combo)
        puts combo unless rows.next
      end
    end
  end
end
download code