Domain Intelligence

EPP Status Codes: Complete Reference for Developers and Domain Owners

Every domain carries at least one EPP status code. Most people ignore them — until a transfer fails or a site vanishes from DNS. Here is the complete reference, plus a developer guide for reading codes programmatically.

April 28, 202611 min readDomain Intelligence · WHOIS · EPP · Reference

Introduction

Every domain registration record contains at least one EPP status code. They appear in every WHOIS response, they govern what operations are permitted on the domain, and they change at every significant lifecycle event — registration, transfer, renewal, expiry. Most domain owners never look at them. Most developers treat them as noise in the WHOIS output.

That changes the first time a transfer fails because of a code nobody noticed, or the first time a domain stops resolving because a registrar applied a hold. At that point, understanding what each code means — who set it, why, and what action it requires — becomes urgent.

This article is the complete reference: every EPP status code defined, organized by who sets it and what it signals, with a developer section covering how to parse the status  and statusAnalysis  fields from the WhoisJSON API to build automated alerts. If you are new to WHOIS data, the WHOIS API JSON response field reference  is the recommended starting point.

What Are EPP Status Codes?

EPP status codes are standardized indicators that describe the current state of a domain name and the operations permitted on it. They are defined by the IETF in RFC 5731  and are transmitted between registrars and registries using the Extensible Provisioning Protocol (EPP). The same codes surface in WHOIS and RDAP responses, making them the canonical source of truth for a domain's operational state.

Three properties are worth understanding before looking at individual codes:

  • Client codes vs server codes.  Codes prefixed client  are set by the registrar (the company you bought the domain from). Codes prefixed server  are set by the registry (the organization that operates the TLD, such as Verisign for .com). Server codes take absolute priority over client codes and can only be removed by the registry itself — your registrar cannot unilaterally lift a server restriction.
  • Multiple codes.  A domain can carry several codes simultaneously. The full set is returned as an array in the WHOIS/RDAP response. The most common real-world combination is okclientTransferProhibited, and serverTransferProhibited.
  • Authoritative reference.  The ICANN EPP status codes page  is the canonical listing. This article adds developer context and programmatic examples that are absent from the ICANN reference.

Client Status Codes

Client codes are set and managed by the registrar. They can be added or removed at the registrant's request (subject to registrar policy) and do not require registry involvement to change.

ok

The baseline status. It means the domain has no restrictions of any kind — no locks, no holds, no pending operations. It appears alone; if displayed alongside any other code in a real WHOIS response, that is a data quality issue, not a valid combination.

A domain with only ok  has no transfer lock and no update lock.   It can be transferred to another registrar or have its nameservers changed without any additional verification step. This is a security risk for domains that are not actively being managed.

clientTransferProhibited

The most common EPP code. It blocks outgoing transfers to another registrar. Registrars apply it by default at registration to protect against unauthorized transfers. Removing it requires logging into your registrar account (or contacting support) and explicitly unlocking the domain — a step that should only be done immediately before initiating a transfer, then reversed as soon as the transfer completes.

The presence of clientTransferProhibited  does not affect DNS resolution, email delivery, or any other operational aspect of the domain. It exclusively governs registrar-to-registrar transfer.

clientUpdateProhibited

Blocks all modifications to the domain record — nameserver changes, contact data updates, DNSSEC configuration. Commonly paired with  code clientTransferProhibited |  to create a "domain lock" that prevents both hijacking via nameserver modification and unauthorized transfer. Critical production domains — those running core business infrastructure — should carry both codes permanently.

clientDeleteProhibited

Blocks explicit deletion of the domain. Note that it does not prevent natural expiry  — if the domain is not renewed before the expiry date, it will still enter the grace period and eventually drop regardless of this code. It protects against accidental or malicious deletion commands sent to the registry.

clientRenewProhibited

Blocks explicit renewal commands. Rare in normal operation — typically indicates a registrar-level dispute, a court order, or a compliance hold. If you see this code on a domain you own and did not request it, contact your registrar immediately.

clientHold

Critical.  This code removes the domain from the DNS zone file. The domain will not resolve — the website returns an NXDOMAIN, email bounces, and any service depending on this domain stops working.

