# Domain Availability Checker & Brand TLD Matrix (`truenorth/brand-domain-availability-matrix`) Actor

Check brand keywords across TLDs with authoritative RDAP and DNS evidence, stable matrix output, and explicit unknown states.

- **URL**: https://apify.com/truenorth/brand-domain-availability-matrix.md
- **Developed by:** [TrueNorth](https://apify.com/truenorth) (community)
- **Categories:** Developer tools, Automation, SEO tools
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 domain checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Domain Availability Checker & Brand TLD Matrix

Turn brand names into a deterministic keyword × top-level domain (TLD) matrix for naming research, startup domain discovery, agency projects, portfolio monitoring, and brand-protection watchlists. This bulk domain checker uses authoritative Registration Data Access Protocol (RDAP) routing plus optional Domain Name System (DNS) evidence and returns one auditable row per candidate.

Every result is `registered`, `available`, or `unknown`. Stable row, column, and matrix indexes make repeated runs easy to compare through JSON, CSV, Excel, Google Sheets, webhooks, or the Apify API.

Use it as a TLD availability matrix, TLD checker, brand domain checker, RDAP domain lookup, domain status API, domain availability API, or brand domain monitor. It is not a WHOIS scraper, premium domain pricing tool, registrar checkout, or domain-registration service.

This Actor is not affiliated with Vercel, any registry, or any registrar. It does not return registrar prices, premium status, purchasability, ownership advice, trademark clearance, registration services, or purchase guarantees.

### Why use this domain availability checker?

- Generate every brand keyword × TLD combination automatically.
- Discover registry RDAP endpoints from the official Internet Assigned Numbers Authority (IANA) bootstrap registry.
- Require both authoritative RDAP `404` and exact DNS `NXDOMAIN` before returning `available`.
- Preserve explicit `unknown` results for rate limits, unsupported TLDs, stale evidence, malformed responses, transport failures, and RDAP/DNS conflicts.
- Include evidence timestamps, endpoint provenance, cache status, attempts, HTTP status, and stable reason codes.
- Export one strict domain-status API row per candidate.
- Schedule identical matrices and monitor domain registration status over time.
- Cache stable positive and negative evidence while never persisting transient errors.

### Input

```json
{
  "keywords": ["acme", "acme-labs"],
  "tlds": ["com", "org", "io"],
  "dnsCorroboration": true
}
```

| Field              | Required | Exact limits                            | Meaning                                     |
| ------------------ | -------- | --------------------------------------- | ------------------------------------------- |
| `keywords`         | yes      | 1–100; each canonical label ≤ 63 bytes  | One DNS label per entry                     |
| `tlds`             | no       | 1–50; default `com`, `org`, `net`, `io` | Single-label TLDs; one leading dot accepted |
| `dnsCorroboration` | no       | default `true`                          | Required for any `available` result         |

Maximum matrix size is 2,000 cells. Input is Unicode Normalization Form C (NFC)-normalized, lowercased, converted with Internationalized Domain Names in Applications (IDNA), and validated at runtime. Canonical duplicates, embedded dots, invalid labels, unknown properties, and oversized matrices fail input validation.

### Output

Default dataset contains one strict item per matrix cell. Keyword order is outer; TLD order is inner. Concurrent network completion never changes row-major output order.

```json
{
  "keyword": "acme",
  "tld": "com",
  "canonicalKeyword": "acme",
  "canonicalTld": "com",
  "domain": "acme.com",
  "rowIndex": 0,
  "columnIndex": 0,
  "matrixIndex": 0,
  "status": "unknown",
  "reason": "CONFLICT_RDAP_404_DNS_EXISTS",
  "checkedAt": "2026-07-27T12:00:00.000Z",
  "rdap": {
    "classification": "not_found",
    "authoritative": true,
    "bootstrapFresh": true,
    "serviceBaseUrl": "https://registry.example/rdap/",
    "requestUrl": "https://registry.example/rdap/domain/acme.com",
    "finalUrl": "https://registry.example/rdap/domain/acme.com",
    "httpStatus": 404,
    "attempts": 1,
    "cached": false,
    "responseTimeMs": 121,
    "checkedAt": "2026-07-27T12:00:00.000Z",
    "errorCode": null
  },
  "dns": {
    "enabled": true,
    "classification": "exists",
    "queryType": "SOA",
    "attempts": 1,
    "cached": false,
    "responseTimeMs": 42,
    "checkedAt": "2026-07-27T12:00:00.000Z",
    "errorCode": null
  }
}
```

Run-level `OUTPUT` in the default key-value store reports exact `total`, `registered`, `available`, and `unknown` counts, DNS setting, timestamps, and dataset ID.

### Understanding the three states

- `registered`: authoritative RDAP returned a valid matching domain entity. With DNS enabled, DNS must not contradict RDAP with `NXDOMAIN`.
- `available`: fresh IANA routing led to an authoritative RDAP `404`, and DNS returned exact `NXDOMAIN`.
- `unknown`: evidence was incomplete, stale, unsupported, malformed, rate-limited, unavailable, or contradictory.

`available` describes evidence at check time, not a purchase guarantee. Domain state can change immediately after a check.

Common `unknown` reasons:

- `CONFLICT_RDAP_FOUND_DNS_NXDOMAIN`
- `CONFLICT_RDAP_404_DNS_EXISTS`
- `DNS_ERROR`
- `DNS_REQUIRED_FOR_AVAILABILITY`
- `STALE_BOOTSTRAP_CANNOT_PROVE_AVAILABILITY`
- `NO_AUTHORITATIVE_RDAP_SERVICE`
- `RDAP_HTTP_ERROR`
- `RDAP_RATE_LIMITED`
- `RDAP_TRANSPORT_ERROR`
- `RDAP_INVALID_RESPONSE`

### Evidence and cache policy

Actor downloads official IANA DNS RDAP bootstrap data, accepts only HTTPS service bases, follows at most three HTTPS redirects, and never guesses registry endpoints. Bootstrap remains fresh for 24 hours and can locate positive RDAP records from stale fallback for up to seven days; stale `404` never proves availability.

Cached evidence keeps its original timestamp:

- RDAP found: 12 hours
- RDAP `404`: 15 minutes
- DNS exists: 15 minutes
- DNS `NXDOMAIN`: 5 minutes

Errors are never persisted between runs. DNS disabled skips DNS network calls; RDAP `404` then remains `unknown`. A DNS Start of Authority (SOA) query distinguishes exact `NXDOMAIN` from `NOERROR` with no data (`NODATA`).

### Billing behavior

Pay-Per-Event (PPE) integration uses one `domain-checked` event per successfully persisted dataset row. No event is charged before persistence, after a failed dataset write, or during guarded local fixture verification. Apify Store pricing shown at run time is the source of truth; this repository does not claim that planned pricing is remotely configured.

### Monitoring and AI workflows

Schedule identical input and compare `domain`, `status`, `reason`, and `checkedAt`. Stable indexes support Sheets, CSV, webhooks, vector databases, relational databases, and Retrieval-Augmented Generation (RAG) pipelines. Preserve `status`, `reason`, `rdap`, and `dns` when asking a large language model (LLM) to rank candidates. Treat transitions into or out of `unknown` as evidence-health changes, not registration events.

Do not use output as legal trademark advice or proof that a domain can be purchased.

### Data sources and limits

- IANA RDAP bootstrap: `https://data.iana.org/rdap/dns.json`
- Registry RDAP endpoints: validated HTTPS bases published through IANA bootstrap data
- DNS evidence: exact SOA query with `NXDOMAIN` separated from `NOERROR/NODATA`

No WHOIS (historical domain-registration lookup protocol) HTML scraping, browser automation, registrar account, private API key, pricing endpoint, checkout action, typo generation, or legal conclusion is used.

### Local development

Requires Node.js 22 and pnpm 10.

```sh
pnpm install --frozen-lockfile
pnpm test
pnpm coverage
pnpm format:check
pnpm lint
pnpm typecheck
pnpm build
pnpm validate:schemas
apify validate-schema
```

Deterministic fixture mode is internal and test-only. It requires `NODE_ENV=test`, loopback transport, fixture files under `tests/fixtures`, and a non-Cloud environment. Any fixture flag on Apify Cloud aborts startup. Fixture verification persists rows and writes `OUTPUT` but never emits PPE charges.

# Actor input Schema

## `keywords` (type: `array`):

Enter 1–100 single-label brand keywords. Values are combined with every selected TLD; total matrix size cannot exceed 2,000 cells.

## `tlds` (type: `array`):

Enter 1–50 single-label top-level domains, with or without one leading dot.

## `dnsCorroboration` (type: `boolean`):

Keep enabled to allow available results. DNS errors or disabled corroboration keep negative RDAP evidence unknown.

## Actor input object example

```json
{
  "tlds": [
    "com",
    "org",
    "net",
    "io"
  ],
  "dnsCorroboration": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("truenorth/brand-domain-availability-matrix").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("truenorth/brand-domain-availability-matrix").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call truenorth/brand-domain-availability-matrix --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,truenorth/brand-domain-availability-matrix"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/HelEFd6lC1Nmg43Xy/builds/slmHUvB6B4lO4Q3pU/openapi.json
