Summary

Use the name.com domain availability API to run bulk ccTLD queries, scope results without a tldFilter, and separate registered, unoffered, and unsupported TLDs. Stop sending users to dead ends.

Most availability API implementations collapse three distinct failure states into one. Your code gets purchasable: false, shows the user that the domain is "unavailable," and leaves it at that. The problem is that purchasable: false can mean one of three different things: the domain is already registered, name.com doesn't carry that TLD, or the API doesn't support that TLD at all. Each requires a different response from your application. Most availability solutions don't surface this distinction at all, leaving integrations with no reliable way to tell the three cases apart.

The name.com domains:check-availability endpoint returns both purchasable and reason in every response. This guide covers how to structure bulk availability queries correctly, how to scope ccTLD results without a tldFilter parameter, and how to branch on all three purchasable: false scenarios so your users get useful information instead of a dead end.

1. What the name.com availability endpoint actually returns

The /core/v1/domains:checkAvailability endpoint uses HTTP Basic Auth. Pass your username and API token as username:token. In the sandbox environment, you’ll use https://api.dev.name.com as your base URL, append -test to your username and use your sandbox token. The production environment is available at https://api.name.com. Do all your exploratory work in the sandbox environment first. Our sandbox uses registry test data, which means availability results may differ from production, but that's exactly what you want when validating response shapes without spending money.

A minimal single-domain request:

Bash
curl -u "yourusername-test:your-sandbox-token" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"domainNames": ["acmecorp.de"]}' \
  https://api.dev.name.com/core/v1/domains:checkAvailability

You should receive a response similar to this:

JSON
{
  "results": [
    {
      "domainName": "acmecorp.de",
      "purchasable": true,
      "purchasePrice": 19.99,
      "purchaseType": "registration",
      "renewalPrice": 19.99,
      "sld": "acmecorp",
      "tld": "de"
    }
  ]
}

The response for each domain in the results array includes four fields: domainName (the fully-qualified domain you queried), sld (the second-level label, e.g. acmecorp), tld (the extension, e.g. .de) and purchasable (boolean).

purchasable: true requires no further inspection. You can safely mark the domain as available.

2. Bulk domain availability queries: The AvailabilityRequest structure and the 50-domain limit

The checkAvailability endpoint accepts up to 50 fully-qualified domain names per call in the domainNames array. The request body also accepts an optional purchaseType field. For standard reseller registration flows, set it to "registration". This filters results to domains that can actually be purchased as new registrations, which is almost always what you want when building a domain search feature.

JSON
{
  "domainNames": ["acmecorp.com", "acmecorp.io", "acmecorp.de"],
  "purchaseType": "registration"
}

The checkAvailability endpoint has no tldFilter parameter. You control the scope entirely by which domain names you pass in. Include domains like acmecorp.de and acmecorp.nl in the domainNames[] array.

For lists larger than 50 domains, chunk them client-side:

python
import requests
from itertools import islice

def chunk(lst: list, n: int):
    it = iter(lst)
    while batch := list(islice(it, n)):
        yield batch

def check_bulk(domains: list[str], username: str, token: str, sandbox: bool = True) -> list[dict]:
    base_url = "https://api.dev.name.com" if sandbox else "https://api.name.com"
    url = f"{base_url}/core/v1/domains:checkAvailability"
    results = []
    for batch in chunk(domains, 50):
        resp = requests.post(
            url,
            json={"domainNames": batch, "purchaseType": "registration"},
            auth=(username, token),
        )
        resp.raise_for_status()
        results.extend(resp.json().get("results", []))
    return results

# Example usage
user = "youruser@yourcorp-test"
token = "yourtoken"
domains = ["acmecorp.com", "acmecorp.io", "acmecorp.de"]

results = check_bulk(domains=domains, username=user, token=token, sandbox=True)

print(results)

Watch your rate limits! Our API documentation covers per-account limits in the overview section.

The 50-domain ceiling shows up most in ccTLD-heavy queries. If your platform supports 10 ccTLDs and a user types a domain name, that's 10 domains in one call, which is well under the limit. If you're building a "check everything" feature that hits 100+ TLDs, you should be batching the calls. Build the chunking logic in from the start.

3. Scoping ccTLD availability results without a tldFilter parameter

Because checkAvailability takes explicit domain names rather than a TLD filter, ccTLD scoping is a construction problem. Build the list of fully-qualified domains before the request. Take the user's SLD, concatenate each target ccTLD, and pass the resulting array:

python
sld = "acmecorp"
target_tlds = [".de", ".nl", ".ca", ".co.uk", ".io"]
domains = [f"{sld}{tld}" for tld in target_tlds]

# ["acmecorp.de", "acmecorp.nl", "acmecorp.ca", "acmecorp.co.uk", "acmecorp.io"]

