Every launch starts with a name, and every name needs a handle. The GitHub organization, the npm package, the X account, the Bluesky handle, the username that will post the launch on Hacker News, the .com. Checking them one tab at a time takes twenty minutes, and the tools that check them for you tend to guess.

IndieHandle asks each platform directly and reports what it said. Enter a handle and it asks 22 places at once: code hosts and package registries, social networks and communities, publishing and selling tools, and the registries behind .com, .io, and .dev. Each row says free, taken, or could not check, with the HTTP status that produced it and a link to the exact URL it asked.

The rule that shapes the tool is simple. A platform that answers not found is free. A platform that serves a page or a record is taken. Anything else is could not check, and it stays could not check. Reddit refuses keyless checks from servers, and Product Hunt puts a bot challenge in front of profiles, so those rows will often say so. A row that says could not check is a row you open yourself. A row that says free when the name is taken would cost you a launch, so IndieHandle never produces one.

Each platform also has its own rules for what a name can be. X stops at 15 characters, Docker IDs need four, crate names start with a letter, and a domain label cannot start with a hyphen. When a handle does not fit a platform, the row says not valid here and quotes the rule, and that platform is not asked.

Free means free at the moment of the check, from Cloudflare’s network. A name can be reserved by the platform, held by a deleted account, or registered a minute after you looked. The row’s link is there so you can confirm before you commit.

The core stays free. There is no account, card, premium plan, or public list of checked handles. IndieHandle stores no lookup history and loads no analytics or third-party script in the page.

How each platform is read

Every row rests on one request to one fixed URL, with the handle filled in. Each rule below was verified on 2026-09-02 by asking for one handle known to be taken and one random string known to be free. If a platform changes its answers, the row falls back to could not check, because these rules only ever turn a specific answer into free or taken. Every request goes out with the user agent IndieHandle/0.1, follows no redirects, and gives up after eight seconds.

Code and packages

  • GitHub, username. HEAD https://github.com/{handle}. 404 free, 200 taken. A redirect means the name is reserved by GitHub, such as settings, and counts as taken. The REST API was not used because its keyless limit is 60 requests an hour per address, which a shared network exhausts in minutes.
  • GitLab, username. GET https://gitlab.com/api/v4/users?username={handle}. An empty list is free. A list with an account is taken.
  • npm, package name. GET https://registry.npmjs.org/{handle}. 404 free, 200 taken. This is the package name, not the npm username: the user endpoint needs a login and the website answers servers with a bot challenge.
  • PyPI, project name. GET https://pypi.org/pypi/{handle}/json. 404 free, 200 taken. A redirect means an existing project normalizes to this name, and counts as taken.
  • crates.io, crate name. GET https://crates.io/api/v1/crates/{handle}. 404 free, 200 taken.
  • RubyGems, gem name. GET https://rubygems.org/api/v1/gems/{handle}.json. 404 free, 200 taken.
  • Docker Hub, Docker ID. GET https://hub.docker.com/v2/users/{handle}/. 404 free, 200 a user, and a 308 redirect an organization, both taken.

Social and communities

  • X, username. HEAD https://x.com/{handle}. 404 free. 200 means the name is in use, suspended, or reserved, and counts as taken. A redirect is could not check.
  • Bluesky, handle at bsky.social. GET https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?handle={handle}.bsky.social. A DID is taken. A 400 whose message is “Unable to resolve handle” is free. The row covers the default bsky.social handle only, not custom domains.
  • Mastodon, username at mastodon.social. GET https://mastodon.social/api/v1/accounts/lookup?acct={handle}. 404 free, 200 taken. Other instances are not checked.
  • Reddit, username. GET https://www.reddit.com/user/{handle}/about.json. 404 free, 200 taken. On 2026-09-02 Reddit answered every server request with 403, so this row usually says could not check and links the profile for you to open.
  • Hacker News, username. GET https://hacker-news.firebaseio.com/v0/user/{handle}.json, the official Hacker News API. A body of null is free. A user record is taken. The website’s own user page answers Cloudflare’s network with 429, so it is not used.
  • DEV Community, username. GET https://dev.to/api/users/by_username?url={handle}. 404 free, 200 taken.
  • Indie Hackers, username. GET https://www.indiehackers.com/{handle}. 404 free, 200 taken.
  • Product Hunt, username. HEAD https://www.producthunt.com/@{handle}. 404 free, 200 taken. On 2026-09-02 Product Hunt answered every server request with a 403 bot challenge, so this row usually says could not check and links the profile.
  • YouTube, handle. HEAD https://www.youtube.com/@{handle} with the cookie SOCS=CAI, which skips the regional consent page. 404 free, 200 taken. Any remaining redirect is could not check.

Publishing and selling

  • Substack, profile handle. GET https://substack.com/@{handle}. 200 taken. A redirect to substack.com/search/{handle}?searching=profile is Substack’s own answer for a profile that does not exist, and is free. Any other redirect is could not check. This is the profile handle, not a publication subdomain: the subdomains answer Cloudflare’s network with 429.
  • Gumroad, subdomain. GET https://{handle}.gumroad.com/. 404 free, 200 taken.
  • Linktree, username. GET https://linktr.ee/{handle}. 404 free, 200 taken.

Domains

Each domain row asks the registry’s RDAP service, the public successor to WHOIS defined in RFC 9083. 404 means the name is not registered. 200 means it is.

  • .com: GET https://rdap.verisign.com/com/v1/domain/{handle}.com.
  • .io: GET https://rdap.identitydigital.services/rdap/domain/{handle}.io.
  • .dev: GET https://pubapi.registry.google/rdap/domain/{handle}.dev.

Left out on purpose

Medium and Ko-fi answered every server request with 403. Threads serves a profile with 200 and sends everything else to a login page, which a private profile also gets, so a free reading would be a guess. Telegram, Twitch, Instagram, TikTok, and LinkedIn give a server no keyless signal at all. A row that could only ever say could not check is noise, and a row that guesses is worse, so those platforms are not on the list. When one of them exposes a reliable answer, it can be added.