EPP Deep Dive

The Extensible Provisioning Protocol — how registrars communicate with registries to create, manage, transfer, and delete domain names.

Every time you register a domain, renew it, transfer it, or update its nameservers, a protocol called EPP carries that action from your registrar to the registry. EPP is the invisible plumbing of the domain registration system — unseen by end users but essential to every operation in the domain ecosystem.

Understanding EPP gives you a view behind the curtain: what actually happens when you click “Register,” how status codes control your domain’s behavior, and why certain operations take the time they do.

What is EPP?

The Extensible Provisioning Protocol is an XML-based client-server protocol designed for provisioning and managing objects stored in a shared central repository — in practice, domain names, contacts, and hosts (nameservers) in a registry database.

EPP was developed by the IETF and is defined across several RFCs:

RFC Title Purpose
RFC 5730 EPP Core protocol framework
RFC 5731 EPP Domain Name Mapping Domain-specific commands
RFC 5732 EPP Host Mapping Nameserver object commands
RFC 5733 EPP Contact Mapping Contact object commands
RFC 5734 EPP Transport over TCP Network transport specification

EPP replaced earlier, registry-specific protocols (like the RRP — Registry Registrar Protocol used by Verisign) with a standardized system that works across all ICANN-accredited registries.

Architecture

EPP uses a client-server model over persistent TCP connections with TLS encryption:

┌──────────────┐         TLS/TCP          ┌──────────────┐
│   Registrar  │◄───────────────────────►│   Registry    │
│  (EPP Client)│    Port 700 (standard)   │  (EPP Server) │
└──────────────┘                          └──────────────┘

Key architectural features:

  • Persistent connections: Unlike HTTP (traditionally), EPP maintains long-lived TCP connections. A registrar opens a session, authenticates, and sends commands over that session.
  • Synchronous request-response: Each command gets exactly one response. No streaming, no callbacks.
  • Stateful sessions: After login, the server tracks the client’s authentication state.
  • XML-based: All messages are well-formed XML documents with strict schema validation.

The Session Lifecycle

An EPP session follows a fixed pattern:

1. Greeting

When a client connects, the server immediately sends a <greeting> containing:

  • Server name and version
  • Supported protocol versions
  • Supported languages
  • Supported object types and extensions
  • Data collection policy
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
  <greeting>
    <svID>Example Registry EPP Server</svID>
    <svDate>2024-01-15T00:00:00Z</svDate>
    <svcMenu>
      <version>1.0</version>
      <lang>en</lang>
      <objURI>urn:ietf:params:xml:ns:domain-1.0</objURI>
      <objURI>urn:ietf:params:xml:ns:contact-1.0</objURI>
      <objURI>urn:ietf:params:xml:ns:host-1.0</objURI>
    </svcMenu>
  </greeting>
</epp>

2. Login

The client authenticates with credentials:

<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
  <command>
    <login>
      <clID>RegistrarX</clID>
      <pw>secretPassword123</pw>
      <options>
        <version>1.0</version>
        <lang>en</lang>
      </options>
      <svcs>
        <objURI>urn:ietf:params:xml:ns:domain-1.0</objURI>
        <objURI>urn:ietf:params:xml:ns:contact-1.0</objURI>
      </svcs>
    </login>
  </command>
</epp>

3. Commands

After login, the client sends commands and receives responses (the bulk of the session).

4. Logout

The client terminates the session gracefully:

<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
  <command>
    <logout/>
  </command>
</epp>

EPP Commands

EPP defines a set of standard commands for managing domain objects:

Query Commands

<check> — Test whether a domain is available for registration:

<domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
  <domain:name>example.com</domain:name>
  <domain:name>example.net</domain:name>
</domain:check>

Response indicates availability:

<domain:chkData>
  <domain:cd>
    <domain:name avail="0">example.com</domain:name>
    <domain:reason>In use</domain:reason>
  </domain:cd>
  <domain:cd>
    <domain:name avail="1">example.net</domain:name>
  </domain:cd>
</domain:chkData>

<info> — Retrieve detailed information about a domain:

<domain:info xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
  <domain:name hosts="all">example.com</domain:name>
  <domain:authInfo>
    <domain:pw>authSecret123</domain:pw>
  </domain:authInfo>
</domain:info>

The response includes registrant, contacts, nameservers, status codes, dates, and auth info (if the querier is the sponsoring registrar).

Transform Commands

<create> — Register a new domain:

<domain:create xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
  <domain:name>newdomain.com</domain:name>
  <domain:period unit="y">2</domain:period>
  <domain:ns>
    <domain:hostObj>ns1.example.com</domain:hostObj>
    <domain:hostObj>ns2.example.com</domain:hostObj>
  </domain:ns>
  <domain:registrant>contact-123</domain:registrant>
  <domain:contact type="admin">contact-456</domain:contact>
  <domain:contact type="tech">contact-789</domain:contact>
  <domain:authInfo>
    <domain:pw>newAuthCode!@#</domain:pw>
  </domain:authInfo>
</domain:create>

<update> — Modify domain properties (nameservers, contacts, status):

<domain:update xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
  <domain:name>example.com</domain:name>
  <domain:add>
    <domain:ns>
      <domain:hostObj>ns3.example.com</domain:hostObj>
    </domain:ns>
    <domain:status s="clientTransferProhibited"/>
  </domain:add>
  <domain:rem>
    <domain:ns>
      <domain:hostObj>ns1.old-provider.com</domain:hostObj>
    </domain:ns>
  </domain:rem>
</domain:update>

<delete> — Remove a domain from the registry:

<domain:delete xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
  <domain:name>example.com</domain:name>
</domain:delete>

<renew> — Extend the domain’s registration period:

<domain:renew xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
  <domain:name>example.com</domain:name>
  <domain:curExpDate>2025-04-03</domain:curExpDate>
  <domain:period unit="y">1</domain:period>
</domain:renew>

The curExpDate is a safety check — it must match the registry’s current expiry date, preventing accidental double-renewals.

<transfer> — Request, approve, reject, or cancel a domain transfer:

<domain:transfer op="request"
  xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
  <domain:name>example.com</domain:name>
  <domain:authInfo>
    <domain:pw>authFromCurrentOwner</domain:pw>
  </domain:authInfo>
</domain:transfer>

The op attribute specifies the operation: request, approve, reject, cancel, or query. For the full transfer workflow from a registrant’s perspective, see Domain Transfers.

EPP Status Codes

Status codes are one of EPP’s most important features. They control what operations are allowed on a domain and indicate its current lifecycle state. Status codes come in two varieties:

Client Status Codes

Set by the registrar (the “client” in EPP terminology):

Code Meaning
clientDeleteProhibited Registrar prevents deletion
clientHold Registrar suspends DNS resolution
clientRenewProhibited Registrar prevents renewal
clientTransferProhibited Registrar prevents transfer (the “registrar lock”)
clientUpdateProhibited Registrar prevents modifications

Server Status Codes

Set by the registry (the “server”):

Code Meaning
serverDeleteProhibited Registry prevents deletion
serverHold Registry suspends DNS resolution
serverRenewProhibited Registry prevents renewal
serverTransferProhibited Registry prevents transfer
serverUpdateProhibited Registry prevents modifications

Lifecycle Status Codes

Code Meaning
ok Normal, active — no pending operations or prohibitions
addPeriod Within the Add Grace Period after registration
autoRenewPeriod Within the Auto-Renew Grace Period
renewPeriod Within the Renew Grace Period
transferPeriod Within the Transfer Grace Period
redemptionPeriod Domain deleted, in redemption (recoverable at high cost)
pendingCreate Registration is pending
pendingDelete Domain queued for deletion (5-day countdown)
pendingRenew Renewal is pending
pendingRestore Restoration from redemption is pending
pendingTransfer Transfer is in progress
pendingUpdate Update is pending
inactive Domain has no nameservers delegated

Reading Status Codes

A typical active domain might show:

Domain Status: clientTransferProhibited
Domain Status: clientDeleteProhibited

This means the registrar has locked the domain against transfers and deletions — standard security practice. The absence of ok is normal when other status codes are present; ok only appears when no other statuses are set.

A domain in trouble might show:

Domain Status: serverHold
Domain Status: clientTransferProhibited

serverHold means the registry has suspended DNS resolution — the domain won’t resolve. This happens for abuse (phishing, malware), legal orders, or UDRP decisions.

EPP Extensions

EPP’s “extensible” nature allows registries to add custom functionality beyond the base protocol. Common extensions include:

DNSSEC Extension (RFC 5910)

Allows registrars to manage DNSSEC delegation signer (DS) records:

<secDNS:create xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1">
  <secDNS:dsData>
    <secDNS:keyTag>12345</secDNS:keyTag>
    <secDNS:alg>13</secDNS:alg>
    <secDNS:digestType>2</secDNS:digestType>
    <secDNS:digest>49FD46E6C4B45C55D4AC...</secDNS:digest>
  </secDNS:dsData>
</secDNS:create>

Registry Grace Period Extension (RFC 3915)

Provides grace period status information so registrars can manage AGP deletions and redemption restorations.

Launch Phase Extension (RFC 8334)

Used during new gTLD launches to handle sunrise periods (trademark holders register first), landrush, and claims notifications.

Fee Extension

Various registries implement fee extensions to communicate dynamic or premium pricing for certain domain names. Before registering insurance.com, the registrar can query the fee extension to discover it costs $10,000/year instead of $10.

EPP in Practice

Connection Pools

Registrars managing millions of domains don’t open a new connection for each operation. They maintain connection pools — persistent EPP sessions to each registry, ready to process commands instantly. A large registrar might maintain dozens of concurrent connections to Verisign’s .com EPP servers.

Rate Limiting

Registries impose rate limits on EPP commands. Verisign, for example, limits the number of <check> commands per connection per second. This prevents abuse (like checking every possible 3-letter .com domain in rapid succession) while ensuring fair access for all registrars.

Testing Environments

Every registry operates an OT&E (Operational Test and Evaluation) environment — a sandbox where registrars test their EPP integration before going live. New registrars must successfully complete OT&E testing to become operational.

Key Takeaways

  • EPP (RFC 5730-5734) is the XML protocol connecting registrars to registries for all domain operations
  • Six core commands: check, info, create, update, delete, renew, plus transfer with multiple operations
  • Status codes control what’s allowed — client* codes are set by registrars, server* by registries
  • clientTransferProhibited is the standard “registrar lock” — enable it on every important domain
  • serverHold stops DNS resolution — a registry enforcement action
  • Extensions add DNSSEC, grace periods, launch phases, and premium pricing capabilities
  • Persistent connections and connection pools make EPP performant at scale

This completes Part 3 — The Domain Ecosystem. You now understand how domain names are structured, how the registration industry operates, and the protocols and processes that make it all work. In Part 4, we’ll explore the security layer: DNSSEC, DNS-over-HTTPS, DNS hijacking, and the ongoing battle to keep the namespace trustworthy.