# Bulk Domain Availability Checker: WHOIS, RDAP & Expiry (`hillcountrybots/domain-availability-checker`) Actor

Check if domain names are available or taken, in bulk, from official registry RDAP (the modern WHOIS): registrar, creation and expiry dates, nameservers and status codes. Try names across TLDs. No personal data. $1 per 1,000 domains.

- **URL**: https://apify.com/hillcountrybots/domain-availability-checker.md
- **Developed by:** [Hill Country Bots](https://apify.com/hillcountrybots) (community)
- **Categories:** Developer tools, SEO tools, Automation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Bulk Domain Availability Checker: WHOIS, RDAP & Expiry

**Check whether domain names are available or taken, in bulk.** The answers come straight from the official registry **RDAP** servers listed by IANA. RDAP is the modern replacement for WHOIS. For every registered domain you also get the registrar, the creation and expiry dates, the nameservers and the status codes. **No personal data is collected.** **$1.00 per 1,000 checked domains.** Invalid inputs and errors are free.

### What does this domain availability checker do?

- **Bulk domain check:** paste a list of full domains (`example.com`), or try base names across TLDs (`brightbakery` × `com, net, io, dev`).
- Picks the right registry server for each TLD from the IANA RDAP bootstrap file, which covers about 590 TLDs, including .com, .net, .org, .dev, .app, .ai, .xyz and .info.
- Gives every domain a clear `status`:
  - `available`: the registry has no record of the name
  - `registered`: the name is taken
  - `likely_available`: the TLD has no public RDAP (.io, .co, .de, .us) and DNS says the name doesn't exist. Confirm at a registrar.
  - `unsupported_tld`, `invalid` or `error`: no answer. These rows are free.
- For taken domains, a **WHOIS-style record without contacts**: `registrar`, `registrarIanaId`, `createdAt`, `expiresAt`, `updatedAt`, `nameservers`, `statusCodes` and `dnssec`.

### Who is it for?

- **Founders, brand and naming teams:** shortlist names and see which TLDs are free in one run
- **Domain investors and agencies:** check expiry dates, registrars and status locks across a whole portfolio
- **AI agents and automations:** a fast "is this domain free?" tool through the API or MCP, with a fixed price per result

### Quick start

1. Enter domains, or names plus TLDs. The form comes prefilled, so **Start** works right away.
2. Leave **DNS fallback** on to get answers for TLDs without public RDAP (for example `.io`).
3. Click **Start**, then download JSON, CSV or Excel, or read the results through the API.

In our tests a lookup took about 0.3 s on average, and 30 domains finished in under 5 s.

#### Sample output

This table is from a real run on **November 10, 2026, at 9:34 PM CT** (America/Chicago). You pay about **$1 per 1,000** domains that come back available, likely available, or registered. Invalid inputs and errors are free.

![Sample output from a real Bulk Domain Availability Checker run](https://api.apify.com/v2/key-value-stores/2kusIBSeqRffwM3Q9/records/domain-sample-output.png?signature=7xYpTWBkvAldGVfOPCUL)

| Domain | Status | Registrar | Created | Expires |
|---|---|---|---|---|
| google.com | registered | MarkMonitor Inc. | Sep 15, 1997 | Sep 14, 2028 |
| wikipedia.org | registered | MarkMonitor Inc. | Jan 13, 2001 | Jan 13, 2027 |
| hillcountrybots-example-name.com | available | n/a | n/a | n/a |

Created and expiry dates are the registry's UTC timestamps, shown as calendar days. If a name cannot be checked, the run writes a row with `status` `invalid` or `error` and a plain-English `note` instead of finishing as a silent success with empty data. Those rows are not charged.

#### Example inputs

Bulk domain availability check for a list of full domain names:

```json
{
  "domains": ["google.com", "wikipedia.org", "hillcountrybots-example-name.com"]
}
```

Try one brand name across popular TLDs (including .io, which falls back to DNS):

```json
{
  "names": ["brightbakery-atx"],
  "tlds": ["com", "net", "org", "io", "dev", "app"]
}
```

Bulk expiry and registrar lookup for registered domains (WHOIS-style RDAP, no personal data):

```json
{
  "domains": ["google.com", "wikipedia.org", "github.com"]
}
```

List plus name-across-TLDs in one run:

```json
{
  "domains": ["google.com", "wikipedia.org"],
  "names": ["brightbakery-atx"],
  "tlds": ["com", "net", "org", "io", "dev", "app"]
}
```

Ready-to-run example tasks (pre-filled inputs on this Actor's Store page):

- [Check whether a list of domains is available](https://apify.com/hillcountrybots/domain-availability-checker/examples/domain-list-availability)
- [Try a brand name across popular TLDs](https://apify.com/hillcountrybots/domain-availability-checker/examples/domain-name-across-tlds)

### Input

| Field | Default | What it does |
|---|---|---|
| `domains` | `[]` | Full domains. URLs and `www.` are cleaned automatically. |
| `names` | `[]` | Base names to combine with `tlds`. |
| `tlds` | `[]` | e.g. `["com","net","org","io"]` |
| `dnsFallback` | `true` | Uses DNS for TLDs that have no public RDAP. |
| `maxConcurrency` | 4 | Parallel checks. Each registry server still gets one request at a time. |
| `minDelayPerServerMs` | 300 | Gap between requests to the same registry, for politeness. |
| `maxResults` | 1000 | Most domains per run. Spend is capped at `maxResults` × $0.001. |
| `requestTimeoutSecs` | 20 | Per-request timeout. Each domain gets up to 4 attempts with backoff. |

### Output example

These are real rows from a test run on Nov 10, 2026. A registered domain:

```json
{
  "domain": "google.com",
  "tld": "com",
  "registrar": "MarkMonitor Inc.",
  "registrarIanaId": "292",
  "createdAt": "1997-09-15T04:00:00Z",
  "expiresAt": "2028-09-14T04:00:00Z",
  "updatedAt": "2019-09-09T15:39:04Z",
  "nameservers": [
    "ns1.google.com",
    "ns2.google.com",
    "ns3.google.com",
    "ns4.google.com"
  ],
  "statusCodes": [
    "client delete prohibited",
    "client transfer prohibited",
    "client update prohibited",
    "server delete prohibited",
    "server transfer prohibited",
    "server update prohibited"
  ],
  "dnssec": false,
  "status": "registered",
  "method": "rdap",
  "rdapServer": "rdap.verisign.com",
  "durationMs": 175,
  "checkedAt": "2026-11-10T20:32:34.449Z"
}
```

An available domain:

```json
{"domain": "hcb-zq7-unlikely-48213.com", "tld": "com", "nameservers": [], "statusCodes": [], "status": "available", "method": "rdap", "rdapServer": "rdap.verisign.com", "note": "Not found in the registry RDAP. Premium or reserved names may still be unregistrable or cost more.", "durationMs": 467, "checkedAt": "2026-11-10T20:32:35.808Z"}
```

A TLD without RDAP, answered from DNS:

```json
{"domain": "hcb-zq7-unlikely-48213.io", "tld": "io", "nameservers": [], "statusCodes": [], "status": "likely_available", "method": "dns", "note": "TLD has no public RDAP. DNS says the name does not exist (NXDOMAIN), so it is probably unregistered. Confirm at a registrar.", "durationMs": 12, "checkedAt": "2026-11-10T20:32:36.109Z"}
```

The key-value store also gets a `RUN_SUMMARY` record with totals for available, registered, errors and HTTP 429 responses.

#### Output fields (for AI agents and integrations)

- `status`: `available` (no registry record), `registered` (taken), `likely_available` (no public RDAP; DNS says the name does not exist), `unsupported_tld`, `invalid`, or `error`. The first three are charged; the last three are free.
- `method`: `rdap` (official registry), `dns` (TLDs without RDAP), or `none`.
- `rdapServer`: registry RDAP host that answered, when `method` is `rdap`.
- `registrar` / `registrarIanaId`: the sponsoring registrar (a company), never the registrant.
- `createdAt` / `expiresAt` / `updatedAt`: ISO 8601 UTC dates from the registry, when reported.
- `nameservers`: nameserver hostnames, lower-case.
- `statusCodes`: EPP/RDAP status values (for example `client transfer prohibited`).
- `dnssec`: true if the domain is DNSSEC-signed, when the registry reports it.
- `errorCode`: `TIMEOUT`, `NETWORK_ERROR`, `HTTP_<code>`, or `RETRIES_EXHAUSTED` when there is no answer. Null otherwise.
- `note`: a plain-English explanation for DNS-based or unusual answers.
- `durationMs` / `checkedAt`: time spent on this domain, and when the check finished.

### Use it from the API, MCP or an AI agent

- **Actor ID:** `hillcountrybots/domain-availability-checker`
- **One API call** returns the rows:

```bash
curl -X POST "https://api.apify.com/v2/acts/hillcountrybots~domain-availability-checker/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"names":["brightbakery-atx"],"tlds":["com","io","dev"]}'
```

- **MCP (Claude, Cursor, ChatGPT and other MCP clients):** add `https://mcp.apify.com?tools=hillcountrybots/domain-availability-checker`.
- **For agents:** branch on `status`. Each `available`, `likely_available` or `registered` row costs $0.001. Every other row is free.

### How much does it cost?

**$1.00 per 1,000 checked domains**, which is $0.001 per `domain-checked` event. You pay nothing for:

- invalid input
- unsupported TLDs
- registry errors
- the run summary

The Actor's compute is included, so there's no separate platform usage charge. For example, 50 names × 20 TLDs is 1,000 domains, or $1.00. To cap spend, use `maxResults` or the run's maximum charge setting.

### Limits

- **"Available" means the registry has no record of the name.** Premium, reserved or blocked names can still cost more or be unregistrable. Always confirm at checkout.
- TLDs without public RDAP (.io, .co, .de, .us and some other ccTLDs) are answered from DNS only. That is why those rows say `likely_available`.
- This tool doesn't register domains, show prices, or return registrant contacts.

### FAQ

**Is RDAP the same as WHOIS?** RDAP is the IETF-standard successor to WHOIS, and ICANN requires it from gTLD registries. It returns the same registration facts as structured JSON.

**Does it return the owner's name, email or phone?** No. Only registry and registrar facts are returned, and a unit test enforces that.

**Can I check domain expiration dates in bulk?** Yes. `expiresAt` is filled in for every registered domain the registry reports.

**Will registries block me?** It sends one request at a time per registry with a gap in between, and it backs off on HTTP 429 (respecting `Retry-After`). Our test runs saw zero 429s.

### More tools from Hill Country Bots

- [Bulk PageSpeed Insights Test](https://apify.com/hillcountrybots/bulk-pagespeed-checker): Lighthouse scores and Core Web Vitals for many URLs. $3 per 1,000 audits, failures free.
- [Sitemap URL Extractor](https://apify.com/hillcountrybots/sitemap-url-extractor): Every URL from a site's XML sitemaps (robots.txt, indexes, gzip). $0.50 per 1,000 URLs, failures free.
- [Tech Stack Detector](https://apify.com/hillcountrybots/tech-stack-detector): CMS, ecommerce, analytics, CDN and frameworks for many websites. $0.50 per 1,000 sites, failures free.
- [SEO Audit Tool](https://apify.com/hillcountrybots/seo-audit): 0-100 SEO score per page, top 5 fixes and a client-ready HTML report. $2 per 1,000 pages, failures free.

### Support

Found a wrong answer or need a TLD added? Open an issue on this Actor's **Issues** tab with the run ID and the domain. We reply within 2 business days (US Central time). Built and maintained by **Hill Country Bots**.

# Actor input Schema

## `domains` (type: `array`):

Full domain names to check, one per line (example.com). URLs and www. are cleaned automatically. Use this and/or names + tlds. At least one of domains or names is required for a useful run; this field has no default.

## `names` (type: `array`):

Base names (no dot) to try across every TLD in 'tlds', e.g. 'brightbakery' with com, net, io gives brightbakery.com, brightbakery.net, brightbakery.io. If you set names, also set tlds. This field has no default.

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

Extensions to combine with each name, without the dot (com, net, org, io, dev, app, ai...). Required when using names. This field has no default.

## `dnsFallback` (type: `boolean`):

For TLDs with no public RDAP server (e.g. io, co, de, us): if DNS nameservers exist, the domain is 'registered'; if DNS says the name does not exist, it is 'likely_available'. Turn off to get 'unsupported_tld' instead.

## `maxConcurrency` (type: `integer`):

Domains checked in parallel (1-10). Each registry server still gets one request at a time.

## `minDelayPerServerMs` (type: `integer`):

Milliseconds to wait between requests to the same registry server (politeness; avoids HTTP 429).

## `maxResults` (type: `integer`):

Maximum number of domains checked in this run. Caps spend: at most maxResults x $0.001.

## `requestTimeoutSecs` (type: `integer`):

Seconds to wait for one registry answer before retrying (up to 4 attempts with backoff).

## Actor input object example

```json
{
  "domains": [
    "google.com",
    "wikipedia.org",
    "hillcountrybots-example-name.com"
  ],
  "names": [
    "brightbakery-atx"
  ],
  "tlds": [
    "com",
    "net",
    "org",
    "io",
    "dev",
    "app"
  ],
  "dnsFallback": true,
  "maxConcurrency": 4,
  "minDelayPerServerMs": 300,
  "maxResults": 1000,
  "requestTimeoutSecs": 20
}
```

# Actor output Schema

## `results` (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 = {
    "domains": [
        "google.com",
        "wikipedia.org",
        "hillcountrybots-example-name.com"
    ],
    "names": [
        "brightbakery-atx"
    ],
    "tlds": [
        "com",
        "net",
        "org",
        "io",
        "dev",
        "app"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("hillcountrybots/domain-availability-checker").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 = {
    "domains": [
        "google.com",
        "wikipedia.org",
        "hillcountrybots-example-name.com",
    ],
    "names": ["brightbakery-atx"],
    "tlds": [
        "com",
        "net",
        "org",
        "io",
        "dev",
        "app",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("hillcountrybots/domain-availability-checker").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 '{
  "domains": [
    "google.com",
    "wikipedia.org",
    "hillcountrybots-example-name.com"
  ],
  "names": [
    "brightbakery-atx"
  ],
  "tlds": [
    "com",
    "net",
    "org",
    "io",
    "dev",
    "app"
  ]
}' |
apify call hillcountrybots/domain-availability-checker --silent --output-dataset

```

## MCP server setup

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

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/QamyzhCtpWz4DVRtf/builds/GHEiUFWiwfPu9iVBn/openapi.json