Common causes: unpaid registrar invoice, failed WHOIS verification (ICANN requires registrars to validate contact data), a dispute triggered by the registrar's fraud or abuse team, or a court-ordered suspension. Resolution always requires contacting the registrar directly — no registry intervention is involved.

Server Status Codes

Server codes are set by the registry. They cannot be modified by the registrar or the registrant without explicit registry approval. In practice, this means contacting the registry directly or going through a formal process (legal, compliance, or a paid "registry lock" service).

serverTransferProhibited

The registry-level equivalent of clientTransferProhibited. Applied automatically by ICANN policy for 60 days after a new registration or an incoming transfer — this is the Anti-Abuse Transfer Policy lock, designed to prevent domain hijacking immediately after a registration event. After 60 days it is removed automatically, unless the registrar has enrolled the domain in a paid "registry lock" service (common for high-value domains).

Key distinction: unlike the client version, removing serverTransferProhibited  requires the registry's involvement. A registrar cannot lift it unilaterally.

serverUpdateProhibited

Blocks all record modifications at the registry level. Used as part of a full "registry lock" (typically a paid service for premium or critical domains), or applied by the registry following a legal dispute such as a UDRP proceeding or a court injunction. A domain under UDRP typically carries both this code and serverTransferProhibited for the duration of the case.

serverDeleteProhibited

Blocks deletion at the registry level. Part of a full registry lock. Also applied automatically during active UDRP proceedings to prevent the losing party from deleting the domain before a decision is enforced.

serverRenewProhibited

Rare. Blocks renewal at the registry level. Signals an active regulatory or legal proceeding. If observed on a domain you own, escalate to your registrar immediately — it may indicate a compliance hold that could result in domain suspension if not addressed.

serverHold

The registry-level equivalent of clientHold. Removes the domain from the DNS zone file. Applied by the registry for legal reasons (court order, UDRP outcome), abuse (confirmed phishing or malware hosting), or financial (outstanding registry fees). Requires registry intervention to lift — the registrar alone cannot resolve it.

Lifecycle (Pending) Status Codes

Pending codes represent in-progress operations. They are transient — they resolve automatically once the operation completes or its timeout expires. You should not take action based on a pending code alone; wait for it to clear and re-query the domain.

pendingCreate

The domain registration has been submitted and is being processed by the registry. Typically clears within minutes to a few hours. No action required.

pendingTransfer

An outgoing transfer to another registrar is in progress. The losing registrar has up to 5 days to approve or reject; if no action is taken, the transfer completes automatically on day 5. Either party can accelerate the process — the gaining registrar by resubmitting, the losing registrar by explicitly approving.

pendingUpdate

A record modification (nameserver change, contact update) has been submitted and is propagating. Clears within a few hours.

pendingRenew

A renewal has been submitted and is being processed. Clears within a few hours.

pendingDelete

Critical — 5-day window before public release.  The domain has passed through the redemption period and will be released for public registration in 5 days. This is not recoverable through normal channels — the restoration window has already closed. If this domain belongs to you, contact your registrar and registry immediately; options are extremely limited at this stage.

Do not confuse pendingDelete  with redemptionPeriodredemptionPeriod  is earlier in the lifecycle and still recoverable (at a cost). By the time a domain reaches pendingDelete, normal restoration is no longer possible.

Registry Grace Period (RGP) Codes

Defined by RFC 5731, RGP codes manage the post-deletion recovery window and the grace periods following standard registration events. For a detailed breakdown of the full expiry lifecycle, see what happens when a domain expires.

redemptionPeriod

Recovery is still possible — but expensive and time-limited.  The registrant has up to 30 days from the start of the redemption period to submit a restore request through their registrar. Recovery costs typically range from $80 to $200 on top of the renewal fee.

The domain is effectively suspended — DNS is removed and the domain does not resolve. After the 30-day redemption window closes, the domain moves to pendingDelete and is queued for public release 5 days later.

pendingRestore

A restore request from redemptionPeriod has been submitted. The registrar has up to 7 days to submit a restore report to the registry. If the report is not submitted within that window, the domain reverts to redemptionPeriod and the restoration fails.

autoRenewPeriod

A 45-day grace period applied after an automatic renewal. If the domain is deleted during this window, the registry refunds the renewal fee to the registrar. Used to handle billing failures and registration errors.

renewPeriod

A 5-day grace period applied after a manual renewal command. Same refund mechanism as autoRenewPeriod, but shorter.

transferPeriod

A 5-day grace period applied after an incoming transfer completes. If the domain is deleted during this window, the registry refunds the transfer fee.

Common Combinations and What They Mean

A WHOIS query rarely returns a single code. The table below covers the combinations you will encounter most often in production data.

Status combinationWhat it meansRisk level
ok onlyNo locks active. Domain is fully transferable and updatable.MEDIUM
ok + clientTransferProhibitedStandard configuration for a registered domain. Transfer locked, DNS operations unrestricted.OK
ok + clientTransferProhibited + clientUpdateProhibited + clientDeleteProhibitedFull client-side domain lock. Recommended for all critical domains.SECURE
serverTransferProhibited (only server code)Recent registration or transfer (<60 days), or registry lock on a premium domain.OK
All four server* codes togetherFull registry lock. Maximum protection for ultra-critical domains.SECURE
clientHold or serverHoldDomain removed from DNS. Site and email are down.CRITICAL
redemptionPeriodDomain expired and deleted. Recovery possible within 30 days at extra cost.CRITICAL
pendingDelete5 days before public release. Recovery extremely unlikely.CRITICAL

Reading EPP Status Codes Programmatically

The WhoisJSON API returns EPP codes in two complementary fields. The status  array contains the raw code strings exactly as returned by the registry. The statusAnalysis  object — present only when source  is rdap  — pre-computes the boolean flags you would otherwise derive yourself, eliminating the need for string matching in application code. See the WHOIS API JSON field reference  for the full schema.

whois_response.json (abbreviated)JSON
{
  "name": "example.com",
  "registered": true,
  "source": "rdap",
  "status": [
    "clientTransferProhibited",
    "clientUpdateProhibited",
    "serverTransferProhibited"
  ],
  "statusAnalysis": {
    "clientTransferProhibited": true,
    "clientUpdateProhibited": true,
    "serverTransferProhibited": true,
    "clientDeleteProhibited": false,
    "serverDeleteProhibited": false,
    "isActive": true,
    "isOnHold": false,
    "isPendingDelete": false,
    "isPendingTransfer": false,
    "isRedemptionPeriod": false
  }
}

Python — alert on critical codes

The following function checks the statusAnalysis  object for the three codes that require immediate action and sends an alert for each one found. For the full async query pattern, see the Python WHOIS API guide.

check_status.pyPython
import requests

API_KEY = "YOUR_API_KEY"
BASE    = "https://whoisjson.com/api/v1"


def check_epp_status(domain: str) -> dict:
    resp = requests.get(
        f"{BASE}/whois",
        params={"domain": domain},
        headers={"Authorization": f"TOKEN={API_KEY}"},
        timeout=10,
    )
    resp.raise_for_status()
    data = resp.json()

    analysis = data.get("statusAnalysis") or {}
    alerts   = []

    if analysis.get("isOnHold"):
        alerts.append({
            "code":    "clientHold or serverHold",
            "message": "Domain is on hold — DNS removed, site and email are down.",
            "action":  "Contact registrar immediately.",
        })

    if analysis.get("isPendingDelete"):
        alerts.append({
            "code":    "pendingDelete",
            "message": "Domain will be released in ~5 days.",
            "action":  "Contact registrar and registry — options are extremely limited.",
        })

    if analysis.get("isRedemptionPeriod"):
        alerts.append({
            "code":    "redemptionPeriod",
            "message": "Domain expired. Recovery window: 30 days.",
            "action":  "Submit restore request via registrar before window closes.",
        })

    return {
        "domain":       domain,
        "status_codes": data.get("status", []),
        "is_active":    analysis.get("isActive", False),
        "transfer_ok":  not (
            analysis.get("clientTransferProhibited") or
            analysis.get("serverTransferProhibited")
        ),
        "alerts":       alerts,
    }


