Author image Vadim Likhota (Вадим Лихота)


IO::EPP - Object and procedure interface of the client-side for work with EPP API of registries and some resellers


    use IO::EPP;
    print "IO::EPP version is $IO::EPP::VERSION\n";


IO::EPP is a very light and fast interface of the access to EPP API from the client's side with minimum dependences. It is independent of libxml and other heavy libraries.

It works over IO::Socket::SSL without additional modules and demands only Digest::MD5 for generation of unique ID and Time::HiRes for the purpose of logging. LWP is necessary for two registries and one reseller (TCI/RIPN, Taeping и HosterKZ), because EPP of these providers works over HTTPS.

In test mode IO::EPP can emulate the job of some registries. Now the emulation of Verisign Core and CentralNic servers is supported at the level of 99% of answers. The test environment for IO::EPP::Base uses the emulation of CentralNic without extensions.

The main difference of the emulation from a registry is that all the data are into the process which makes requests. That's why when the process comes to the end all the data will be lost. If you want to save the data between queries you need to replace the functions in the module IO::EPP::Test::Server.

The library IO::EPP has two ways of working - procedural or object one. The procedural method works over the object one and when called returns the object of connection.

The authorization occurs when an object is created.

Logout is called automatically from the object destructor.

The basic module is IO::EPP::Base. It supports all the functions of EPP RFC and the extension DNSSEC. But since many registries and resellers use a large number of their own extensions the special modules that work over IO::EPP::Base are wrote for them.

The description of definite functions see in IO::EPP::Base.

The special parameters for every provider should be seen in relevant modules.

Full examples of working with every function of packages see in the tests t/Base.t and t/VerisignCore.t.


For now there are the modules for such providers:


The universal module for working with EPP API and the basic class for other modules.


Registry for gtlds (Core Server), cctlds and new gtlds (NameStore Server)


.org, .ngo, .org, .орг, .संगठन, .机构 –

Registry for gltds and cctlds


Registry for 3lvl.cctlds and new gtlds


Reseller, belongs to the CentralNic Group


Registry for cctlds and some new gtlds

.рус –


The module for working with TCI tlds over normal EPP

Registry for .tatar, .дети


The module for working with TCI tlds over HTTPS, needs LWP

Registry for .ru, .su, .рф


Registry for, org. tlds

This module works over HTTPS, needs LWP


Registry for .moscow, .москва, and tlds


Registry for new gtlds


Registry for,, and reseller for other .ua tlds


Reseller, a division of BRS Media Inc.


Reseller for .kz, .қаз tlds

This module works over HTTPS, needs LWP.

The links on documentation of EPP for each provider are in relevant modules.

The list of emulation modules:


The module of emulation of server with standard EPP API, mostly repeats the behavior of CentralNic server.


The module of emulation of CentralNic server.


The module of emulation of Verisign Core Server. The real test Verisign server does not support the redemption of domains. The redemption of domains works in this module, but without checking of parametres.

For working with emulation of registries it is necessary to set the parameter test_mode = 1. Error codes and messages have been checked on production server.

The modules of emulation of other registries are still in construction.


It is more convenient for cases when it is necessary to keep the connection with the registry.

An example of registration of a new nameserver

    use IO::EPP::CNic;
    use Data::Dumper;

    # Parameters for IO::Socket::SSL
    my %sock_params = (
        PeerHost        => '',
        PeerPort        => 700,
        SSL_key_file    => 'ssl_key_file.pem',
        SSL_cert_file   => 'ssl_cert_file.pem',
        Timeout         => 30,
        debug           => 1,

    # Login parameters
    my %params = (
        user        => 'H1234567',
        pass        => 'XXXXXXXX',
        sock_params => \%sock_params,
        test_mode   => 0, # real connect
        no_log      => 1, # without logger

    my $conn = IO::EPP::CNic->new( \%params ); # create object, get greeting and call login()

    my ( $answer, $code, $msg ) = $conn->get_ns_info( ns => '' );

    if ( $code == 2303 ) {
        # $msg eq 'The host '' does not exist'
        ( $answer, $code, $msg ) = $conn->create_ns( { ns => '', ips => ['', 'fe80::1'] } );

        if ( $code == 1000 ) {
            print "ns created\n";
        else {
            print "error: $msg\n";
    elsif ( $code == 1000 ) {
        print " allready exist: " . Dumper $answer;
    else {
        print "error getting ns info: $msg\n";

    undef $conn; # call logout() and DESTROY()


This method of working is more suitable for single requests.

An example of cheking of two domains access

    use Data::Dumper;
    use IO::EPP::Verisign;
    use Config;

    # common function for setting the connection parametres
    sub make_request {
        my ( $action, $params ) = @_;

        if ( !$params->{tld}  &&  $params->{dname} ) {
            ( $params->{tld} ) = $params->{dname} =~ /\.([^.]+)$/;

        unless ( $params->{tld} ) {
            my $msg = 'Not found tld';
            return ( { code => 0, msg => "code: 0\nmsg: $msg" }, $msg, 0 );

        unless ( $params->{conn} ) {
            # need create new connection
            state $config = Config::get('Providers.Verisign');

            # Parameters for IO::Socket::SSL
            my %sock_params = (
                PeerPort         => $config->{port},
                Proto            => 'tcp',
                SSL_key_file     => $config->{ssl_key_file},
                SSL_cert_file    => $config->{ssl_cert_file},
                # SSL_verify_mode => SSL_VERIFY_NONE, -- for this parameter need use IO::Socket::SSL
                Timeout          => 30,
                debug            => 1,

            if ( $params->{tld} =~ /^(com|net|edu)$/ ) {
                $params->{server}      = 'Core';
                $params->{user}        = $config->{core_username};
                $params->{pass}        = $config->{core_password};
                $sock_params{PeerHost} = $config->{core_url}; #
            elsif ( $params->{tld} eq 'name' ) {
                # For .name need set special epp extensions
                # earlier this tld was located on the dedicated server
                $params->{server}      = 'DotName';
                $params->{user}        = $config->{name_username};
                $params->{pass}        = $config->{name_password};
                $sock_params{PeerHost} = $config->{name_url}; #
            else {
                # .tv, .cc, .jobs and other tlds
                $params->{server}      = 'NameStore';
                $params->{user}        = $config->{name_username};
                $params->{pass}        = $config->{name_password};
                $sock_params{PeerHost} = $config->{name_url}; #

            $params->{sock_params} = \%sock_params;
            $params->{test_mode} = 0;
            # By default the logging is directed into STDOUT, but this can be changed
            # $params->{no_logs} = 1; -- work without logs
            # $params->{log_fn} = sub { print "\nverisign logger:\n$_[0]\n" }; -- use manual logger
            $params->{log_name} = '/var/log/comm_epp_verisign.log'; # use this file for output

        return IO::EPP::Verisign::make_request( $action, $params );

    my ( $answer, $msg ) = make_request(  'check_domains', { tld => 'com', domains => [ '', '' ] } );

    print Dumper $answer;

As a result in STDOUT will be output:

    $VAR1 = {
          'msg' => 'Command completed successfully',
          '' => {
                                            'avail' => '1'
          '' => {
                         'reason' => 'Domain exists',
                         'avail' => '0'
          'code' => '1000'


Vadim Likhota <>, some edits were made by Andrey Voyshko, Victor Efimov


This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


  • Version # 1 will be assigned to the library when the emulations of all registries and the tests for them will be written.

  • The additions for working with other registries and resellers are welcome.