diff --git a/dnsapi/dns_cpanel.sh b/dnsapi/dns_cpanel.sh
new file mode 100644
index 00000000..c4ead3fa
--- /dev/null
+++ b/dnsapi/dns_cpanel.sh
@@ -0,0 +1,281 @@
+#!/usr/bin/env bash
+
+#This is a dns hook for cpanel
+#This file name is "dns_cpanel.sh"
+#This hook is compatible with cpdyndns from https://forums.cpanel.net/threads/can-cpanel-update-dynamic-ip-information-to-dns-records.261951/
+# cpdyndns is not required, but this was designed to update a domain on a dd-wrt router to a cpanel hosted public domain. It may work elsewhere
+# test and use at your own peril.
+#returns 0 means success, otherwise error.
+#
+#Author: smithec
+#Report Bugs here: https://github.com/Neilpang/acme.sh
+#
+#Tested on DD-WRT, Linux Mint 18
+#
+# This is released without ANY warranty or guarantee of use. USE THIS AT YOUR OWN RISK.
+# Your use of this API signifies an agreement to hold blameless the developers for any results or damages that may occur to you or to others.
+# Always backup your data files and cPanel zones prior to using any tool that you allow to make edits.
+
+######## Public functions #####################
+
+#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
+dns_cpanel_add() {
+ fulldomain="$1"
+ txtvalue="$2"
+ _info "Using cPanel add"
+ _debug fulldomain: "$fulldomain"
+ _debug txtvalue: "$txtvalue"
+ _get_root
+ _setup_vars
+ _setup_timeout
+ _load_config
+ _check_config
+ _generate_auth_string
+
+ REQUEST="GET /xml-api/cpanel?cpanel_xmlapi_module=ZoneEdit&cpanel_xmlapi_func=add_zone_record&cpanel_xmlapi_apiversion=2&domain=$_domain&name=$_sub_domain&type=TXT&txtdata=$txtvalue&ttl=300 HTTP/1.0\r\nConnection: close\r\nAuthorization: Basic $AUTH_STRING\r\nUser-Agent: $USERAGENT $VERSION\r\n\r\n\r\n"
+ RESULT=`echo -e "$REQUEST" | openssl s_client -quiet -connect $CPANEL_SERVER:2083 2>&1`
+ _check_results_for_error "$RESULT" "$REQUEST"
+ _terminate
+ return 1
+}
+
+#Usage: fulldomain txtvalue
+#Remove the txt record after validation.
+dns_cpanel_rm() {
+ fulldomain=$1
+ txtvalue=$2
+ _info "Using cpanel rm"
+ _debug fulldomain "$fulldomain"
+ _debug txtvalue "$txtvalue"
+ _get_root
+ _setup_vars
+ _setup_timeout
+ _load_config
+ _check_config
+ _generate_auth_string
+
+ _retreive_zone
+ _parse_zone_lines
+}
+
+#################### Private functions below ##################################
+
+#_acme-challenge.www.domain.com
+#returns
+# _sub_domain=_acme-challenge.www
+# _domain=domain.com
+_get_root() {
+_debug "IN _get_root()"
+ domain="$fulldomain"
+ i=3
+ p=2
+ _domain=$(printf "$domain" | cut -d . -f $i-100)
+ _sub_domain=$(printf "$domain" | cut -d . -f 1-$p)
+ _debug domain "$_domain"
+ _debug subdomain "$_sub_domain"
+_debug "OUT _get_root()"
+}
+
+# This loads a pre-existing config file from cpdyndns
+# your config file should be located at ~/etc/cpdyndns.conf
+# a proper file will contain:
+#CONTACT_EMAIL="my_email_here@cpanel.net"
+#CPANEL_SERVER="my_server_here.cpanel.net"
+#DOMAIN="my_domain_here.tld"
+#SUBDOMAIN="my_subdomain_here"
+#CPANEL_USER="my_username_here"
+#CPANEL_PASS="my_password_here"
+_load_config ()
+{
+ if [ -e "/etc/$BASEDIR.conf" ]; then
+ chmod 0600 /etc/$BASEDIR.conf
+ . /etc/$BASEDIR.conf
+ _debug "== /etc/$BASEDIR.conf is being used for configuration"
+ else
+ _debug "== /etc/$BASEDIR.conf does not exist"
+ fi
+ if [ -e "$HOMEDIR/etc/$BASEDIR.conf" ]; then
+ chmod 0600 $HOMEDIR/etc/$BASEDIR.conf
+ . $HOMEDIR/etc/$BASEDIR.conf
+ _debug "== $HOMEDIR/etc/$BASEDIR.conf is being used for configuration"
+ else
+ _debug "== $HOMEDIR/etc/$BASEDIR.conf does not exist"
+ fi
+}
+
+#Prime needed Variables
+#These are meant to be compatible with cpdyndns/cpanel-dynamic-dns.sh
+#You can use the CPANEL Values here, but this is designed to use a config file see _load_config()
+_setup_vars ()
+{
+ USERAGENT="acme.sh/dns_cpanel.sh"
+ VERSION="0.1"
+ APINAME=""
+ PARENTPID=$$
+ HOMEDIR=`echo ~`
+ TIMEOUT="300"
+ BASEDIR="cpdyndns"
+ CPANEL_SERVER=""
+ CPANEL_USER=""
+ CPANEL_PASS=""
+}
+
+_exit_timeout ()
+{
+ ALARMPID=""
+ _err "Timeout while connecting to $LAST_CONNECT_HOST"
+ exit
+}
+
+_setup_timeout ()
+{
+ (sleep $TIMEOUT; kill -ALRM $PARENTPID) &
+ ALARMPID=$!
+ trap exit_timeout SIGALRM
+}
+
+#Generate an Authentication String for cPanel
+_generate_auth_string () {
+ AUTH_STRING=`echo -n "$CPANEL_USER:$CPANEL_PASS" | openssl enc -base64`
+}
+
+#verify our configuration
+_check_config () {
+ if [ -z "$CPANEL_SERVER" ]; then
+ _err "= Error: CPANEL_SERVER must be set in a configuration file"
+ exit
+ fi
+ if [ -z "$CPANEL_USER" ]; then
+ _err "= Error: CPANEL_USER must be set in a configuration file"
+ exit
+ fi
+ if [ -z "$CPANEL_PASS" ]; then
+ _err "= Error: CPANEL_PASS must be set in a configuration file"
+ exit
+ fi
+}
+
+_terminate () {
+ if [ -z "$ALARMPID" ]; then
+ kill $ALARMPID
+ fi
+ exit
+}
+
+_retreive_zone(){
+ _info "In _retreive_zone"
+ _debug "matching for: TXT $_sub_domain.$_domain."
+ REQUEST="GET /xml-api/cpanel?cpanel_xmlapi_module=ZoneEdit&cpanel_xmlapi_func=fetchzone&cpanel_xmlapi_apiversion=2&domain=$DOMAIN HTTP/1.0\r\nConnection: close\r\nAuthorization: Basic $AUTH_STRING\r\nUser-Agent: cpanel-dynamic-dns.sh $VERSION\r\n\r\n\r\n"
+ RECORD=""
+ LINES=""
+ INRECORD=0
+ USETHISRECORD=0
+ REQUEST_RESULTS=`echo -e "$REQUEST" | openssl s_client -quiet -connect $CPANEL_SERVER:2083 2>/dev/null`
+
+ _check_results_for_error "$REQUEST_RESULTS" "$REQUEST"
+ for LINE in $REQUEST_RESULTS
+ do
+ #_debug "$LINE"
+ if [ "$LINE" == "" ]; then
+ INRECORD=1
+ continue
+ fi
+ if [ "$LINE" == "" ]; then
+ INRECORD=0
+ if [ "$USETHISRECORD" == "2" ]; then
+ LINENUM=`echo -e "$RECORD" | grep '' | awk -F'<' '{print \$2}' | awk -F'>' '{print \$2}'`
+ TXT=`echo -e "$RECORD" | grep -i '' | awk -F'<' '{print \$2}' | awk -F'>' '{print \$2}'`
+ LINES="$LINES\n$LINENUM=$TXT"
+ fi
+ USETHISRECORD=0
+ RECORD=""
+ continue
+ fi
+ if [ "$LINE" == "TXT" ]; then
+ _debug "Match TXT"
+ USETHISRECORD=`expr $USETHISRECORD + 1`
+ fi
+ if [ "$LINE" == "$_sub_domain.$_domain." ]; then
+ _debug "Match Domain"
+ USETHISRECORD=`expr $USETHISRECORD + 1`
+ fi
+ if [ "$INRECORD" == "1" ]; then
+ RECORD="$RECORD\n$LINE"
+ fi
+ done
+}
+
+_parse_zone_lines(){
+ #_info "In _parse_zone_lines"
+ #_debug "$LINES"
+ for LINE in `echo -e $LINES`
+ do
+ _debug "Removing Validation TXT"
+ LINENUM=`echo $LINE | awk -F= '{print $1}'`
+ REQUEST="GET /xml-api/cpanel?cpanel_xmlapi_module=ZoneEdit&cpanel_xmlapi_func=remove_zone_record&cpanel_xmlapi_apiversion=2&domain=$DOMAIN&line=$LINENUM HTTP/1.0\r\nConnection: close\r\nAuthorization: Basic $AUTH_STRING\r\nUser-Agent: cpanel-dynamic-dns.sh $VERSION\r\n\r\n\r\n"
+ RESULT=`echo -e "$REQUEST" | openssl s_client -quiet -connect $CPANEL_SERVER:2083 2>&1`
+ _check_results_for_error "$RESULT" "$REQUEST"
+ done
+}
+
+_check_results_for_error ()
+{
+ REQUEST_RESULTS="$1"
+ REQUEST="$2"
+ if [ "`echo $REQUEST_RESULTS | grep '1'`" ]; then
+ if [ "$QUIET" != "1" ]; then
+ echo -n "success..."
+ fi
+ else
+ INREASON=0
+ INSTATUSMSG=0
+ MSG=""
+ STATUSMSG=""
+
+ for LINE in $REQUEST_RESULTS
+ do
+ if [ "`echo $LINE | grep ''`" != "" ]; then
+ INREASON=1
+ INSTATUSMSG=0
+ MSG=`echo $LINE | awk -F'>' '{print \$2}'`
+ continue
+ fi
+ if [ "`echo $LINE | grep ''`" != "" ]; then
+ INREASON=0
+ MSGADD=`echo $LINE | awk -F'<' '{print \$1}'`
+ MSG="$MSG $MSGADD"
+ continue
+ fi
+ if [ "`echo $LINE | grep ''`" != "" ]; then
+ INSTATUSMSG=1
+ INREASON=0
+ STATUSMSG=`echo $LINE | awk -F'>' '{print \$2}'`
+ continue
+ fi
+ if [ "`echo $LINE | grep ''`" != "" ]; then
+ INSTATUSMSG=0
+ MSGADD=`echo $LINE | awk -F'<' '{print \$1}'`
+ STATUSMSG="$STATUSMSG $MSGADD"
+ continue
+ fi
+ if [ "$INREASON" -eq "1" ]; then
+ MSG="$MSG $LINE"
+ fi
+ if [ "$INSTATUSMSG" -eq "1" ]; then
+ STATUSMSG="$STATUSMSG $LINE"
+ fi
+
+ done
+
+ if [ -z "$MSG" ]; then
+ MSG="Unknown Error"
+ if [ -z "$STATUSMSG" ]; then
+ STATUSMSG="Please make sure you have the zoneedit, or simplezone edit permission on your account."
+ fi
+ fi
+
+ _err "Request failed with error: $MSG ($STATUSMSG)"
+
+ _terminate
+ fi
+}