Mass update Cloudflare target IP on multiple domains

By.

min read

My profile

Share this:
#!/bin/bash
CF_TOKEN=""
OLD_IP="1.2.3.4"
NEW_IP="222.222.222.222"
CF_API="https://api.cloudflare.com/client/v4"

# Function to fetch all zones using pagination
fetch_all_zones() {
    page=1
    per_page=50
    while :; do
        response=$(curl -s -G "$CF_API/zones" \
            -H "Authorization: Bearer $CF_TOKEN" \
            -H "Content-Type: application/json" \
            --data-urlencode "page=$page" \
            --data-urlencode "per_page=$per_page")
        
        echo "$response" | jq -r '.result[] | [.id, .name] | @tsv'

        total_pages=$(echo "$response" | jq -r '.result_info.total_pages')
        if [[ "$page" -ge "$total_pages" ]]; then break; fi
        page=$((page + 1))
    done
}

# Function to fetch all DNS records for a zone using pagination
fetch_all_records() {
    local zone_id="$1"
    page=1
    per_page=100
    while :; do
        response=$(curl -s -G "$CF_API/zones/$zone_id/dns_records" \
            -H "Authorization: Bearer $CF_TOKEN" \
            -H "Content-Type: application/json" \
            --data-urlencode "page=$page" \
            --data-urlencode "per_page=$per_page")

        echo "$response" | jq -r --arg OLD_IP "$OLD_IP" '
            .result[] 
            | select(.content == $OLD_IP) 
            | [.id, .name, .type, .ttl, .proxied] 
            | @tsv'

        total_pages=$(echo "$response" | jq -r '.result_info.total_pages')
        if [[ "$page" -ge "$total_pages" ]]; then break; fi
        page=$((page + 1))
    done
}

# Main logic
fetch_all_zones | while IFS=$'\t' read -r ZONE_ID ZONE_NAME; do
    echo "🔍 Checking zone: $ZONE_NAME"

    fetch_all_records "$ZONE_ID" | while IFS=$'\t' read -r RECORD_ID RECORD_NAME RECORD_TYPE RECORD_TTL RECORD_PROXIED; do
        echo "➡️ Updating $RECORD_NAME ($RECORD_TYPE) in $ZONE_NAME"

        update_payload=$(jq -n \
            --arg type "$RECORD_TYPE" \
            --arg name "$RECORD_NAME" \
            --arg content "$NEW_IP" \
            --argjson ttl "$RECORD_TTL" \
            --argjson proxied "$RECORD_PROXIED" \
            '{type: $type, name: $name, content: $content, ttl: $ttl, proxied: $proxied}')

        response=$(curl -s -X PUT "$CF_API/zones/$ZONE_ID/dns_records/$RECORD_ID" \
            -H "Authorization: Bearer $CF_TOKEN" \
            -H "Content-Type: application/json" \
            --data "$update_payload")

        if [[ $(echo "$response" | jq -r '.success') == "true" ]]; then
            echo "✅ Updated $RECORD_NAME"
        else
            echo "❌ Failed to update $RECORD_NAME"
            echo "$response"
        fi
    done
done
Share this:

Leave a Reply

Your email address will not be published. Required fields are marked *