As of about 11pm yesterday, I’m the proud owner of 0hats.com.
On Friday, I received a link to a document hosted on 17hats.com, which as far as I can tell is some kind of CRM. 17 is a fun number1, and the concept of wearing 17 is a silly one and got a chuckle out of me. On a whim, I checked if 19hats.com (the next largest prime quantity of hats) was taken. It was. 23hats? Taken. 29hats? Also taken. Well then, what’s the smallest numbered hat quantity that I could register as my own domain?
A first attempt went something like this:
% for i in {1..50}; do dig ${i}hats.com | grep -i nxdomain >/dev/null && echo ${i}hats.com is available; done
5hats.com is available
16hats.com is available
26hats.com is available
28hats.com is available
30hats.com is available
35hats.com is available
36hats.com is available
37hats.com is available
41hats.com is available
43hats.com is available
44hats.com is available
46hats.com is available
48hats.com is available
49hats.com is available
%
(That’s not exactly right, as 5hats.com is registered, but doesn’t have a DNS entry associated with it.)
Anyway, I ended up getting well and truly nerd sniped by the problem—how many of these are registered? What are they used for? What’s the smallest number of hats whose domain name I could own?
So a few hours of Go code
later, 0hats.com graced belabored the world with its
presence.
In short, for each domain from 0hats.com to some limit (I’ve chosen 50, rather arbitrarily):
- Checks if the domain is registered with a whois lookup, and if it is, notes the owner
- Does a DNS lookup to see if there may be anything hosted at the site
- Opens a geckodriver instances, browses to the page, grabs the title, and takes a screenshot.
- and then renders the whole thing to one big list.
I’ve already snagged the smallest possible non-negative quantity of hats, but if anyone is interested, 16hats.com is available at the time of writing!
I also did a very basic scan of {51..1000} hats; it seems that registrations drop off pretty quickly after 50.
package main
import (
"fmt"
"github.com/likexian/whois"
whoisparser "github.com/likexian/whois-parser"
)
func main() {
for i := 0; i < 1000; i++ {
domainName := fmt.Sprintf("%vhats.com", i)
// Check if domain is registered
query_result, err := whois.Whois(domainName)
if err != nil {
panic(err)
}
_, err = whoisparser.Parse(query_result)
if err == whoisparser.ErrNotFoundDomain {
fmt.Println(domainName, " is available")
} else if err != nil {
panic(err)
} else {
fmt.Println(domainName, " is taken")
}
}
}
% time go run main.go >/dev/null
go run main.go 2.58s user 1.96s system 1% cpu 5:03.92 total
% go run main.go | grep "taken" | wc -l # How many in total?
77
% go run main.go | tail +52 | grep "taken" | wc -l # How many above 50?
39
% go run main.go | tail +52 | grep "taken"
51hats.com is taken
52hats.com is taken
58hats.com is taken
66hats.com is taken
68hats.com is taken
69hats.com is taken
73hats.com is taken
80hats.com is taken
83hats.com is taken
86hats.com is taken
88hats.com is taken
89hats.com is taken
97hats.com is taken
99hats.com is taken
100hats.com is taken
101hats.com is taken
112hats.com is taken
123hats.com is taken
208hats.com is taken
210hats.com is taken
234hats.com is taken
241hats.com is taken
247hats.com is taken
252hats.com is taken
300hats.com is taken
310hats.com is taken
360hats.com is taken
365hats.com is taken
386hats.com is taken
420hats.com is taken
444hats.com is taken
500hats.com is taken
501hats.com is taken
586hats.com is taken
710hats.com is taken
777hats.com is taken
802hats.com is taken
906hats.com is taken
911hats.com is taken
-
The answer to this is very simple. It was a joke. It had to be a number, an ordinary, smallish number, and I chose that one. Binary representations, base thirteen, Tibetan monks are all complete nonsense. I sat at my desk, stared into the garden and thought ‘42 will do’ I typed it out. End of story.