Table of Contents
How to Delete Addon Domains in cPanel with a Script (Maps, Confirms, and Continues on Errors)
This guide shows how to delete addon domains in cPanel with a script that first prints an addon domain → associated subdomain map, asks for confirmation, then deletes both names while continuing on errors. It uses UAPI to discover relationships and whmapi1 to perform deletions.
Why this approach
- Discovery with UAPI:
DomainInfo::domains_dataexposes each addon domain and its associated subdomain (servername). - Deletion with WHM API 1:
delete_domainremoves a domain. The script explicitly deletes the addon domain and then its linked subdomain. - Safe flow: Print the mapping, confirm with
y/n, proceed, and never abort the run on a failed deletion.
Prerequisites
- Run as root on the cPanel server.
- Tools installed and on
PATH:uapi,whmapi1,jq. - The target cPanel username and a file listing addon domains to remove.
Create your domain list
Save the domains (one per line) to a file (comments allowed):
# /root/addons.txt
addon1.com
addon2.net
# lines starting with # are ignored
The bash script
The script prints the map, asks for confirmation, deletes the addon domain and its associated subdomain, and logs failures without stopping.
#!/usr/bin/env bash
set -euo pipefail
CPUSER="cpanel_username" # target cPanel user
DOMAINS_FILE="/root/addons.txt" # one addon domain per line
need(){ command -v "$1" >/dev/null 2>&1 || { echo "Missing: $1"; exit 1; }; }
need uapi; need whmapi1; need jq
echo "Collecting domain data for user: $CPUSER ..."
json="$(uapi --user "$CPUSER" DomainInfo domains_data format=list --output=json)"
# Build map: addon_domain -> associated subdomain (servername)
declare -A ADDON2SUB
while IFS= read -r row; do
addon=$(jq -r '.domain' <<<"$row")
sub=$(jq -r '.servername' <<<"$row")
ADDON2SUB["$addon"]="$sub"
done < <(jq -c '.result.data[] | select(.type=="addon_domain")' <<<"$json")
echo
echo "Mapped addon domains and their associated subdomains:"
echo "------------------------------------------------------"
declare -a TARGETS=()
while IFS= read -r addon || [[ -n "$addon" ]]; do
[[ -z "$addon" || "$addon" =~ ^# ]] && continue
TARGETS+=("$addon")
sub="${ADDON2SUB[$addon]:-<not found>}"
printf "%-30s -> %s\n" "$addon" "$sub"
done < "$DOMAINS_FILE"
echo "------------------------------------------------------"
echo
read -rp "Proceed with deletion? (y/n): " ans
[[ "$ans" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 0; }
# --- deletion helpers (continue on error) ---
declare -a FAILS=()
del_domain() {
local user="$1" name="$2"
# prevent set -e from killing the script on failure
set +e
out="$(whmapi1 delete_domain user="$user" domain="$name" 2>&1)"
rc=$?
set -e
if [[ $rc -ne 0 ]]; then
echo "ERROR deleting '$name' (rc=$rc): ${out%%$'\n'*}"
FAILS+=("$name")
return 1
fi
echo "Deleted: $name"
return 0
}
# Perform deletions (continue on errors)
for addon in "${TARGETS[@]}"; do
sub="${ADDON2SUB[$addon]:-}"
echo "Deleting addon: $addon"
if ! del_domain "$CPUSER" "$addon"; then
# Skip subdomain if addon delete failed
continue
fi
if [[ -n "$sub" ]]; then
echo "Deleting associated subdomain: $sub"
del_domain "$CPUSER" "$sub" || true
else
echo "WARNING: No associated subdomain found for $addon"
fi
done
echo
if ((${#FAILS[@]})); then
echo "Completed with errors on ${#FAILS[@]} item(s):"
printf ' - %s\n' "${FAILS[@]}"
exit 1
else
echo "Completed without deletion errors."
fi
How to run
- Update
CPUSERand verifyDOMAINS_FILEpath. - Save the script, make it executable:
chmod +x delete-addons.sh. - Run as root:
./delete-addons.sh. - Review the printed map, enter
yto proceed.
Troubleshooting
- JSON parse errors from whmapi1: If your environment injects HTTP headers that confuse
whmapi1, switch the deletion calls tocurlagainst/json-api/delete_domainand parse the JSON response withjq. - Permissions: Ensure you are root and that the account exists. Check
/usr/local/cpanel/logs/error_logif deletions fail. - SSL certs: If you manage custom certs, remove or reissue certs that referenced the deleted names to avoid stale SANs.
Security and safety notes
- Always review the map before confirming.
- Back up vhost configs or home directories if you need to preserve content or settings related to the domains.
FAQ
Does deleting an addon domain also remove its associated subdomain?
No. The script deletes the addon domain and then explicitly deletes the associated subdomain identified via servername.
Why use UAPI for discovery and WHM API 1 for deletion?
UAPI exposes detailed domain metadata per account. WHM API 1 provides the delete_domain action required for removals.
What happens if a deletion fails?
The script continues, logs the failure, and shows a summary at the end.
Will this remove website files?
Domain removal does not automatically delete arbitrary content in the user’s home directory. Verify and clean up files as needed.
Can I dry run?
Yes. Run the script and abort at the confirmation prompt after reviewing the printed map.