Cloudflare Dynamic DNS

If you want to use and old computer as a dynamic DNS client to update you IP you can easily do it using the Cloudflare API and a Debian minimal install.

First install the API with:

pip install cloudflare

After create a file somewhere with the code bellow, changing lines 105, 109, 110 and 115 as required.

#!/usr/bin/env python3
"""Cloudflare API code - example"""

from __future__ import print_function

import os
import sys
import re
import json
import requests

sys.path.insert(0, os.path.abspath('..'))
import CloudFlare

def my_ip_address():
    """Cloudflare API code - example"""

    # This list is adjustable - plus some v6 enabled services are needed
    # url = ''
    # url = ''
    # url = ''
    url = ''
        ip_address = requests.get(url).text
        exit('%s: failed' % (url))
    if ip_address == '':
        exit('%s: failed' % (url))

    if ':' in ip_address:
        ip_address_type = 'AAAA'
        ip_address_type = 'A'

    return ip_address, ip_address_type

def do_dns_update(cf, zone_name, zone_id, dns_name, ip_address, ip_address_type):
    """Cloudflare API code - example"""

        params = {'name': dns_name, 'match': 'all', 'type': ip_address_type}
        dns_records = cf.zones.dns_records.get(zone_id, params=params)
    except CloudFlare.exceptions.CloudFlareAPIError as e:
        exit('/zones/dns_records %s - %d %s - api call failed' % (dns_name, e, e))

    updated = False

    # update the record - unless it's already correct
    for dns_record in dns_records:
        old_ip_address = dns_record['content']
        old_ip_address_type = dns_record['type']

        if ip_address_type not in ['A', 'AAAA']:
            # we only deal with A / AAAA records

        if ip_address_type != old_ip_address_type:
            # only update the correct address type (A or AAAA)
            # we don't see this becuase of the search params above
            print('IGNORED: %s %s ; wrong address family' % (dns_name, old_ip_address))

        if ip_address == old_ip_address:
            print('UNCHANGED: %s %s' % (dns_name, ip_address))
            updated = True

        # Yes, we need to update this record - we know it's the same address type

        dns_record_id = dns_record['id']
        dns_record = {
            'name': dns_name,
            'type': ip_address_type,
            'content': ip_address
            dns_record = cf.zones.dns_records.put(zone_id, dns_record_id, data=dns_record)
        except CloudFlare.exceptions.CloudFlareAPIError as e:
            exit('/zones.dns_records.put %s - %d %s - api call failed' % (dns_name, e, e))
        print('UPDATED: %s %s -> %s' % (dns_name, old_ip_address, ip_address))
        updated = True

    if updated:

    # no exsiting dns record to update - so create dns record
    dns_record = {
        'name': dns_name,
        'type': ip_address_type,
        'content': ip_address
        dns_record =, data=dns_record)
    except CloudFlare.exceptions.CloudFlareAPIError as e:
        exit('/ %s - %d %s - api call failed' % (dns_name, e, e))
    print('CREATED: %s %s' % (dns_name, ip_address))

def main():
    """Cloudflare API code - example"""

        dns_name = ""
    except IndexError:
        exit('args missing: fqdn-hostname')

    host_name = "YOUR.SUBDOMAIN"
    zone_name = "YOUR.MAIN.DOMAIN.COM"
    ip_address, ip_address_type = my_ip_address()

    print('MY IP: %s %s' % (dns_name, ip_address))

    cf = CloudFlare.CloudFlare(email="[email protected]", token="CLOUDFLARE_TOKEN")

    # grab the zone identifier
        params = {'name': zone_name}
        zones = cf.zones.get(params=params)
    except CloudFlare.exceptions.CloudFlareAPIError as e:
        exit('/zones %d %s - api call failed' % (e, e))
    except Exception as e:
        exit('/zones.get - %s - api call failed' % (e))

    if len(zones) == 0:
        exit('/zones.get - %s - zone not found' % (zone_name))

    if len(zones) != 1:
        exit('/zones.get - %s - api call returned %d items' % (zone_name, len(zones)))

    zone = zones[0]

    zone_name = zone['name']
    zone_id = zone['id']

    do_dns_update(cf, zone_name, zone_id, dns_name, ip_address, ip_address_type)

if __name__ == '__main__':

You can test if everything is working by running:


If everything is alright, you can create an entry in the crontab database to run every X minutes so the script can keep you ip updated in case it changes