Two practical strategies for deciding which ccTLDs make it into that list:

  • Curated static list: Maintain a set of TLDs your platform officially supports (15 to 20 ccTLDs that are most relevant to your user base) and always construct the domain list from it. This is the right starting point for new builds. It keeps your result set predictable, makes the UI easy to design around, and prevents unsupported TLDs from appearing in queries. The downside is that you need to update the list manually when adding coverage.
  • User-driven picker: Let users select the ccTLDs they care about, then have your backend construct the domain list from their selection. This gives users more control, but you need to validate that every selected TLD is supported before sending the request. More on that in Section 5.

One critical behavior to understand: if you include a domain with a TLD the API doesn't support, it won't appear in the response. No error, no purchasable: false, just a missing entry. You can't infer "TLD not supported" from a missing result unless you're tracking what you sent versus what came back. That gap is what creates the third failure scenario.

4. Decoding purchasable: false: Three domain availability scenarios

The reason field separates three genuinely different situations that all produce purchasable: false (or no result at all).

Scenario A: Domain is registered. The registry has a match. The reason field will indicate the domain is taken. This is the common case your UI almost certainly already handles.

JSON
{
  "domainName": "google.com",
  "sld": "google",
  "tld": ".com",
  "purchasable": false,
  "reason": "registered"
}

Show the user a clear "this domain is taken" state and surface alternatives. For example, the search UI can suggest google.io or google.dev if those come back as available.

Scenario B: TLD exists but name.com doesn't resell it. Not every TLD is in our catalog, even though the registry itself exists. The reason field returns "not_offered".

JSON
{
  "domainName": "acmecorp.tk",
  "sld": "acmecorp",
  "tld": ".tk",
  "purchasable": false,
  "reason": "not_offered"
}

Don't show this as "taken." Surface a distinct state: "This TLD isn't available for registration through this platform." Conflating this with Scenario A is the most common mistake. A user sees "unavailable" and assumes someone else owns their name, when they actually hit a coverage delta.

Scenario C: TLD is unsupported— domain absent from response. Send acmecorp.zz and if .zz isn't in the API's supported set, the domain won't appear in the results array at all. No purchasable field, no reason, just a missing entry. Detect this by diffing what you sent against what came back:

python
sld = "acmecorp"
target_tlds = [".de", ".nl", ".ca", ".co.uk", ".io", ".zz"]
domains = [f"{sld}{tld}" for tld in target_tlds]

requested = set(domains)

results = check_bulk(domains=domains, username=user, token=token, sandbox=True)

returned = {r["domainName"] for r in results}

missing = requested - returned  # TLDs the API didn't return data for

print(missing)

The missing set is your unsupported TLD signal. Handle it separately from the purchasable: false branch.

The full branching logic across all three cases:

The corresponding Python branching logic over a merged result set:

python
def classify_results(requested: list[str], results: list[dict]) -> None:
    returned = {r["domainName"]: r for r in results}

    for domain in requested:
        if domain not in returned:
            # Scenario C: no data returned— TLD likely unsupported
            print(f"[NO DATA]     {domain}— TLD not supported by API")
            continue

        result = returned[domain]
        purchasable = result.get("purchasable", False)
        reason = result.get("reason", "")

        if purchasable:
            print(f"[AVAILABLE]   {domain}")
        elif "registered" in reason.lower():
            # Scenario A: domain is taken
            print(f"[TAKEN]       {domain}")
        elif "not_offered" in reason.lower() or "not offered" in reason.lower():
            # Scenario B: TLD not in name.com's catalog
            print(f"[NOT OFFERED] {domain}— TLD not sold by name.com")
        else:
            print(f"[UNAVAILABLE] {domain}— {reason}")

Check the exact reason string values in your sandbox responses before hardcoding comparisons. The lower() calls above are defensive. Match on substrings until you've confirmed the exact format from live responses.

5. Handling unsupported TLDs: detection, validation, and user-facing messaging

Prevent unsupported TLDs from entering the query rather than detecting them at query time.

name.com supports over 600 TLDs. You can fetch TLD-level requirements programmatically via the requirements endpoint:

Bash
curl -u "yourusername-test:your-sandbox-token" \
  https://api.dev.name.com/core/v1/domaininfo/requirements/de

This returns registration requirements for .de. If a TLD isn't in our catalog, this endpoint returns an error:

JSON
{
  "message": "Invalid Argument",
  "details": "Required Parameter Missing - Invalid Tld"
}

Use this to pre-validate TLDs before exposing them in your UI, or to build a local allowlist from the API's supported set. A nightly sync job that hits the requirements endpoint for each TLD in your UI picker is cheap and keeps your list current without manual maintenance.

For most teams, a simpler approach works better: maintain a static list of the ccTLDs you've verified work end-to-end with name.com (availability query, registration, DNS management) and only expose those in your UI. Start with the 20 most relevant to your users and expand from there.

