Skip to content

Instantly share code, notes, and snippets.

@bouroo
Last active July 8, 2025 08:53
Show Gist options
  • Select an option

  • Save bouroo/b2273e7e7adbde61bb0fd3a7ad6cc074 to your computer and use it in GitHub Desktop.

Select an option

Save bouroo/b2273e7e7adbde61bb0fd3a7ad6cc074 to your computer and use it in GitHub Desktop.
Cloudflare bash add Sites/DNS record
#!/usr/bin/env bash
# Require curl & jq
hash curl 2>/dev/null || { echo >&2 "I require 'curl' but it's not installed. Aborting."; exit 1; }
hash jq 2>/dev/null || { echo >&2 "I require 'jq' but it's not installed. Aborting."; exit 1; }
# Get domain list
read -e -i 'domains.csv' -p 'Domain list file: ' DOMAIN_FILE
read -e -i 'y' -p 'CF Proxy [Y/n]: ' CF_PROXY
if [[ ${CF_PROXY} =~ ^([yY][eE][sS]|[yY])+$ ]]
then
CF_PROXY="true"
else
CF_PROXY="false"
fi
# Loop through domains list file
while IFS=',' read -r DOMAIN_ITEM HOST_IP CF_API_EMAIL CF_API_KEY || [ -n "${HOST_IP}" ]; do
# Ignore header
if [[ ${DOMAIN_ITEM} != *"."* ]]
then
continue
fi
# Retrive user's ID
echo "Retrive user's ID"
ACC_OBJ=$(curl -s --http1.1 -X GET "https://api.cloudflare.com/client/v4/accounts" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json")
SUCCESS=$(echo ${ACC_OBJ} | jq -r '.success')
# Account not found
[[ ${SUCCESS} != "true" ]] && { echo "User Account not found" ; exit 1; }
ACC_ID=$(echo ${ACC_OBJ} | jq -r '.result[0].id')
ACC_NAME=$(echo ${ACC_OBJ} | jq -r '.result[0].name')
sleep 1
# Get Zone
echo "Zone Name: " ${DOMAIN_ITEM}
RESP=$(curl -s --http1.1 -X GET "https://api.cloudflare.com/client/v4/zones?name=${DOMAIN_ITEM}" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json")
SUCCESS=$(echo ${RESP} | jq -r '.success')
[[ ${SUCCESS} != "true" ]] && { echo "Zone not found" ; continue; }
ZONE_ID=$(echo ${RESP} | jq -r '.result[0].id')
[[ ${ZONE_ID} == "null" ]] && { echo "Zone not found" ; continue; }
echo "Zone ID: " ${ZONE_ID}
sleep 1
# Create DNS Record
echo "Add DNS: ${DOMAIN_ITEM} ${HOST_IP}"
DATA='{"type":"A","name":"'${DOMAIN_ITEM}'","content":"'${HOST_IP}'","proxied":'${CF_PROXY}'}'
RESP=$(curl -s --http1.1 -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json" \
--data ${DATA})
SUCCESS=$(echo ${RESP} | jq -r '.success')
if [ ${SUCCESS} == "true" ]
then
echo -e "Success: \e[32m${SUCCESS}\e[0m"
else
ERROR=$(echo ${RESP} | jq '.errors[]')
echo -e "Success: \e[31m${SUCCESS}\e[0m"
echo "Errors: ${ERROR}"
echo "Debug: " ${DATA}
# continue
fi
# WWW
echo "Add DNS: www.${DOMAIN_ITEM} ${HOST_IP}"
DOMAIN_ITEM="www.${DOMAIN_ITEM}"
DATA='{"type":"A","name":"'${DOMAIN_ITEM}'","content":"'${HOST_IP}'","proxied":'${CF_PROXY}'}'
RESP=$(curl -s --http1.1 -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json" \
--data ${DATA})
SUCCESS=$(echo ${RESP} | jq -r '.success')
sleep 1
if [ ${SUCCESS} == "true" ]
then
echo -e "Success: \e[32m${SUCCESS}\e[0m"
else
ERROR=$(echo ${RESP} | jq '.errors[]')
echo -e "Success: \e[31m${SUCCESS}\e[0m"
echo "Errors: ${ERROR}"
echo "Debug: " ${DATA}
continue
fi
sleep 10
done < ${DOMAIN_FILE}
exit 0
#!/usr/bin/env bash
# Require curl & jq
hash curl 2>/dev/null || { echo >&2 "I require 'curl' but it's not installed. Aborting."; exit 1; }
hash jq 2>/dev/null || { echo >&2 "I require 'jq' but it's not installed. Aborting."; exit 1; }
# Get domain list
read -e -i 'domains.csv' -p 'Domain list file: ' DOMAIN_FILE
read -e -i 'n' -p 'Automatically attempt to fetch existing DNS records [y/N]: ' CF_INIT
if [[ ${CF_INIT} =~ ^([yY][eE][sS]|[yY])+$ ]]
then
CF_INIT="true"
else
CF_INIT="false"
fi
# Loop through domains list file
while IFS=',' read -r DOMAIN_ITEM HOST_IP CF_API_EMAIL CF_API_KEY || [ -n "${HOST_IP}" ]; do
# Ignore header
if [[ ${DOMAIN_ITEM} != *"."* ]]
then
continue
fi
# Retrive user's ID
echo "Retrive user's ID"
ACC_OBJ=$(curl -s --http1.1 -X GET "https://api.cloudflare.com/client/v4/accounts" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json")
SUCCESS=$(echo ${ACC_OBJ} | jq -r '.success')
# Account not found
sleep 1
[[ ${SUCCESS} != "true" ]] && { echo "User Account not found" ; continue; }
ACC_ID=$(echo ${ACC_OBJ} | jq -r '.result[0].id')
ACC_NAME=$(echo ${ACC_OBJ} | jq -r '.result[0].name')
# Create Zone
echo "Add site: ${DOMAIN_ITEM}"
DATA='{"account":{"id":"'${ACC_ID}'"},"name":"'${DOMAIN_ITEM}'","jump_start":'${CF_INIT}'}'
RESP=$(curl -s --http1.1 -X POST "https://api.cloudflare.com/client/v4/zones" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json" \
--data ${DATA})
SUCCESS=$(echo ${RESP} | jq -r '.success')
sleep 1
if [[ ${SUCCESS} == "true" ]]
then
echo -e "Success: \e[32m${SUCCESS}\e[0m"
NS=$(echo ${RESP} | jq -r '.result.name_servers[]')
echo "Name servers: " ${NS}
else
ERROR=$(echo ${RESP} | jq '.errors[]')
echo -e "Success: \e[31m${SUCCESS}\e[0m"
echo "Errors: ${ERROR}"
echo "Debug: " ${DATA}
continue
fi
sleep 8
done < ${DOMAIN_FILE}
exit 0
#!/usr/bin/env bash
# Require curl & jq
hash curl 2>/dev/null || { echo >&2 "I require 'curl' but it's not installed. Aborting."; exit 1; }
hash jq 2>/dev/null || { echo >&2 "I require 'jq' but it's not installed. Aborting."; exit 1; }
# Get user infos
read -p 'Email: ' CF_API_EMAIL
read -sp 'API Key: ' CF_API_KEY
echo
# Retrive user's ID
echo "Retrive user's ID"
ACC_OBJ=$(curl -s --http1.1 -X GET "https://api.cloudflare.com/client/v4/accounts" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json")
SUCCESS=$(echo ${ACC_OBJ} | jq -r '.success')
# Account not found
[[ ${SUCCESS} != "true" ]] && { echo "User Account not found" ; exit 1; }
ACC_ID=$(echo ${ACC_OBJ} | jq -r '.result[0].id')
ACC_NAME=$(echo ${ACC_OBJ} | jq -r '.result[0].name')
# Get Zone
echo "Retrive user's zone"
ZONE_OBJ=$(curl -s --http1.1 -X GET "https://api.cloudflare.com/client/v4/zones" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json")
SUCCESS=$(echo ${ZONE_OBJ} | jq -r '.success')
# Zone not found
[[ ${SUCCESS} != "true" ]] && { echo "Zone not found" ; exit 1; }
echo "Zone details"
echo -e "Email:\t" ${CF_API_EMAIL}
echo -e "Pass:\t "
echo "API Key:" ${CF_API_KEY}
echo -e "NS1:\t" $(echo ${ZONE_OBJ} | jq -r '.result[0].name_servers[0]')
echo -e "NS2:\t" $(echo ${ZONE_OBJ} | jq -r '.result[0].name_servers[1]')
echo "--------------------"
for ZONE in $(echo ${ZONE_OBJ} | jq -r '.result[] | @base64'); do
ZONE_ID=$(echo ${ZONE} | base64 --decode | jq -r '.id')
# Get dns
SITE_OBJ=$(curl -s --http1.1 -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?type=A" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json")
SUCCESS=$(echo ${SITE_OBJ} | jq -r '.success')
# dns not found
[[ ${SUCCESS} != "true" ]] && { echo "DNS not found" ; exit 1; }
for SITE in $(echo ${SITE_OBJ} | jq -r '.result[] | @base64'); do
echo -e "Domain:\t" $(echo ${SITE} | base64 --decode | jq -r '.name')
echo -e "IP:\t" $(echo ${SITE} | base64 --decode | jq -r '.content')
done
echo "--------------------"
done
exit 0
#!/usr/bin/env bash
# Require curl & jq
hash curl 2>/dev/null || { echo >&2 "I require 'curl' but it's not installed. Aborting."; exit 1; }
hash jq 2>/dev/null || { echo >&2 "I require 'jq' but it's not installed. Aborting."; exit 1; }
# Get domain list
read -e -i 'domains.csv' -p 'Domain list file: ' DOMAIN_FILE
read -e -i 'y' -p 'CF Proxy [Y/n]: ' CF_PROXY
if [[ ${CF_PROXY} =~ ^([yY][eE][sS]|[yY])+$ ]]
then
CF_PROXY="true"
else
CF_PROXY="false"
fi
# Loop through domains list file
while IFS=$' \t\n\r' read -r DOMAIN_ITEM HOST_IP
do
# Ignore header
if [[ ${DOMAIN_ITEM} != *"."* ]]
then
continue
fi
# Retrive user's ID
echo "Retrive user's ID"
ACC_OBJ=$(curl -s --http1.1 -X GET "https://api.cloudflare.com/client/v4/accounts" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json")
SUCCESS=$(echo ${ACC_OBJ} | jq -r '.success')
# Account not found
[[ ${SUCCESS} != "true" ]] && { echo "User Account not found" ; exit 1; }
ACC_ID=$(echo ${ACC_OBJ} | jq -r '.result[0].id')
ACC_NAME=$(echo ${ACC_OBJ} | jq -r '.result[0].name')
sleep 1
# Get Zone
echo "Zone Name: " ${DOMAIN_ITEM}
RESP=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=${DOMAIN_ITEM}" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json")
SUCCESS=$(echo ${RESP} | jq -r '.success')
[[ ${SUCCESS} != "true" ]] && { echo "Zone not found" ; continue; }
ZONE_ID=$(echo ${RESP} | jq -r '.result[0].id')
[[ ${ZONE_ID} == "null" ]] && { echo "Zone not found" ; continue; }
echo "Zone ID: " ${ZONE_ID}
sleep 1
# Get DNS Records
echo "Get record: ${DOMAIN_ITEM}"
DATA='{"name":"'${DOMAIN_ITEM}'"}'
RESP=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json" \
--data ${DATA})
SUCCESS=$(echo ${RESP} | jq -r '.success')
if [ ${SUCCESS} == "true" ]
then
echo -e "Success: \e[32m${SUCCESS}\e[0m"
else
ERROR=$(echo ${RESP} | jq '.errors[]')
echo -e "Success: \e[31m${SUCCESS}\e[0m"
echo "Errors: ${ERROR}"
echo "Debug: " ${DATA}
# continue
fi
REC_ID=$(echo ${RESP} | jq -r '.result[0].id')
REC_TYPE=$(echo ${RESP} | jq -r '.result[0].type')
echo "Record ID: " ${REC_ID}
# Update DNS Record
echo "Update DNS: ${DOMAIN_ITEM} ${HOST_IP}"
DATA='{"type":"'${REC_TYPE}'","name":"'${DOMAIN_ITEM}'","content":"'${HOST_IP}'","proxied":'${CF_PROXY}'}'
RESP=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${REC_ID}" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json" \
--data ${DATA})
SUCCESS=$(echo ${RESP} | jq -r '.success')
if [ ${SUCCESS} == "true" ]
then
echo -e "Success: \e[32m${SUCCESS}\e[0m"
else
ERROR=$(echo ${RESP} | jq '.errors[]')
echo -e "Success: \e[31m${SUCCESS}\e[0m"
echo "Errors: ${ERROR}"
echo "Debug: " ${DATA}
# continue
fi
# Get WWW DNS Records
DOMAIN_ITEM="www.${DOMAIN_ITEM}"
echo "Get record: ${DOMAIN_ITEM}"
DATA='{"name":"'${DOMAIN_ITEM}'"}'
RESP=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json" \
--data ${DATA})
SUCCESS=$(echo ${RESP} | jq -r '.success')
if [ ${SUCCESS} == "true" ]
then
echo -e "Success: \e[32m${SUCCESS}\e[0m"
else
ERROR=$(echo ${RESP} | jq '.errors[]')
echo -e "Success: \e[31m${SUCCESS}\e[0m"
echo "Errors: ${ERROR}"
echo "Debug: " ${DATA}
# continue
fi
REC_ID=$(echo ${RESP} | jq -r '.result[0].id')
REC_TYPE=$(echo ${RESP} | jq -r '.result[0].type')
echo "Record ID: " ${REC_ID}
# Update WWW record
echo "Update DNS: ${DOMAIN_ITEM} ${HOST_IP}"
DATA='{"type":"'${REC_TYPE}'","name":"'${DOMAIN_ITEM}'","content":"'${HOST_IP}'","proxied":'${CF_PROXY}'}'
RESP=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${REC_ID}" \
-H "X-Auth-Email: ${CF_API_EMAIL}" \
-H "X-Auth-Key: ${CF_API_KEY}" \
-H "Content-Type: application/json" \
--data ${DATA})
SUCCESS=$(echo ${RESP} | jq -r '.success')
sleep 1
if [ ${SUCCESS} == "true" ]
then
echo -e "Success: \e[32m${SUCCESS}\e[0m"
else
ERROR=$(echo ${RESP} | jq '.errors[]')
echo -e "Success: \e[31m${SUCCESS}\e[0m"
echo "Errors: ${ERROR}"
echo "Debug: " ${DATA}
continue
fi
sleep 5
done < ${DOMAIN_FILE}
exit 0
domain1.com ip1 cf1@email.com cf_key1
domain2.net ip2 cf2@email.com cf_key2
domain3.io ip3 cf3@email.com cf_key3
domainX.xyz ipX cfx@email.com cf_keyx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment