Automating Dynamic DNS Updates with Cloudflare API & PowerShell

Published on June 13, 2025 Network Administration

One of the ongoing challenges of running self-hosted services on a residential internet connection is dealing with dynamic public IP addresses. Since my ISP doesn't provide a static IP, my public IP changes periodically, which used to cause downtime on arran.cc whenever DNS records became stale.

Cloudflare hosts my DNS zone for arran.cc, and thankfully they offer a solid API that can be leveraged to automate DNS updates. This post walks through how I solved this problem using a simple PowerShell script and scheduled task to keep my A records accurate.

Why This Change Was Needed

Whenever my ISP changed my WAN IP, visitors would hit the wrong IP address and fail to reach my web server. Manually updating the Cloudflare A record every time wasn't scalable or reliable, so automation was the obvious solution.

Solution Overview

I wrote a PowerShell script that:

The PowerShell Script

Here's a high-level look at the script logic:

# Load Cloudflare credentials
$apiToken = "CLOUDFLARE_API_TOKEN"
$zoneID = "ZONE_ID"
$recordID = "RECORD_ID"
$dnsName = "arran.cc"

# Get current public IP
$currentIP = (Invoke-RestMethod -Uri "https://api.ipify.org").Content

# Get existing DNS record details
$dnsRecord = Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones/$zoneID/dns_records/$recordID" `
    -Headers @{ "Authorization" = "Bearer $apiToken" }

# Compare and update if necessary
if ($dnsRecord.result.content -ne $currentIP) {
    Invoke-RestMethod -Uri "https://api.cloudflare.com/client/v4/zones/$zoneID/dns_records/$recordID" `
        -Method PUT `
        -Headers @{ "Authorization" = "Bearer $apiToken" } `
        -Body (@{
            type = "A"
            name = $dnsName
            content = $currentIP
            ttl = 120
            proxied = $dnsRecord.result.proxied
        } | ConvertTo-Json -Depth 10)

    Write-Output "DNS record updated to $currentIP"
} else {
    Write-Output "No change needed"
}

(For obvious reasons, I've redacted my actual API credentials and IDs.)

Automation via Task Scheduler

To make sure this runs regularly, I set up a scheduled task on homenet-web-01 to execute the script every hour. This ensures my DNS record stays accurate even if the IP changes unexpectedly.

Validation & Testing

I tested the script by forcibly changing my router WAN IP (via reboot) and confirmed that the Cloudflare record updated automatically within minutes of the change being detected.

References

Closing Thoughts

This was a simple but very effective fix to what could have been an ongoing pain point. Thanks to the flexibility of Cloudflare's API and the scripting power of PowerShell, I now have a self-healing DNS setup that keeps my home lab online and accessible even with dynamic IPs.