Three options for handling TLDs your platform can't register, in order of quality:

  1. Hide unsupported TLDs from the picker entirely. Users never see options they can't act on. This is a sane default for new builds. No dead ends, no confusing messages, no edge-case handling in the frontend.
  2. Show them as disabled with a label. Display .tk - not available for registration greyed out. This tells users the TLD exists but is unavailable through your platform.
  3. Redirect to our registration UI as a fallback. If a user really wants .tk, send them to name.com directly. This should be considered a last resort, though.

Start with option 1. You can always loosen the constraint later.

6. A complete working example: Bulk ccTLD availability check

This self-contained Python script covers bulk query with chunking, ccTLD-scoped domain construction, and three-way result branching. Run it against the sandbox to see the response shapes before wiring any of this into your application.

python
import requests
from itertools import islice

# Config
# Swap BASE_URL and credentials for production when ready
BASE_URL = "https://api.dev.name.com"
USERNAME = "yourusername-test"   # append -test for sandbox
TOKEN    = "your-sandbox-token"

SUPPORTED_CCTLDS = [".de", ".nl", ".ca", ".io", ".co"]  # your curated list

# Helpers
def chunk(lst: list, n: int):
    it = iter(lst)
    while batch := list(islice(it, n)):
        yield batch

def check_availability(domains: list[str]) -> list[dict]:
    url = f"{BASE_URL}/core/v1/domains:checkAvailability"
    results = []
    for batch in chunk(domains, 50):
        resp = requests.post(
            url,
            json={"domainNames": batch, "purchaseType": "registration"},
            auth=(USERNAME, TOKEN),
        )
        resp.raise_for_status()
        results.extend(resp.json().get("results", []))
    return results

def classify(requested: list[str], results: list[dict]) -> None:
    returned = {r["domainName"]: r for r in results}
    for domain in requested:
        if domain not in returned:
            print(f"[NO DATA]     {domain}")
            continue
        r      = returned[domain]
        reason = r.get("reason", "")
        if r.get("purchasable"):
            print(f"[AVAILABLE]   {domain}")
        elif "registered" in reason.lower():
            print(f"[TAKEN]       {domain}")
        elif "not_offered" in reason.lower() or "not offered" in reason.lower():
            print(f"[NOT OFFERED] {domain}")
        else:
            print(f"[UNAVAILABLE] {domain}  reason={reason!r}")

# Main
sld     = "acmecorp"
domains = [f"{sld}{tld}" for tld in SUPPORTED_CCTLDS]

print(f"Checking {len(domains)} domains across {len(SUPPORTED_CCTLDS)} ccTLDs...\n")
results = check_availability(domains)
classify(domains, results)

To run it: install requests (pip install requests), drop in your credentials, and fire it against the sandbox. You'll see the exact reason string values in the raw response. Use those to tighten up the string matching before you deploy.

Frequently asked questions

What does purchasable: false mean in the name.com API?

purchasable: false can mean one of three things: the domain name is already registered, the TLD exists but name.com does not resell it, or the TLD is unsupported by the API and returns no result at all. Always read the reason field alongside purchasable to determine which scenario applies.

How do I check ccTLD availability with the name.com checkAvailability endpoint?

The checkAvailability endpoint has no tldFilter parameter. To scope results to specific country-code TLDs, construct the fully-qualified domain names before the request (acmecorp.de, acmecorp.nl) and pass them directly in the domainNames array.

How many domains can I query in one name.com API call?

The POST /core/v1/domains:checkAvailability endpoint accepts up to 50 fully-qualified domain names per request. For lists exceeding 50, chunk them client-side and send sequential or concurrent batches.

How do I detect unsupported TLDs in the name.com API response?

If a TLD is unsupported, the domain is absent from the results array with no error and no purchasable: false entry. Detect this by diffing your requested domain list against the returned domainName values. Anything in the delta was not recognized by the API.

What is the reason field in the name.com domain availability response?

The reason field is a string populated whenever purchasable is false. Common values include "registered" (domain is taken) and "not_offered" (TLD not in name.com’s catalog).

Should I use the sandbox or production API while building a domain search integration?

Always start with the sandbox at https://api.dev.name.com. Append -test to your username and use your sandbox token. The sandbox uses registry test data, so availability results differ from production, which is exactly what you want when validating response shapes and error handling before going live.

Wrapping up

The purchasable boolean tells you whether a domain can be bought. The reason field tells you why it can't be. Ignoring reason produces the exact failure mode that makes domain search UIs frustrating: users hit a dead end with no context about whether to try a different name, a different TLD, or a different platform entirely.

Our core/v1 API gives you the signal to distinguish all three cases. Explicit domain list construction for ccTLD scoping, client-side chunking for bulk queries above 50, and diffing requested versus returned to catch unsupported TLDs are what production-grade integrations actually look like.

Generate your free sandbox API token at docs.name.com via Account Settings > Security > API Tokens. The "Try it" tool in the docs lets you fire a bulk availability request directly in the browser, so you can confirm the response shape before you write a single line of integration code.

Start for free