result = check_epp_status("example.com")
if result["alerts"]:
    for alert in result["alerts"]:
        print(f"[ALERT] {alert['code']}: {alert['message']}")
        print(f"        Action: {alert['action']}")
else:
    print(f"OK — {result['domain']} is active. Transfer allowed: {result['transfer_ok']}")

Node.js — check if a domain is transferable

The clientTransferProhibited  and serverTransferProhibited  flags together determine whether an outgoing transfer can be initiated. For more Node.js patterns, see the Node.js WHOIS API guide.

checkTransferable.mjsJavaScript
const API_KEY = "YOUR_API_KEY";
const BASE    = "https://whoisjson.com/api/v1";

async function isTransferable(domain) {
    const resp = await fetch(`${BASE}/whois?domain=${domain}`, {
        headers: { Authorization: `TOKEN=${API_KEY}` },
        signal: AbortSignal.timeout(10_000),
    });
    if (!resp.ok) throw new Error(`HTTP ${resp.status}`);

    const data = await resp.json();
    const sa   = data.statusAnalysis ?? {};

    return {
        domain,
        transferable: !sa.clientTransferProhibited && !sa.serverTransferProhibited,
        locked:       sa.clientTransferProhibited || sa.clientUpdateProhibited,
        onHold:       sa.isOnHold ?? false,
        pendingDelete: sa.isPendingDelete ?? false,
        statusCodes:  data.status ?? [],
    };
}

const result = await isTransferable("example.com");
console.log(result);
// { domain: 'example.com', transferable: false, locked: true, onHold: false, ... }

EPP Status Codes for Security Monitoring

Beyond operational checks, EPP codes are useful security signals. Three patterns are worth building automated detection for.

  • No clientTransferProhibited  on an owned domain.   A domain in your inventory that only carries ok  has no transfer lock. It can be stolen via a social-engineering attack on your registrar's support team without any additional verification. Flag it in your domain inventory sweep and lock it immediately. See domain monitoring for security teams  for how to automate this check across a portfolio.
  • Sudden appearance of serverHold  or clientHold  on a monitored domain.   A hold that was not preceded by a known operational event (expired invoice, WHOIS verification request) is a high-severity signal — it may indicate the registrar has received a legal or abuse notice against your domain. The isOnHold  boolean in statusAnalysis  is the cleanest field to watch.
  •  pendingDelete  on a domain that resembles your brand.   A lookalike domain entering pendingDelete  will be available for re-registration in 5 days. This is the optimal window for defensive registration — query the availability endpoint on day 5 and register immediately if it drops. This pattern connects directly with the phishing domain detection workflow.

Conclusion

Five codes account for the vast majority of operationally relevant situations:

  • clientTransferProhibited  — should be present on every domain you own. If absent, lock it now.
  • clientHold  / serverHold  — domain is down. Requires immediate action.
  • redemptionPeriod  — domain expired. Recovery possible but costly. 30-day window.
  • pendingDelete  — 5 days before public release. Escalate immediately.
  • serverTransferProhibited  (without client equivalent) — normal for the first 60 days or on registry-locked domains.

The WhoisJSON API surfaces all of these via the status array and the pre-computed statusAnalysis object, making it straightforward to build automated portfolio monitoring without manual WHOIS parsing.

Read EPP Codes via API

1,000 free WHOIS lookups/month. statusAnalysis included. No credit card.

Get Your Free API Key

Full API Reference

All endpoints, response schemas, and authentication docs.

View Documentation
Domain Intelligence

Read EPP Status Codes Programmatically

The WhoisJSON API returns the full status array and pre-computed statusAnalysis flags — isOnHold, isPendingDelete, isRedemptionPeriod — in every WHOIS response. 1,000 free requests per month.

statusAnalysis pre-computed flagsRDAP + WHOIS unified response1,000 free requests/monthNo credit card required

Get Started Free

No credit card. All endpoints unlocked.

Get Free API Key

Read the Docs

Full response schema, authentication, and code examples.

Documentation