Quick Answer
EPP (Extensible Provisioning Protocol) is the standardized protocol that enables domain registrars to communicate with domain registries to register, transfer, renew, and manage domain names. Operating over TCP port 700 with TLS encryption, EPP uses XML-formatted commands and responses to handle all domain lifecycle operations. When you register a domain through GoDaddy, Namecheap, or any registrar, they're sending EPP commands like domain:create, domain:renew, or domain:transfer to the registry (Verisign for .com, PIR for .org, etc.). Understanding EPP helps you troubleshoot domain issues, comprehend EPP status codes, interpret transfer authorization codes, and grasp how the domain registration ecosystem functions behind the scenes.
Table of Contents
- What is EPP?
- The History of EPP
- How EPP Works: The Architecture
- EPP Commands Overview
- EPP Command Details
- EPP Response Structure
- EPP Status Codes
- EPP Authorization Codes (Auth Codes)
- XML Structure of EPP Messages
- EPP Extensions
- EPP and Domain Transfers
- EPP Security Features
- How EPP Helps Troubleshoot Domain Issues
- EPP vs Other Protocols
- Frequently Asked Questions
- Key Takeaways
- Next Steps
What is EPP?
EPP stands for Extensible Provisioning Protocol. It's the standardized protocol that registrars use to communicate with registries to manage domain names, IP addresses, and other internet resources.
The Simple Explanation
Think of domain registration like a retail system:
- Registries (Verisign, PIR, Afilias) are the wholesalers who control top-level domains
- Registrars (GoDaddy, Namecheap, Cloudflare) are the retailers who sell to customers
- EPP is the ordering system that lets retailers place orders with wholesalers
When you register example.com at Namecheap:
- You fill out a form on Namecheap's website
- Namecheap's system creates an EPP
domain:createcommand - Namecheap sends this XML command to Verisign (the .com registry)
- Verisign processes the command and reserves the domain
- Verisign sends back an EPP response confirming registration
- Namecheap shows you a success message
All of this happens in seconds, entirely through EPP.
What EPP Manages
EPP handles the complete domain lifecycle:
Domain operations:
- Create: Register a new domain
- Check: Verify domain availability
- Info: Query domain details
- Update: Modify domain information (contacts, nameservers, status)
- Renew: Extend domain registration period
- Transfer: Move domain between registrars
- Delete: Remove domain from registry
Other resources:
- Contacts: Register and manage contact objects
- Hosts: Register nameservers (host objects)
- Authorization codes: Generate and verify transfer codes
Why EPP Matters to You
Even if you never interact with EPP directly, understanding it helps you:
- Troubleshoot issues: EPP status codes explain why transfers fail or why domains are locked
- Understand timing: EPP defines transfer timelines and renewal grace periods
- Security awareness: EPP auth codes protect your domains from unauthorized transfers
- Make informed decisions: Knowing EPP helps you choose registrars and interpret domain data
The History of EPP
Before EPP: The Wild West Era
1990s: Email-Based Registration
- Registrars emailed plain-text domain requests to registries
- Manual processing took hours or days
- No standardization—each registry had different formats
- High error rates due to manual data entry
Late 1990s: Proprietary Protocols
- Large registrars developed custom integration systems
- RRP (Registry Registrar Protocol) emerged as early standard
- Still inconsistent across different registries
- Security was minimal—passwords in plain text
EPP Development Timeline
1998: Development Begins The Internet Engineering Task Force (IETF) recognized the need for a standardized, secure protocol for domain provisioning. Work on EPP began under the PROVREG working group.
2000-2004: RFC Series Published The IETF published the original EPP specifications:
- RFC 3730: EPP Protocol specification (base protocol)
- RFC 3731: EPP Domain name mapping
- RFC 3732: EPP Host mapping
- RFC 3733: EPP Contact mapping
2004-2007: Industry Adoption
- Verisign (.com, .net) transitioned to EPP
- ICANN required EPP for all new gTLD registries
- Most registrars upgraded systems to support EPP
- Became the de facto standard for domain provisioning
2009: EPP 1.0 Standards Finalized Updated RFC series replaced the originals:
- RFC 5730: EPP Protocol (superseded RFC 3730)
- RFC 5731: Domain name mapping (superseded RFC 3731)
- RFC 5732: Host mapping (superseded RFC 3732)
- RFC 5733: Contact mapping (superseded RFC 3733)
2010s: Universal Adoption
- All major registries implemented EPP
- DNSSEC extensions added
- IDN (Internationalized Domain Name) support
- Registry-specific extensions proliferated
2020s: Modern EPP
- Over 1,500 TLDs use EPP
- Processing billions of domain transactions annually
- Continuing evolution through extensions
- Foundation for new RDAP protocol (Registration Data Access Protocol)
How EPP Works: The Architecture
The Three Layers
EPP operates in a client-server model with three main components:
1. EPP Client (Registrar Systems)
What it does:
- Translates registrar's internal systems into EPP commands
- Manages EPP sessions with multiple registries
- Handles authentication and connection management
- Processes EPP responses and updates registrar database
Example registrars: GoDaddy, Namecheap, Cloudflare Registrar, Google Domains
2. EPP Server (Registry Systems)
What it does:
- Receives EPP commands from authorized registrars
- Validates commands against registry policies
- Executes operations on registry database
- Returns standardized EPP responses
- Enforces security and access controls
Example registries: Verisign (.com, .net), PIR (.org), Donuts (many new gTLDs)
3. Transport Layer
Connection details:
- Protocol: TCP/IP
- Port: 700 (standard) or 3121 (alternative)
- Encryption: TLS 1.2 or higher (required)
- Authentication: Username/password or certificate-based
- Session-based: Persistent connection for multiple commands
How a Domain Registration Flows Through EPP
Let's trace the complete flow when you register example.com:
Step 1: Customer Action
You → Namecheap Website → Search for "example.com" → Add to cart → Checkout
Step 2: Registrar Prepares Namecheap's system:
- Establishes EPP session with Verisign (.com registry)
- Authenticates using TLS certificate and credentials
- Sends EPP greeting received from server
Step 3: Domain Availability Check
Namecheap sends → domain:check command
Verisign responds → domain available
Step 4: Domain Creation
Namecheap sends → domain:create command with:
- Domain name: example.com
- Registration period: 1 year
- Contact IDs: registrant, admin, tech
- Nameservers: ns1.namecheap.com, ns2.namecheap.com
- Auth code: Randomly generated
Verisign processes → Creates domain in registry
Verisign responds → Success, creation date, expiration date
Step 5: Registrar Confirmation
Namecheap updates internal database → Sends confirmation email to you
Total time: Typically 1-3 seconds for the EPP commands
EPP Session Management
EPP uses persistent sessions rather than stateless requests:
Session Lifecycle:
- Connect: Client establishes TLS connection to registry
- Greeting: Server sends greeting with capabilities
- Login: Client authenticates with credentials
- Commands: Client sends multiple commands in the session
- Logout: Client terminates session gracefully
- Disconnect: TCP connection closes
Why sessions?
- Performance: Avoid reconnection overhead
- Security: Maintain authenticated state
- Transactions: Group related operations
- Rate limiting: Control per-session limits
EPP Command Flow Diagram
┌─────────────┐ ┌──────────────┐
│ Registrar │ │ Registry │
│ (Client) │ │ (Server) │
└──────┬──────┘ └──────┬───────┘
│ │
│ 1. TCP Connect (port 700) │
├─────────────────────────────────>│
│ │
│ 2. Server Greeting │
│<─────────────────────────────────┤
│ │
│ 3. <login> Command │
├─────────────────────────────────>│
│ │
│ 4. Login Success Response │
│<─────────────────────────────────┤
│ │
│ 5. <domain:check> Command │
├─────────────────────────────────>│
│ │
│ 6. Check Response (available) │
│<─────────────────────────────────┤
│ │
│ 7. <domain:create> Command │
├─────────────────────────────────>│
│ │
│ 8. Create Success Response │
│<─────────────────────────────────┤
│ │
│ 9. <logout> Command │
├─────────────────────────────────>│
│ │
│ 10. Logout Success Response │
│<─────────────────────────────────┤
│ │
│ 11. TCP Disconnect │
└──────────────────────────────────┘
EPP Commands Overview
EPP defines three categories of commands:
Query Commands (Read-Only)
These commands retrieve information without modifying registry data:
| Command | Purpose | Example Use Case |
|---|---|---|
| check | Verify if object is available | Check if domain is registered |
| info | Retrieve object details | Get domain expiration date |
| poll | Retrieve pending messages | Check for transfer notifications |
| transfer (query) | Check transfer status | Monitor pending transfer |
Transform Commands (Write Operations)
These commands modify registry data:
| Command | Purpose | Example Use Case |
|---|---|---|
| create | Register new object | Register a domain |
| delete | Remove object | Delete domain after expiration |
| renew | Extend registration period | Renew domain for another year |
| update | Modify object details | Change nameservers |
| transfer (request) | Initiate transfer | Move domain to new registrar |
| transfer (approve) | Approve pending transfer | Losing registrar approves transfer |
| transfer (reject) | Reject pending transfer | Losing registrar denies transfer |
| transfer (cancel) | Cancel pending transfer | Gaining registrar cancels transfer |
Session Commands
These commands manage the EPP session itself:
| Command | Purpose | Example Use Case |
|---|---|---|
| hello | Retrieve server greeting | Test connection |
| login | Authenticate session | Start authenticated session |
| logout | Terminate session | End session gracefully |
EPP Command Details
Domain Check
Purpose: Verify if one or more domain names are available for registration.
When it's used:
- Domain search on registrar website
- Bulk availability checking
- Pre-registration validation
Example request:
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<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:name>example.org</domain:name>
</domain:check>
</check>
<clTRID>ABC-12345</clTRID>
</command>
</epp>
Example response:
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:chkData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:cd>
<domain:name avail="1">example.com</domain:name>
</domain:cd>
<domain:cd>
<domain:name avail="0">example.net</domain:name>
<domain:reason>In use</domain:reason>
</domain:cd>
<domain:cd>
<domain:name avail="1">example.org</domain:name>
</domain:cd>
</domain:chkData>
</resData>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>XYZ-67890</svTRID>
</trID>
</response>
</epp>
Key fields:
avail="1": Domain is availableavail="0": Domain is registereddomain:reason: Why domain is unavailable (optional)
Domain Create
Purpose: Register a new domain name.
When it's used:
- Customer completes domain purchase
- Bulk registration operations
- Drop-catch registration (expired domains)
Example request:
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<create>
<domain:create xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.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-001</domain:registrant>
<domain:contact type="admin">CONTACT-002</domain:contact>
<domain:contact type="tech">CONTACT-003</domain:contact>
<domain:authInfo>
<domain:pw>2fooBAR</domain:pw>
</domain:authInfo>
</domain:create>
</create>
<clTRID>ABC-12346</clTRID>
</command>
</epp>
Example response:
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:creData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.com</domain:name>
<domain:crDate>2025-12-01T12:00:00.0Z</domain:crDate>
<domain:exDate>2027-12-01T12:00:00.0Z</domain:exDate>
</domain:creData>
</resData>
<trID>
<clTRID>ABC-12346</clTRID>
<svTRID>XYZ-67891</svTRID>
</trID>
</response>
</epp>
Required fields:
domain:name: Domain to registerdomain:period: Registration length (years or months)domain:registrant: Registrant contact IDdomain:authInfo: Authorization password for future transfers
Optional fields:
domain:ns: Nameservers (can be added later)domain:contact: Admin and technical contacts
Domain Info
Purpose: Retrieve detailed information about a domain.
When it's used:
- Displaying domain details in registrar control panel
- Verifying domain configuration
- Auditing domain status
Example request:
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<info>
<domain:info xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.com</domain:name>
<domain:authInfo>
<domain:pw>2fooBAR</domain:pw>
</domain:authInfo>
</domain:info>
</info>
<clTRID>ABC-12347</clTRID>
</command>
</epp>
Example response (abbreviated for readability):
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:infData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.com</domain:name>
<domain:roid>EXAMPLE1-REP</domain:roid>
<domain:status s="ok"/>
<domain:registrant>CONTACT-001</domain:registrant>
<domain:contact type="admin">CONTACT-002</domain:contact>
<domain:contact type="tech">CONTACT-003</domain:contact>
<domain:ns>
<domain:hostObj>ns1.example.com</domain:hostObj>
<domain:hostObj>ns2.example.com</domain:hostObj>
</domain:ns>
<domain:clID>Registrar123</domain:clID>
<domain:crID>Registrar123</domain:crID>
<domain:crDate>2020-01-15T00:00:00.0Z</domain:crDate>
<domain:exDate>2026-01-15T00:00:00.0Z</domain:exDate>
<domain:authInfo>
<domain:pw>2fooBAR</domain:pw>
</domain:authInfo>
</domain:infData>
</resData>
<trID>
<clTRID>ABC-12347</clTRID>
<svTRID>XYZ-67892</svTRID>
</trID>
</response>
</epp>
Key information returned:
- Domain status codes
- Registration and expiration dates
- Nameservers
- Contact IDs
- Sponsoring registrar (clID)
- Auth code (if authorized)
Domain Update
Purpose: Modify domain information such as nameservers, contacts, or status codes.
When it's used:
- Changing nameservers
- Updating contact information
- Adding/removing status codes (locks)
- Changing auth code
Example request (changing nameservers):
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<update>
<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:add>
<domain:rem>
<domain:ns>
<domain:hostObj>ns1.example.com</domain:hostObj>
</domain:ns>
</domain:rem>
<domain:chg>
<domain:authInfo>
<domain:pw>newAuthCode123</domain:pw>
</domain:authInfo>
</domain:chg>
</domain:update>
</update>
<clTRID>ABC-12348</clTRID>
</command>
</epp>
Update structure:
domain:add: Add elements (nameservers, contacts, status codes)domain:rem: Remove elementsdomain:chg: Change elements (auth code, registrant)
Domain Renew
Purpose: Extend a domain's registration period.
When it's used:
- Manual domain renewal
- Auto-renewal processing
- Bulk renewal operations
Example request:
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<renew>
<domain:renew xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.com</domain:name>
<domain:curExpDate>2026-01-15</domain:curExpDate>
<domain:period unit="y">1</domain:period>
</domain:renew>
</renew>
<clTRID>ABC-12349</clTRID>
</command>
</epp>
Example response:
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:renData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.com</domain:name>
<domain:exDate>2027-01-15T00:00:00.0Z</domain:exDate>
</domain:renData>
</resData>
<trID>
<clTRID>ABC-12349</clTRID>
<svTRID>XYZ-67894</svTRID>
</trID>
</response>
</epp>
Required fields:
domain:name: Domain to renewdomain:curExpDate: Current expiration date (validation)domain:period: Renewal length (typically 1-10 years)
Important: The curExpDate must match the registry's current expiration date, preventing accidental double renewals.
Domain Transfer
Purpose: Move domain sponsorship from one registrar to another.
Transfer types:
request: Gaining registrar initiates transferquery: Check transfer statusapprove: Losing registrar approves transferreject: Losing registrar denies transfercancel: Gaining registrar cancels transfer
Example transfer request:
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<transfer op="request">
<domain:transfer xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.com</domain:name>
<domain:period unit="y">1</domain:period>
<domain:authInfo>
<domain:pw>2fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>
<clTRID>ABC-12350</clTRID>
</command>
</epp>
Example response:
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1001">
<msg>Command completed successfully; action pending</msg>
</result>
<resData>
<domain:trnData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.com</domain:name>
<domain:trStatus>pending</domain:trStatus>
<domain:reID>LoseRegistrar</domain:reID>
<domain:reDate>2025-12-01T12:00:00.0Z</domain:reDate>
<domain:acID>GainRegistrar</domain:acID>
<domain:acDate>2025-12-06T12:00:00.0Z</domain:acDate>
</domain:trnData>
</resData>
<trID>
<clTRID>ABC-12350</clTRID>
<svTRID>XYZ-67895</svTRID>
</trID>
</response>
</epp>
Transfer process:
- Gaining registrar sends
transfer requestwith auth code - Registry validates auth code
- Transfer enters
pendingstate (typically 5-7 days) - Losing registrar can
approve(completes immediately) orreject - If no action, transfer auto-approves after waiting period
- Registry updates sponsoring registrar
Domain Delete
Purpose: Remove a domain from the registry (rare operation).
When it's used:
- Deleting domains during grace period (refund)
- Registry administrator operations
- Scheduled deletion after expiration
Example request:
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<delete>
<domain:delete xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.com</domain:name>
</domain:delete>
</delete>
<clTRID>ABC-12351</clTRID>
</command>
</epp>
Important notes:
- Rarely used by registrars (domains normally expire, not delete)
- Add Grace Period (5 days) allows deletion with full refund
- After grace period, domains expire and enter redemption period
- Only registry operators can delete after expiration
EPP Response Structure
All EPP responses follow a consistent XML structure:
Success Response
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<msgQ count="5" id="12345">
<qDate>2025-12-01T12:00:00.0Z</qDate>
<msg>Transfer requested.</msg>
</msgQ>
<resData>
<!-- Command-specific response data -->
</resData>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>XYZ-67890</svTRID>
</trID>
</response>
</epp>
Key elements:
- result code: Numeric status code (1000 = success)
- msg: Human-readable message
- msgQ: Message queue info (pending notifications)
- resData: Command-specific response data
- trID: Transaction IDs (client and server)
Error Response
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="2201">
<msg>Authorization error</msg>
<extValue>
<value>
<domain:name>example.com</domain:name>
</value>
<reason>Invalid authorization information</reason>
</extValue>
</result>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>XYZ-67890</svTRID>
</trID>
</response>
</epp>
Error details:
- result code: Error code (2xxx = command failed)
- msg: Error description
- extValue: Additional error context (optional)
- reason: Specific reason for failure
EPP Status Codes
EPP responses use numeric status codes similar to HTTP:
Success Codes (1xxx)
| Code | Meaning | Description |
|---|---|---|
| 1000 | Success | Command completed successfully |
| 1001 | Success (pending) | Command completed; action pending |
| 1300 | Success (no messages) | Command completed; no queue messages |
| 1301 | Success (ack to dequeue) | Command completed; ack message to dequeue |
| 1500 | Success (ending session) | Command completed successfully; ending session |
Client Error Codes (2xxx)
| Code | Meaning | Common Cause |
|---|---|---|
| 2000 | Unknown command | Invalid EPP command |
| 2001 | Command syntax error | Malformed XML |
| 2002 | Command use error | Using command incorrectly |
| 2003 | Required parameter missing | Missing mandatory field |
| 2004 | Parameter value range error | Value out of allowed range |
| 2005 | Parameter value syntax error | Invalid format |
| 2100 | Unimplemented protocol version | EPP version not supported |
| 2101 | Unimplemented command | Command not supported by registry |
| 2102 | Unimplemented option | Option not supported |
| 2103 | Unimplemented extension | Extension not supported |
| 2104 | Billing failure | Payment or credit issue |
| 2105 | Object not eligible for renewal | Domain can't be renewed (e.g., too early) |
| 2106 | Object not eligible for transfer | Domain can't be transferred |
| 2200 | Authentication error | Login failed |
| 2201 | Authorization error | Insufficient privileges or invalid auth code |
| 2202 | Invalid authorization information | Wrong auth code |
| 2300 | Object pending transfer | Domain has pending transfer |
| 2301 | Object not pending transfer | No pending transfer exists |
| 2302 | Object exists | Domain already registered |
| 2303 | Object does not exist | Domain not found |
| 2304 | Object status prohibits operation | Domain locked or in wrong state |
| 2305 | Object association prohibits operation | Dependencies prevent operation |
| 2306 | Parameter value policy error | Value violates policy |
| 2307 | Unimplemented object service | Service not available |
| 2308 | Data management policy violation | Operation violates data policy |
Server Error Codes (5xxx)
| Code | Meaning | Description |
|---|---|---|
| 2400 | Command failed | Generic failure |
| 2500 | Command failed; server closing connection | Fatal error |
| 2501 | Authentication error; server closing | Auth failed |
| 2502 | Session limit exceeded; server closing | Too many sessions |
EPP Authorization Codes (Auth Codes)
Authorization codes (also called EPP codes, auth codes, or transfer keys) are passwords that protect domains from unauthorized transfers.
What are Auth Codes?
Auth codes are randomly generated passwords assigned to each domain. To transfer a domain to a new registrar, you must provide the correct auth code to prove ownership.
Example auth code: Xy7$kL2p!9Qm
Auth Code Format
Typical characteristics:
- Length: 8-32 characters
- Complexity: Mix of letters, numbers, symbols
- Case-sensitive: Yes
- Validity: Permanent until changed
Generated by: Registry when domain is created, or by current registrar on request
How Auth Codes Work
Domain transfer process:
- Domain owner requests auth code from current registrar
- Registrar retrieves auth code from registry via EPP
domain:info - Owner provides auth code to new registrar
- New registrar submits transfer via EPP
domain:transferwith auth code - Registry validates auth code
- If valid, transfer proceeds; if invalid, transfer rejected (code 2202)
Getting Your Auth Code
From your registrar:
- Log into registrar control panel
- Find domain management section
- Look for "Transfer Out", "Auth Code", or "EPP Code"
- Click to reveal or email auth code
Registrar requirements:
- ICANN requires registrars to provide auth codes within 5 days
- Most registrars provide immediately
- Some require account verification first
Changing Auth Codes
Registrars can change auth codes via EPP domain:update:
<domain:chg>
<domain:authInfo>
<domain:pw>newAuthCode456</domain:pw>
</domain:authInfo>
</domain:chg>
When to change auth code:
- After failed transfer attempt (security)
- If auth code was compromised
- Regular security rotation
Auth Code Security
Protecting your auth code:
- ✅ Store securely (password manager)
- ✅ Only share with trusted registrars
- ✅ Change after any transfer
- ✅ Enable transfer lock to prevent unauthorized use
- ❌ Don't email in plain text
- ❌ Don't post publicly
Transfer locks override auth codes: Even with a valid auth code, domains with clientTransferProhibited or serverTransferProhibited status cannot be transferred until unlocked.
XML Structure of EPP Messages
EPP uses XML for all communication. Understanding the structure helps troubleshoot issues.
Basic XML Structure
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<!-- Commands or responses go here -->
</epp>
XML Namespaces
EPP uses XML namespaces to organize elements:
Core namespace:
xmlns="urn:ietf:params:xml:ns:epp-1.0"
Domain namespace:
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"
Contact namespace:
xmlns:contact="urn:ietf:params:xml:ns:contact-1.0"
Host namespace:
xmlns:host="urn:ietf:params:xml:ns:host-1.0"
Complete Command Example
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
<command>
<check>
<domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"
xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
<domain:name>example.com</domain:name>
</domain:check>
</check>
<clTRID>ABC-12345</clTRID>
</command>
</epp>
XML Schema Validation
EPP servers validate all commands against XML schemas:
EPP base schema: epp-1.0.xsd
Domain schema: domain-1.0.xsd
Contact schema: contact-1.0.xsd
Host schema: host-1.0.xsd
Invalid XML results in:
- Code 2001: Command syntax error
- Server rejects command without processing
EPP Extensions
EPP's extensibility allows registries to add custom functionality beyond the core protocol.
Why Extensions Exist
Core EPP covers basics, but registries need specialized features:
- DNSSEC key management
- IDN (internationalized domain names)
- Registry-specific policies
- Premium pricing
- Custom fields
Common EPP Extensions
1. DNSSEC Extension (secDNS)
Purpose: Manage DNSSEC key material
Namespace: urn:ietf:params:xml:ns:secDNS-1.1
Example (adding DNSSEC):
<extension>
<secDNS:create xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1">
<secDNS:dsData>
<secDNS:keyTag>12345</secDNS:keyTag>
<secDNS:alg>8</secDNS:alg>
<secDNS:digestType>2</secDNS:digestType>
<secDNS:digest>38EC...</secDNS:digest>
</secDNS:dsData>
</secDNS:create>
</extension>
2. Launch Extension
Purpose: Handle new TLD launches (sunrise, landrush phases)
Namespace: urn:ietf:params:xml:ns:launch-1.0
Example (sunrise registration):
<extension>
<launch:create xmlns:launch="urn:ietf:params:xml:ns:launch-1.0">
<launch:phase>sunrise</launch:phase>
<launch:smd>PD94bWwgd...</launch:smd>
</launch:create>
</extension>
3. Registry Grace Period (RGP)
Purpose: Manage grace period operations
Namespace: urn:ietf:params:xml:ns:rgp-1.0
Example (restore after redemption):
<extension>
<rgp:update xmlns:rgp="urn:ietf:params:xml:ns:rgp-1.0">
<rgp:restore op="request"/>
</rgp:update>
</extension>
4. IDN Extension
Purpose: Handle internationalized domain names
Namespace: Varies by registry
Example (language tag):
<extension>
<idn:create xmlns:idn="urn:ietf:params:xml:ns:idn-1.0">
<idn:languageTag>zh-Hans</idn:languageTag>
</idn:create>
</extension>
5. Premium Domain Pricing
Purpose: Handle premium domain pricing
Namespace: Registry-specific
Example (fee extension):
<extension>
<fee:check xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:domain>
<fee:name>premium.com</fee:name>
<fee:command>create</fee:command>
<fee:period unit="y">1</fee:period>
</fee:domain>
</fee:check>
</extension>
Registry-Specific Extensions
Each registry can define proprietary extensions:
Verisign (.com, .net):
- Sync extension
- IDN language extension
- NameStore extension (product bundling)
PIR (.org):
- ID protection extension
- Registry lock extension
Nominet (.uk):
- Direct Rights Protection extension
- Tag extension
EPP and Domain Transfers
Domain transfers are one of EPP's most complex operations. Understanding the process helps troubleshoot transfer issues.
Transfer Prerequisites
Before transfer can start:
- ✅ Domain unlocked (no
clientTransferProhibitedstatus) - ✅ Valid auth code obtained
- ✅ Domain registered at least 60 days
- ✅ No pending transfer
- ✅ Not within 60 days of previous transfer
- ✅ Not expired
Transfer Timeline
Day 0: Gaining registrar submits EPP transfer request
- Registry validates auth code
- Transfer enters
pendingstatus - Losing registrar notified via EPP poll message
Day 0-5: Waiting period
- Losing registrar can approve (instant transfer)
- Losing registrar can reject (transfer fails)
- Domain owner can cancel at gaining registrar
Day 5: Auto-approval
- If losing registrar takes no action, transfer auto-approves
- Registry updates sponsoring registrar
- Domain renewed for 1 year (added to current expiration)
Day 5+: Transfer complete
- Gaining registrar now controls domain
- Auth code should be changed
EPP Transfer States
| State | Meaning | Next Action |
|---|---|---|
clientApproved |
Losing registrar approved | Transfer completes immediately |
clientRejected |
Losing registrar rejected | Transfer fails; retry after fixing issues |
clientCancelled |
Gaining registrar cancelled | Transfer cancelled |
pending |
Awaiting action | Auto-approves after 5 days |
serverApproved |
Registry approved | Rare; registry intervention |
serverCancelled |
Registry cancelled | Rare; registry intervention |
Common Transfer Failures
Code 2201: Authorization error
- Invalid or incorrect auth code
- Auth code expired
- Fix: Get correct auth code from current registrar
Code 2304: Object status prohibits operation
- Domain locked (
clientTransferProhibited) - Fix: Unlock domain at current registrar
Code 2106: Object not eligible for transfer
- Domain registered less than 60 days ago
- Transfer within 60 days of previous transfer
- Fix: Wait until eligible
Code 2302: Object exists (transfer already pending)
- Another transfer is in progress
- Fix: Cancel existing transfer or wait for completion
Transfer EPP Flow
Gaining Registrar Registry Losing Registrar
| | |
| 1. transfer request | |
| (with auth code) | |
|--------------------------->| |
| | |
| | 2. Validate auth code |
| | 3. Check eligibility |
| | 4. Set status: pending |
| | |
| | 5. Poll message: |
| | transfer requested |
| |--------------------------->|
| | |
| 6. Response: pending | |
|<---------------------------| |
| | |
| | [ 5-day wait period ] |
| | |
| | 7. Auto-approve (or manual)|
| | 8. Update sponsorship |
| | 9. Renew domain +1 year |
| | |
| 10. Poll message: | |
| transfer completed | |
|<---------------------------| |
| | |
| | 11. Poll message: |
| | transfer completed |
| |--------------------------->|
EPP Security Features
EPP was designed with security as a core requirement:
Transport Layer Security (TLS)
Required encryption:
- All EPP communication uses TLS 1.2 or higher
- Registry servers reject unencrypted connections
- Prevents eavesdropping and man-in-the-middle attacks
Certificate validation:
- Registrars verify registry's SSL certificate
- Some registries require client certificates (mutual TLS)
Authentication
Credentials:
- Username and password required for login
- Some registries use client certificates instead
- Session authentication persists until logout
Login command:
<login>
<clID>RegistrarID</clID>
<pw>EncryptedPassword</pw>
<newPW>NewPasswordOptional</newPW>
<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>
<objURI>urn:ietf:params:xml:ns:host-1.0</objURI>
</svcs>
</login>
Authorization
Object-level authorization:
- Registrars can only modify domains they sponsor
- Auth codes required for cross-registrar operations
- Contact/host objects have ownership rules
Status-based protection:
- Status codes like
clientTransferProhibitedprevent unauthorized transfers clientUpdateProhibitedprevents unauthorized changesclientDeleteProhibitedprevents accidental deletion
Rate Limiting
Registry-imposed limits:
- Maximum commands per second (e.g., 10/second)
- Maximum concurrent sessions (e.g., 5 per registrar)
- Throttling during high load
Protects against:
- Abuse and resource exhaustion
- Accidental loops in registrar software
- Competitive domain sniping
Audit Trail
Transaction IDs:
- Every command has unique client transaction ID (
clTRID) - Every response has unique server transaction ID (
svTRID) - Registries log all transactions for compliance
Logging requirements:
- ICANN requires transaction logs retained for years
- Used for dispute resolution
- Compliance auditing
How EPP Helps Troubleshoot Domain Issues
Understanding EPP empowers you to diagnose and fix domain problems:
Issue: Domain Won't Transfer
Check EPP status codes:
clientTransferProhibited → Unlock at current registrar
serverTransferProhibited → Contact registry (rare)
pendingTransfer → Wait for current transfer to complete
Verify eligibility:
- Registered less than 60 days? Wait.
- Transferred within 60 days? Wait.
- Expired? Renew first.
Test auth code:
- Try transfer at new registrar—EPP will return code 2201 if auth code is invalid
Issue: Nameservers Won't Update
Check EPP status codes:
clientUpdateProhibited → Unlock at registrar
serverUpdateProhibited → Contact registry
serverHold → Domain suspended (often for non-payment)
Verify nameserver format:
- EPP requires fully qualified domain names:
ns1.example.com(notns1) - Must have valid A/AAAA records
Check for EPP errors:
- Registrar control panel may show EPP error codes
- Code 2005 = Invalid nameserver format
- Code 2303 = Nameserver doesn't exist in registry
Issue: Domain Appears "Locked"
Identify specific lock:
clientUpdateProhibited → Prevents updates (nameservers, contacts)
clientDeleteProhibited → Prevents deletion
clientTransferProhibited → Prevents transfers
clientHold → Domain doesn't resolve (DNS disabled)
Resolution:
- Registrar-applied locks (
client*) → Unlock in registrar control panel - Registry-applied locks (
server*) → Contact registrar to contact registry redemptionPeriod→ Domain expired; restore via registrar
Issue: Contact Information Not Updating
Possible EPP causes:
- Code 2304: Domain locked with
clientUpdateProhibited - Code 2306: Contact info violates registry policy (e.g., invalid country code)
- Code 2002: Using wrong contact ID format
Troubleshooting:
- Verify domain is unlocked
- Check that required fields are provided
- Ensure format matches registry requirements
Issue: Transfer Failed with "Authorization Error"
EPP Code 2201 indicates:
- Wrong auth code entered
- Auth code expired (some registries time-limit codes)
- Auth code not yet generated
Fix:
- Log into current registrar
- Request/reveal auth code (may take up to 5 days per ICANN)
- Copy carefully (auth codes are case-sensitive)
- Paste into new registrar's transfer form
- Retry transfer
Reading Registrar Error Messages
Many registrars expose EPP codes in error messages:
Good registrar error message:
Transfer failed: Authorization error (EPP code 2201).
Please verify your authorization code and try again.
Poor registrar error message:
Transfer failed. Please contact support.
If no code shown: Ask support for the EPP error code—helps diagnose issue faster.
EPP vs Other Protocols
How does EPP compare to other domain-related protocols?
EPP vs WHOIS
| Feature | EPP | WHOIS |
|---|---|---|
| Purpose | Domain provisioning | Domain information lookup |
| Users | Registrars only | Anyone |
| Authentication | Required | None |
| Transport | TCP port 700, TLS | TCP port 43, plain text |
| Format | XML | Unstructured text |
| Operations | Create, update, delete, transfer | Read-only queries |
Relationship: EPP manages domains; WHOIS displays domain info publicly.
EPP vs RDAP
| Feature | EPP | RDAP |
|---|---|---|
| Purpose | Domain provisioning | Domain information lookup |
| Users | Registrars only | Anyone |
| Authentication | Required | Optional (for extended access) |
| Transport | TCP port 700, TLS | HTTPS (RESTful API) |
| Format | XML | JSON |
| Operations | Full CRUD | Read-only |
Relationship: EPP is the "write" protocol (registrars modify); RDAP is the "read" protocol (public queries).
EPP vs DNS
| Feature | EPP | DNS |
|---|---|---|
| Purpose | Domain registration management | Domain name resolution |
| Users | Registrars | Everyone |
| Transport | TCP port 700, TLS | UDP port 53 (TCP for large) |
| Format | XML | Binary |
| Operations | Register/update domains | Resolve names to IPs |
Relationship: EPP manages domain records at registry; DNS resolves domains at runtime.
EPP vs RRP (Legacy)
| Feature | EPP | RRP |
|---|---|---|
| Status | Current standard | Deprecated |
| Format | XML | Line-based text |
| Transport | TCP+TLS | TCP, plain text |
| Extensibility | XML extensions | Limited |
| Security | TLS encryption, auth | Minimal |
History: RRP was EPP's predecessor. EPP replaced RRP due to superior security, extensibility, and standardization.
Frequently Asked Questions
Can I use EPP as an individual domain owner?
No, EPP access is restricted to accredited registrars. As an individual, you interact with your registrar's interface, which then uses EPP on your behalf to communicate with registries. There is no public EPP access.
Why do domain transfers take 5-7 days?
The 5-day window is built into the EPP transfer process to give the losing registrar time to verify the transfer with the domain owner and prevent fraud. Losing registrars can approve immediately (instant transfer), but if they take no action, the transfer auto-approves after 5 days. This delay protects against unauthorized transfers.
What is the difference between an EPP code and an auth code?
They're the same thing. "Auth code," "EPP code," "transfer key," and "authorization code" all refer to the password required to transfer a domain. The technically correct term per EPP specifications is "authorization information" (authInfo), but "auth code" is most common.
Can registrars see EPP auth codes for domains they don't manage?
No. EPP enforces strict authorization. A registrar can only retrieve auth codes (via domain:info) for domains they currently sponsor. This prevents registrars from initiating unauthorized transfers of competitors' domains.
Why do some domains have status codes like clientTransferProhibited?
These EPP status codes provide security by locking domains against specific operations. clientTransferProhibited prevents transfers, protecting against domain hijacking. clientUpdateProhibited prevents unauthorized nameserver changes. Registrars apply these locks either automatically (as a security feature) or at the domain owner's request.
What happens if my registrar sends an invalid EPP command?
The registry's EPP server validates all commands against XML schemas. If a command is malformed, the registry returns an error code (typically 2001 for syntax errors or 2003 for missing required fields) without processing the command. The registrar's system should handle the error and either retry with a corrected command or alert the user.
Can I get EPP logs for my domains?
Generally no, but you can ask your registrar. EPP transaction logs are maintained by registrars and registries for compliance purposes, not typically shared with domain owners. However, some registrars may provide limited EPP history (like "domain updated on [date]") in control panels.
How does EPP handle domain privacy/WHOIS privacy?
EPP doesn't directly handle WHOIS privacy. When a registrar enables privacy, they typically: (1) Update the domain's contact objects via EPP to point to proxy contacts, or (2) Use a registrar-provided privacy service that intercepts WHOIS queries. The domain's EPP contact objects may show the privacy service's contact IDs instead of the owner's.
What is the EPP poll queue?
The poll queue is a message system where registries send notifications to registrars about important events. Registrars retrieve messages using the EPP poll command. Common messages include: transfer requests, transfer completions, expiration warnings, and registry policy updates. Each message has a unique ID and must be acknowledged to remove it from the queue.
Can domains be registered through EPP without a registrar?
No. EPP access requires accreditation. To become an accredited registrar, organizations must meet ICANN's requirements (financial stability, technical infrastructure, compliance capabilities) and pay accreditation fees ($3,500 application + $4,000/year). Individuals and small businesses use existing registrars instead.
Key Takeaways
-
EPP is the backbone of domain registration, enabling registrars to communicate with registries for all domain operations
-
XML-based protocol operating over TLS-encrypted TCP port 700, providing security and standardization
-
Core commands include create, check, info, update, renew, transfer, and delete—covering the complete domain lifecycle
-
EPP status codes (like
clientTransferProhibited) control what operations are allowed and help troubleshoot issues -
Auth codes are EPP's security mechanism, required for domain transfers to prevent unauthorized moves
-
EPP responses use numeric codes similar to HTTP—1xxx = success, 2xxx = client error, 5xxx = server error
-
Extensions enable customization for DNSSEC, IDN, premium pricing, and registry-specific features
-
Transfer process takes 5-7 days with built-in protections against fraud through auth code verification
-
Registrars-only access means individuals interact with registrar interfaces, which use EPP behind the scenes
-
Understanding EPP helps troubleshoot domain transfer failures, update issues, and lock-related problems
Next Steps
If You're a Domain Owner:
- Learn EPP status codes to understand why domains are locked or transfers fail
- Secure your auth codes like passwords—they protect your domains from unauthorized transfers
- Check domain status in your registrar control panel—look for EPP status codes
- Understand transfer process before initiating—know the 5-day timeline and requirements
If You're a Developer:
- Become an accredited registrar if you're building a domain registration business (ICANN application process)
- Study EPP RFCs: RFC 5730 (base), RFC 5731 (domain mapping), RFC 5732 (host), RFC 5733 (contact)
- Use EPP client libraries: Many languages have EPP libraries (PHP-EPP, EPPy for Python, etc.)
- Test in OT&E environment: Registries provide test environments for EPP integration
If You're Experiencing Domain Issues:
- Ask for EPP error codes when contacting registrar support—helps diagnose faster
- Check EPP status codes via WHOIS or RDAP to identify specific locks
- Understand transfer eligibility before attempting—60-day restrictions, unlock requirements
- Verify auth code carefully if transfers fail—auth codes are case-sensitive
Related Articles:
- Understanding EPP Status Codes
- How to Transfer a Domain Name
- What is a Domain Name?
- Domain Lifecycle Stages
Research Sources
This article was researched using information from authoritative sources: