An open-source tool from uRadical · v1.1.0

Rust · MIT · macOS, Linux, Windows

Namecheap DNS
from your terminal.

A careful CLI for Namecheap domains and DNS. It checks records before it writes them, snapshots the zone before it changes it, and reads every write back — because “reported success, changed nothing” is the bug that costs you an afternoon.

cargo install namecheap-cli
zsh
$ namecheap dns add example.com A @ 185.199.108.153,185.199.109.153
 Record added: A @ 185.199.108.153 1800
 Record added: A @ 185.199.109.153 1800

$ namecheap dns add example.com A @ 185.199.108.153,185.199.109.153
· 2 record(s) already present, left unchanged

$ namecheap dns add example.com A @ 1.2.3.400
✗ Invalid record
A @ 1.2.3.400 1800
  Problem: "1.2.3.400" is not a valid IPv4 address — each of the
           four parts must be a number from 0 to 255
  Fix:     Use an address such as 185.199.108.153. To point at
           a hostname instead, use CNAME (on a subdomain) or
           ALIAS (at the domain root).

Error: Validation error: 1 record(s) would be invalid — nothing was changed

Careful by default

Namecheap’s API replaces a domain’s entire record set on every write. There is no server-side undo, no partial update, and a malformed record is accepted as readily as a good one. Every feature below exists because of that.

Validated before anything is sent

Records are checked against your input and against the zone the write would produce, so conflicts with what is already there are caught too. Nothing is written if anything would be invalid.

  • A holds IPv4, AAAA holds IPv6 — each suggests the other when swapped
  • CNAME, ALIAS, NS and MX point at a hostname, not an IP or URL
  • CAA flags and tags, SRV’s four fields, URL records with a scheme
  • No CNAME at the root, no CNAME sharing a host, one SPF per host
  • TTL inside the 60–60000 seconds Namecheap accepts

Legal-but-suspect input — a duplicate record, an over-long TXT string — is a warning, not a refusal. Checks are scoped to the hosts you are changing, so an old problem elsewhere never blocks an unrelated update.

Every change is reversible

The zone is snapshotted locally before each write, and dns rollback puts it back — through the same diff-and-confirm flow, so you see what it will do first.

$ namecheap dns rollback example.com --list
╭────────────┬─────────────────────────┬─────────┬──────────────╮
│ ID         │ Taken                   │ Records │ Before       │
├────────────┼─────────────────────────┼─────────┼──────────────┤
 1755600000  2025-08-19 10:40:00 UTC  1        preset apply 
 1755500000  2025-08-18 06:53:20 UTC  2        dns sync     
╰────────────┴─────────────────────────┴─────────┴──────────────╯

Snapshots carry the account’s mail routing mode alongside the records — restoring one without the other would silently unpublish your MX. The 20 most recent per domain are kept.

Your API key is not in a dotfile

A Namecheap API key is full control of the account’s domains. auth login puts it in the OS keychain — Keychain on macOS, Credential Manager on Windows, Secret Service on Linux — so the config file holds no secret and is safe to sync or commit.

Credentials are verified against the API before being saved, so a mistyped key is never stored. Headless machines fall back to a 0600 config file rather than failing, and auth status tells you which source answered.

Writes are read back

A success response is not proof the change landed. After a write the zone is read again and compared, and a mismatch is its own error — not a green tick over a zone that never changed.

The same suspicion runs through the retry policy: transient failures retry three times with backoff, but everything that spends money — domains renew, whoisguard renew, transfer start — is excluded, so a lost response can never become a second charge.

Traps it knows about

Adding MX breaks email forwarding
Namecheap only delivers forwarded mail while routing mode is FWD, and any MX record switches it away. dns add and dns set warn before doing it.
The domain list lies about locks
Namecheap’s listing reports IsLocked="false" for domains that are in fact locked, so domains info reads the real state from a separate call.
Forwarding set on an MX domain goes nowhere
The mailboxes are stored and nothing arrives. dns email list and dns email set say so instead of reporting success.
A gateway page is not an API response
Over the rate limit, Namecheap returns HTML where XML should be. That is reported as what it is, and retried.

Made to be scripted

Every command takes --json, every failure has its own exit code, and the whole zone round-trips through a file.

Assert your DNS hasn’t drifted

dns diff --check exits 8 when the live zone differs from the file, so a pipeline can tell “the zone has drifted” apart from “the command failed”.

namecheap dns export example.com > expected.json

# ...later, in CI:
namecheap dns diff example.com expected.json --check

