Getting a the Cloudflare API Token
When updating the Cloudflare dynamic DNS record programmatically, your script must authenticate itself to the Cloudflare API. Only then will Cloudflare allow you to make changes to the DNS records in your account.
Cloudflare allows you to create API tokens with enough permissions for its purpose. In turn, you can then use your Cloudflare account’s username and the resulting API token to authenticate with the Cloudflare API.
To create a Cloudflare API Token, follow these steps.
- Open your browser, navigate to https://dash.cloudflare.com/login/, and log in to your Cloudflare account.
- After logging in to the Cloudflare dashboard, click on the profile button on the upper-right corner and click My Profile.
- Next, click the API Tokens tab link. Under the API Tokens section, click the Create Token button. The example below assumes that you have not created any API tokens yet.
- On the list of API token templates, click the Edit zone DNS template to use it. This template allows you to create an API token with edit permission to all or selected DNS zones in your account.
- Under the Zone Resources section on the Create Token page, click the right-most dropdown box and select the DNS zone to include in this API token’s access. After choosing the DNS zone, click Continue to summary.
- Review the summary and ensure that the API has DNS:Edit permission to the previously selected DNS zone. Finally, click Create Token to create the API token.
- After creating the API token, copy the token value and make sure to store it securely. Treat the API token like how you would treat a password
Copy the script below, paste it into your PowerShell code editor, and save the file. Refer to the inline comments to understand what the script does.
#requires -Version 7.1
[cmdletbinding()]
param (
[parameter(Mandatory)]
$Email,
[parameter(Mandatory)]
$Token,
[parameter(Mandatory)]
$Domain,
[parameter(Mandatory)]
$Record
)
# Build the request headers once. These headers will be used throughout the script.
$headers = @{
"X-Auth-Email" = $($Email)
"Authorization" = "Bearer $($Token)"
"Content-Type" = "application/json"
}
#Region Token Test
## This block verifies that your API key is valid.
## If not, the script will terminate.
$uri = "https://api.cloudflare.com/client/v4/user/tokens/verify"
$auth_result = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers -SkipHttpErrorCheck
if (-not($auth_result.result)) {
Write-Output "API token validation failed. Error: $($auth_result.errors.message). Terminating script."
# Exit script
return
}
Write-Output "API token validation [$($Token)] success. $($auth_result.messages.message)."
#EndRegion
#Region Get Zone ID
## Retrieves the domain's zone identifier based on the zone name. If the identifier is not found, the script will terminate.
$uri = "https://api.cloudflare.com/client/v4/zones?name=$($Domain)"
$DnsZone = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers -SkipHttpErrorCheck
if (-not($DnsZone.result)) {
Write-Output "Search for the DNS domain [$($Domain)] return zero results. Terminating script."
# Exit script
return
}
## Store the DNS zone ID
$zone_id = $DnsZone.result.id
Write-Output "Domain zone [$($Domain)]: ID=$($zone_id)"
#End Region
#Region Get DNS Record
## Retrieve the existing DNS record details from Cloudflare.
$uri = "https://api.cloudflare.com/client/v4/zones/$($zone_id)/dns_records?name=$($Record)"
$DnsRecord = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers -SkipHttpErrorCheck
if (-not($DnsRecord.result)) {
Write-Output "Search for the DNS record [$($Record)] return zero results. Terminating script."
# Exit script
return
}
## Store the existing IP address in the DNS record
$old_ip = $DnsRecord.result.content
## Store the DNS record type value
$record_type = $DnsRecord.result.type
## Store the DNS record id value
$record_id = $DnsRecord.result.id
## Store the DNS record ttl value
$record_ttl = $DnsRecord.result.ttl
## Store the DNS record proxied value
$record_proxied = $DnsRecord.result.proxied
Write-Output "DNS record [$($Record)]: Type=$($record_type), IP=$($old_ip)"
#EndRegion
#Region Get Current Public IP Address
$new_ip = Invoke-RestMethod -Uri 'https://mine.wallaceho.com/php/ip_api.php'
Write-Output "Public IP Address: OLD=$($old_ip), NEW=$($new_ip)"
#EndRegion
#Region update Dynamic DNS Record
## Compare current IP address with the DNS record
## If the current IP address does not match the DNS record IP address, update the DNS record.
if ($new_ip -ne $old_ip) {
Write-Output "The current IP address does not match the DNS record IP address. Attempt to update."
## Update the DNS record with the new IP address
$uri = "https://api.cloudflare.com/client/v4/zones/$($zone_id)/dns_records/$($record_id)"
$body = @{
type = $record_type
name = $Record
content = $new_ip
ttl = $record_ttl
proxied = $record_proxied
} | ConvertTo-Json
$Update = Invoke-RestMethod -Method PUT -Uri $uri -Headers $headers -SkipHttpErrorCheck -Body $body
if (($Update.errors)) {
Write-Output "DNS record update failed. Error: $($Update[0].errors.message)"
## Exit script
return
}
Write-Output "DNS record update successful."
return ($Update.result)
}
else {
Write-Output "The current IP address and DNS record IP address are the same. There's no need to update."
}
#EndRegion
Now that you’ve saved the Cloudflare dynamic DNS update script, what’s next? Before deploying the script, testing whether its functionality works is essential. Running the script requires four details to be successful, and those are:
Email – which is the email address for your Cloudflare account.
Token – the API token that you previously created from your Cloudflare account.
Domain – the DNS domain name that contains the DNS record you want to update. (e.g., abc.com).
Record – the DNS record you want to update. (e.g., wallace.abc.com).