# Discord Username Checker - Availability, Bulk & Fast (`neverempty/discord-username-checker`) Actor

For handle hunters, brand teams and developers: bulk-check up to 1,000 Discord usernames per run and get available, taken or invalid with Discord's own reason. Measured 2026-09-23: one name in 1.8-3.5 s, 100 names in 64 s. A name Discord did not answer is never reported as available.

- **URL**: https://apify.com/neverempty/discord-username-checker.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Developer tools, Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 username checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Discord Username Checker - Availability, Bulk & Fast

For developers, brand teams and handle hunters: whether each Discord username is available, taken or invalid (with Discord's own reason code and message), plus the time it was checked. Measured on 2026-09-23 with this Actor on Apify: one name in 1.8 - 3.5 s, 100 names in 64 s and 300 names in 281 s, every name answered. Send one name or a list of up to 1,000 in the same run and get one row per name - a name Discord could not answer is never reported as available.

Export as JSON, CSV or Excel.

Unofficial. Public data only. Not affiliated with, endorsed by or connected to Discord Inc.

***

### What it does

You give it usernames. It asks Discord the same question the sign-up page asks ("is this username taken?") and returns one row per name.

```json
{
  "usernames": ["elonmusk", "quiet.harbor.7319", "a", "discord_fan"]
}
```

Rows returned for that input (real answers, 2026-09-23):

```json
[
  { "username": "elonmusk", "taken": true, "available": false, "status": "taken", "reason": null, "reasonMessage": null, "inputUsername": "elonmusk", "checkedAt": "2026-09-23T11:11:04.865Z", "source": "discord" },
  { "username": "quiet.harbor.7319", "taken": false, "available": true, "status": "available", "reason": null, "reasonMessage": null, "inputUsername": "quiet.harbor.7319", "checkedAt": "2026-09-23T11:11:04.360Z", "source": "discord" },
  { "username": "a", "taken": null, "available": false, "status": "invalid", "reason": "BASE_TYPE_BAD_LENGTH", "reasonMessage": "Must be between 2 and 32 in length.", "inputUsername": "a", "checkedAt": "2026-09-23T11:11:05.845Z", "source": "discord" },
  { "username": "discord_fan", "taken": null, "available": false, "status": "invalid", "reason": "USERNAME_INVALID_CONTAINS", "reasonMessage": "Username cannot contain \"discord\"", "inputUsername": "discord_fan", "checkedAt": "2026-09-23T11:11:07.346Z", "source": "discord" }
]
```

The first three columns - `username`, `taken`, `available` - have the same names and meaning as in other Discord username checkers, so a script that reads those three fields from the dataset does not have to rename them. Results are written to the default dataset only (nothing is written to the key-value store). You can also send a single name in a field called `username` instead of a list.

### Why this one

- **One name or many, same Actor.** Send `{"username": "name"}` for one check, or `usernames` with up to 1,000 names. Other checkers take one name per run (you pay the start-up time for every name) or a list only.
- **Invalid names come back with Discord's reason**, not just "not available": too short or too long (`BASE_TYPE_BAD_LENGTH`), characters Discord does not allow (`USERNAME_INVALID_CHARACTERS`), repeated dots (`USERNAME_INVALID_REPEATING_DOTS`), or a word Discord reserves such as "discord", "clyde" or "wumpus" (`USERNAME_INVALID_CONTAINS`). These are the reason codes seen in the measurements for this README; Discord may add others, and whatever it sends is passed through.
- **Every row says when it was checked** (`checkedAt`, UTC). Availability changes the moment someone registers the name.
- **It does not guess.** If Discord rate-limits a name after the retries, blocks the request, or answers with something that cannot be read, that name comes back as a free row with `available: null`, `taken: null` and a note saying why. It is never counted as available.

### Input

| Field | What it does |
|---|---|
| `usernames` | List of usernames, one per line (commas also split). A leading `@` is removed and upper/lower case is ignored - Discord ignores case too (`ElonMusk` and `elonmusk` got the same answer). A space inside a name is kept and sent as typed, and Discord answers `invalid`. The same name is checked and charged once. Up to 1,000 per run. |
| `username` | One username, for tools that send a single name in a field called `username`. Checked first, together with the list. |

If both are empty, the example names `elonmusk` and `quiet.harbor.7319` are checked and every row says so in `inputUsername`.

### Output columns

| Column | Meaning |
|---|---|
| `username` | The name that was sent to Discord (leading `@` removed, lower case). |
| `taken` | `true` if Discord says the name is in use, `false` if it is free, `null` for invalid names and free rows. |
| `available` | `true` only when Discord said the name is free. `false` for taken and invalid names. `null` on free rows (no answer). |
| `status` | `available`, `taken` or `invalid` on charged rows. Free rows: `rate-limited`, `blocked`, `unreadable`, `invalid-input`, `duplicate`, `budget-reached`, `not-checked`. |
| `reason` | Discord's reason code for an invalid name (several are joined with commas). |
| `reasonMessage` | Discord's own sentence for an invalid name. |
| `inputUsername` | The name exactly as you typed it. |
| `checkedAt` | When the answer came back (ISO 8601, UTC). |
| `note` | Free rows only: why there is no answer, and whether anything was charged (it never is). |
| `source` | Always `discord`. |

### Speed and cost of one check

Measured on Apify on 2026-09-23 with the default 128 MB of memory:

| Run | Time of the run | Time from the API call until the result is ready |
|---|---|---|
| One name (5 runs: taken, available, invalid, the example input) | 1.8 - 3.5 s | 3.6 - 5.2 s |
| One name while the datacenter proxy addresses were rate-limited (3 new sessions, answered on residential) | 6.6 s | 8.4 s |
| 38 names | 24.6 s | 26.4 s |
| 100 names | 64.4 s (about 0.64 s per name, 0 rate limits) | 68.4 s |
| 300 names, right after a heavy test had used up most datacenter proxy addresses | 280.7 s (about 0.94 s per name; 42 retries through other proxy sessions, every name answered) | 282.5 s |

A one-name run costs $0.005 - the price of one checked name - and nothing else.

### Pricing

Pay per event: **$5.00 per 1,000 usernames checked** ($0.005 per name), and nothing else - no start fee. You are charged for a name only when Discord answered for it: `available`, `taken` or `invalid`. Rate-limited, blocked and unreadable names, input that is not a name, repeated names and anything the run's maximum total charge did not cover come back as free rows.

If you set a maximum total charge for the run, the Actor checks only as many names as that limit can pay for. The rest are not sent to Discord, and one free row says how many were left.

### Rate limits and how the requests are made

- The Actor sends one request per name to `https://discord.com/api/v9/unique-username/username-attempt-unauthed` - the endpoint Discord's own sign-up page uses to say whether a name is taken. No account, login, token or cookie is used.
- **It does not hammer Discord.** Names are checked one after another with a short pause, never in parallel. When Discord says "wait N seconds" and N is 3 seconds or less, the Actor waits that long on the same connection. When Discord asks for a longer wait, the Actor does not wait it out and does not ask again through that proxy session: the name is retried through a new Apify Proxy session (up to three datacenter sessions, then residential). Apify's pool of addresses is finite, so in a long run an address can come back later through another session. After 5 attempts the name comes back as a free `rate-limited` row. One proxy session is used for at most 15 names in a row, and after a name needed a residential session the next 25 names start on residential.
- **It stops instead of spinning.** If 10 names in a row get no answer (rate limits or blocks on every session tried), or the run is 30 seconds from its timeout, the Actor stops sending and one free `not-checked` row says how many names were left. If a run has no Apify Proxy at all, rate-limited names are not retried and the log says so.
- **Verification pages (CAPTCHA) are never solved or bypassed.** If Discord answers with one, the name comes back as a free `blocked` row.
- Requests go through Apify Proxy. Measured on 2026-09-23 with a separate probe on Apify: from Apify's plain server addresses (no proxy) Discord answered 19 of 25 requests with a rate limit asking for a wait of 8 to 21 minutes; through Apify's datacenter proxy it answered 96 of 96, spaced 1.5 seconds apart. With this Actor, one proxy address was rate-limited after about 20 names in a row, and a 1,000-name run made right after a day of testing used up the datacenter addresses after about 270 names and slowed to 6 - 7 s per name (538 names answered before the 30-minute timeout). That run is why the Actor now moves to residential sooner and stops before the timeout; the 300-name run in the table above came after the change.
- Discord's `robots.txt` disallows `/api/` for crawlers, and this endpoint is under `/api/`. The Actor is not a crawler: it sends only the names you give it, one request each, and follows no links.

### Limits

- Up to 1,000 names per run. Split longer lists across runs. Speed depends on how many proxy addresses Discord is rate-limiting at the moment (0.64 - 0.94 s per name in the runs above, 6 - 7 s per name in the worst run measured); names that do not fit before the run's timeout come back in the free `not-checked` row.
- An `available` answer means "free at `checkedAt`". Anyone can register it a second later.
- Discord only answers for the new unique usernames (no `#1234` discriminator). A name with `#` in it comes back as `invalid`.
- If Discord changes or closes this endpoint, or starts requiring a verification step for it, the Actor stops returning answers (you get free rows saying so) rather than guessing.

### FAQ

**Is a rate-limited name charged?** No. Only names Discord answered for are charged.

**Can I check the same name every few minutes?** Yes - each run is independent and charged per name checked. Keep the interval reasonable; checking faster does not make Discord answer differently.

**Why is `taken` null for an invalid name?** Discord did not say whether it is taken - it said the name cannot be registered at all. `available` is `false` because you cannot claim it.

# Actor input Schema

## `usernames` (type: `array`):

One Discord username per line (or several separated by commas). A space inside a name is kept and sent as typed (Discord answers invalid for it).A leading @ is removed and upper/lower case is ignored, as Discord ignores it. Each name gets one row: available, taken, or invalid with Discord's reason (for example too short, or contains a word Discord does not allow). The same name is checked and charged once. Up to 1,000 names per run, checked one after another with a short pause, never in parallel. If this and the single username field are both empty, the example names elonmusk and quiet.harbor.7319 are checked and every row says so in inputUsername.

## `username` (type: `string`):

One username, for tools that send a single name in a field called username (the same field name other Discord username checkers use). It is checked first, together with anything in the list above.

## Actor input object example

```json
{
  "usernames": [
    "elonmusk",
    "quiet.harbor.7319"
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

One row per username: the name as checked, taken (true/false), available (true/false), status (available, taken or invalid), Discord's reason code and message for invalid names, the name exactly as you typed it, and the time it was checked. Names Discord did not answer for (rate limits, blocks, unreadable answers), input that is not a name, repeated names and anything cut short by the run's charge limit come back as free rows with a note, and available and taken set to null.

# 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 = {
    "usernames": [
        "elonmusk",
        "quiet.harbor.7319"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/discord-username-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 = { "usernames": [
        "elonmusk",
        "quiet.harbor.7319",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/discord-username-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 '{
  "usernames": [
    "elonmusk",
    "quiet.harbor.7319"
  ]
}' |
apify call neverempty/discord-username-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/discord-username-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/S4dpi2oZl9nj2zIFJ/builds/imqWUkEGEiIx753fQ/openapi.json