The JSON form carries forwarded mailboxes as well as records, so --check catches drift in both.

Exit codes

CodeMeaning
0Success
1General error
2Authentication error
3Domain not found
4Record not found
5Validation error
6Network error
7Verification failed
8dns diff --check found differences

Edit a zone like a file

dns edit opens the whole zone in $EDITOR as plain text. Change a line to change a record, delete a line to remove it. Saving diffs it against what is live and confirms before writing.

# host    ttl   type    value

@       1800  A       185.199.108.153
@       1800  A       185.199.109.153
www     3600  CNAME   user.github.io.
@       1800  MX      10 mx1.privateemail.com
@       1800  TXT     v=spf1 include:_spf.google.com ~all
_dmarc  1800  TXT     v=DMARC1; p=none

The value runs to the end of the line, so TXT needs no quoting and semicolons survive — which matters for DMARC and DKIM. Unreadable input reopens the editor with the line number rather than losing your work.

Across many domains at once

preset apply and dns clone take a list of domains, or read one from a file. Each is diffed and confirmed separately; if one fails the rest still run.

namecheap preset apply github-pages a.com b.com c.com

namecheap dns clone template.com --domains-from domains.txt

# make the target an exact mirror
namecheap dns clone template.com new.com --delete

clone copies records verbatim and flags any value naming the source domain — a redirect target, a mail host, a verification token — rather than silently rewriting it.

What it manages

DNS records

List, add, set, remove, export, import, sync, clone and diff. Multi-value writes for A, AAAA, MX and NS land in a single call.

namecheap dns set example.com A @ 5.6.7.8

Domains

List with expiry sorting, per-domain info, availability checks, registrar lock, renewal, and the price this account pays for a TLD.

namecheap domains list --expiring 30

Nameservers & glue

Point a domain at custom nameservers or reset to Namecheap’s, plus child nameserver records for domains that run their own.

namecheap ns set example.com ns1.cloudflare.com ns2.cloudflare.com

Email forwarding

Forwarding lives outside the zone and never shows in dns list. These commands say which routing mode you are in rather than dropping mail.

namecheap dns email set example.com hello you@gmail.com

Privacy (WhoisGuard)

Turn privacy on or off across one domain, several, or all of them. Subscriptions are looked up by domain, so you never handle ids.

namecheap whoisguard on --all --email you@example.com

Transfers

Start an inbound transfer with an auth code, list every transfer on the account, check where one has got to, and nudge a stalled one.

namecheap transfer start example.com --epp-code ABC123

URL redirects

Plain, permanent (301) and masked frame redirects, managed as their own thing rather than as raw records.

namecheap redirect add example.com old https://new.example.com --permanent

Propagation checks

Resolve what you just wrote and confirm it is actually being served, optionally waiting for it to appear.

namecheap verify example.com --wait --timeout 300

Shell completions

Generated for bash, zsh, fish and PowerShell.

namecheap completions zsh > ~/.zfunc/_namecheap

Every command, every flag: read the reference — generated from the binary's own --help, so it matches the version you installed.

Presets

Common setups applied as a named bundle, diffed and confirmed like any other change. Applying an email preset also switches the domain’s routing mode and clears a previous provider’s MX and stale SPF, because leaving either would break delivery.

  • github-pages
  • google-workspace
  • fastmail
  • protonmail
  • microsoft-365
  • cloudflare
  • netlify
  • vercel
  • sendgrid
namecheap preset apply github-pages example.com -V username=myuser

Install

Requires a Rust toolchain (1.98 or newer).

cargo install namecheap-cli
git clone https://github.com/uRadical/namecheap-cli
cd namecheap-cli
cargo install --path .

Archives with SHA-256 checksums are published for Linux (x86-64, ARM64, musl), macOS (Intel and Apple Silicon) and Windows on the releases page.

tar xzf namecheap-aarch64-apple-darwin.tar.gz
sudo mv namecheap /usr/local/bin/

Then, three steps

  1. Enable API access on your Namecheap account. Profile → Tools → Namecheap API Access, then add your IP to the whitelist and copy the key.
  2. Log in. The key is checked against the API before it is stored, and goes to your OS keychain.
    namecheap auth login
  3. Look around. Nothing here changes anything.
    namecheap domains list
    namecheap dns list example.com

Prefer to keep state out of it entirely? Set NAMECHEAP_API_USER and NAMECHEAP_API_KEY in the environment and skip auth login — useful in CI. A sandbox account works too, with NAMECHEAP_SANDBOX=true.