Using the Cloudflare API to Manage DNS Records

U

I’m probably doing Cloudflare a disservice by categorising it as a CDN provider, but that’s certainly one of the many services they offer and perhaps how most individuals using their free offering see them. Like me, I’m certain the vast majority of that group use the Cloudflare dashboard to configure their domains, but Cloudflare provides an API that allows you to programmatically manage those DNS records through a command-line interface of a Unix shell such as Bash.

The documentation states:

Using Cloudflare’s API, you can do just about anything you can do on cloudflare.com via the customer dashboard.

Although the Cloudflare API documentation gives numerous examples, it took me a while to get to grips with them, so I thought it may be useful for others if I document my examples.

To use the Cloudflare API you’ll need the email address used to login to your Cloudflare account and your Cloudlare account’s global API key.

Table of Contents

 

 

 

 

2. ABOUT THE CODE SAMPLES

2.1 Code

Below is an example of code used throughout this article together with the output if the request is successful and the output if unsuccessful:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="A"; \
NAME="example.com"; \
CONTENT="203.0.113.50"; \
PROXIED="true"; \
TTL="1"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","proxied":'"$PROXIED"',"ttl":'"$TTL"'}' \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": {
        "content": "203.0.113.50",
        "created_on": "2018-01-27T15:57:52.254408Z",
        "id": "02a929c163302fe6ad885e77ad7bd268",
        "locked": false,
        "meta": {
            "auto_added": false,
            "managed_by_apps": false
        },
        "modified_on": "2018-01-27T15:57:52.254408Z",
        "name": "example.com",
        "proxiable": true,
        "proxied": true,
        "ttl": 1,
        "type": "A",
        "zone_id": "8b717207bcee4047af2e9dff95832996",
        "zone_name": "example.com"
    },
    "success": true
}
{
    "errors": [
        {
            "code": 81057,
            "message": "The record already exists."
        }
    ],
    "messages": [],
    "result": null,
    "success": false
}

 

 

I’ve assigned certain values in the code to variables – EMAIL, KEY etc – to make it easier to see how this data is used throughout the code. Below is a sample DNS record on the Cloudflare customer dashboard together with a table summarising the variables used.

Cloudflare dashboard showing a single DNS record for example.com
Cloudflare dashboard showing a single DNS record for example.com

 

 

VariableValue
EMAILThe email address associated with your Cloudflare account.
KEYThe global API key associated with your Cloudflare account.
DOMAINThe name of the domain to create a zone record for.
JUMP_STARTIf true, automatically attempts to fetch existing DNS records when creating a domain’s zone record
ZONE_IDThe unique ID of the domain’s zone record. Assigned by Cloudflare. Required when managing an existing zone record and its DNS records.
DNS_IDThe unique ID given to each of the domain’s individual DNS records. Assigned by Cloudflare. Required when updating or deleting an existing DNS record.
TYPEThe DNS record type including A, CNAME, MX and TCXT ecords. This equates to the Type column on the Cloudflare dashboard.
NAMEThe DNS record name. This equates to the Name column on the Cloudflare dashboard.
CONTENTThe DNS record content. This equates to the Value column on the Cloudflare dashboard.
PROXIEDIf true, a DNS record will pass through Cloudflare’s servers. Un-proxied records will not and are for DNS resolution only. Applicable to A and CNAME records only. This equates to the Status column on the Cloudflare dashboard.
TTLValid TTL. Must be between 120 and 2,147,483,647 seconds, or 1 for automatic
PRIORITYThe order in which servers should be contacted. Applicable to MX records only.
ALLIf true, JSON output will be pretty-printed using Python’s json.tool module. Otherwise, output will be limited to specified data.

Variables Passed To The Cloudflare API

 

 

 

 

2.2 Output

All requests to Cloudflare’s API are made using HTTPS and return unformatted JSON data. To make this output readable, I’ve piped the JSON data through Python’s json.tool – a simple command line interface for the json module to pretty-print JSON objects. All key/value pairs are sorted alphabetically.

HTTPS requests to the API using the POST or DELETE methods return a JSON object containing 4 top-level key/value pairs. These keys are errors, messages, result and success. The values for these keys can be an empty array:

"errors": [],

 

…another object containing other key/value pairs:

"result": {
    "content": "203.0.113.50",
    "created_on": "2018-01-27T15:57:52.254408Z",
    ...
},

 

…or a boolean value:

"success": true

 

For HTTPS requests using GET, result key value objects are contained within an array:

"result": [
    {
    	...
        "id": "8b717207bcee4047af2e9dff95832996",
    	...
    }
],

 

 

In addition there is a fifth top-level key/value pair for the GET method named result_info whose value is an object containing other key/value pairs:

"result_info": {
    "count": 1,
    ...
},

 

 

 

 

2.3 Alternative Code and Output

Some requests to the Cloudflare API produce a lot of JSON data. As an alternative to the main code samples, I have provided alternative code whose output focuses on a particular piece of data – the unique ID of a domain’s DNS record for example. In the example below, the variable ALL is included and controls how JSON data is displayed. If ALL is true, JSON data is piped to Python’s json.tool as before. However, if false, only limited JSON data – as specified in the statements passed as a command to python – is displayed.

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="A"; \
NAME="example.com"; \
CONTENT="203.0.113.50"; \
PROXIED="true"; \
TTL="1"; \
ALL="false"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","proxied":'"$PROXIED"',"ttl":'"$TTL"'}' \
    | if $ALL; then python -m json.tool; else python -c "import sys,json;data=json.loads(sys.stdin.read()); print('Type: ' + data['result']['type'] + '\n' + 'DNS ID: ' + data['result']['id'] if data['success'] else 'ERROR: ' + data['errors'][0]['message'])"; fi
Type: A
DNS ID: 02a929c163302fe6ad885e77ad7bd268
ERROR: The record already exists.

 

 

 

 

3. ClOUDFLARE RESTRICTIONS

Adding DNS records on Cloudflare for a given domain will have no affect on where that domain’s DNS resolves until its nameservers are changed via the domain’s registrar to point to Cloudflare’s. As such, you should be able to use any domain name when experimenting with the Cloudflare API, but Cloudflare does impose some restrictions:

  • You can’t create DNS records for recognised domains like google.com, microsoft.com, example.com etc. Should you try, you’ll receive the error: This zone is banned and cannot be added to Cloudflare at this time. I’ve used example.com in all of my code examples, but this is purely illustrative.

  • The domain must be registered. You can’t use google.test, microsoft.invalid, example.localhost even though these TLDs have been reserved for testing and documentation purposes by the IETF (RFC 2606). The error message is We were unable to identify example.localhost as a registered domain.

  • A valid IP address is also required. Using 12.345.678.9 returns DNS Validation Error. I used 203.0.113.50 which is in a range of IP addresses which the IETF (RFC 5737) have reserved for testing and documentation purposes.

 

 

4. WORKING CODE EXAMPLES

Below is a screenshot of the Cloudflare dashboard showing DNS records for the domain example.com. We’ll create each of these DNS records using the Cloudflare API.

Cloudflare dashboard showing DNS records for example.com
Cloudflare dashboard showing DNS records for example.com

 

 

Each of the following code examples when executed from the command-line should do exactly as described, providing valid data is supplied for EMAIL, KEY and where applicable DOMAIN, ZONE_ID and DNS_ID.

All code examples were successfully tested using cURL 7.54.0 and Python 2.7.10 on macOS High Sierra 10.13.3 and cURL 7.47.0 and Python 2.7.12 on Ubuntu 16.04.3.

 

 

4.1 ZONE RECORDS

4.1.1 Create a New Zone Record for a Domain

In order to create DNS records for a domain, we first need to create a unique zone record for that domain to which we’ll later add these DNS records. To create a zone record for example.com, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
DOMAIN="example.com"; \
JUMP_START="false"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"name":"'"$DOMAIN"'","jump_start":'"$JUMP_START"'}' \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": {
        "account": {
            "id": "2b38766c25a309dc4906a2ca27b7951e",
            "name": "steve@example.com"
        },
        "created_on": "2018-01-27T17:21:09.947727Z",
        "development_mode": 0,
        "id": "8b717207bcee4047af2e9dff95832996",
        "meta": {
            "custom_certificate_quota": 0,
            "multiple_railguns_allowed": false,
            "page_rule_quota": 3,
            "phishing_detected": false,
            "step": 4,
            "wildcard_proxiable": false
        },
        "modified_on": "2018-01-27T17:21:09.947727Z",
        "name": "example.com",
        "name_servers": [
            "elsa.ns.cloudflare.com",
            "sid.ns.cloudflare.com"
        ],
        "original_dnshost": null,
        "original_name_servers": [
            "ns1.sedoparking.com",
            "ns2.sedoparking.com"
        ],
        "original_registrar": null,
        "owner": {
            "email": "steve@example.com",
            "id": "4ca324382cc5077590a1808267ebd523",
            "type": "user"
        },
        "paused": false,
        "permissions": [
            "#access:edit",
            "#access:read",
            "#analytics:read",
            "#app:edit",
            "#billing:edit",
            "#billing:read",
            "#cache_purge:edit",
            "#dns_records:edit",
            "#dns_records:read",
            "#lb:edit",
            "#lb:read",
            "#logs:read",
            "#member:edit",
            "#member:read",
            "#organization:edit",
            "#organization:read",
            "#ssl:edit",
            "#ssl:read",
            "#subscription:edit",
            "#subscription:read",
            "#waf:edit",
            "#waf:read",
            "#worker:edit",
            "#worker:read",
            "#zone:edit",
            "#zone:read",
            "#zone_settings:edit",
            "#zone_settings:read"
        ],
        "plan": {
            "can_subscribe": false,
            "currency": "USD",
            "externally_managed": false,
            "frequency": "",
            "id": "0daaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            "is_subscribed": true,
            "legacy_discount": false,
            "legacy_id": "free",
            "name": "Free Website",
            "price": 0
        },
        "status": "pending",
        "type": "full"
    },
    "success": true
}
{
    "errors": [
        {
            "code": 1061,
            "message": "example.com already exists"
        }
    ],
    "messages": [],
    "result": null,
    "success": false
}

 

 

Alternatively, to limit the data that is displayed use:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
DOMAIN="example.com"; \
JUMP_START="false"; \
ALL="false"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"name":"'"$DOMAIN"'","jump_start":'"$JUMP_START"'}' \
    | if $ALL; then python -m json.tool; else python -c "import sys,json;data=json.loads(sys.stdin.read()); print('ZONE_ID: ' + data['result']['id'] if data['success'] else 'ERROR: ' + data['errors'][0]['message'])"; fi
ZONE_ID: 8b717207bcee4047af2e9dff95832996
ERROR: example.com already exists

 

 

 

 

4.1.2 List an Existing Zone Record for a Domain

To display the existing zone record for example.com, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
DOMAIN="example.com"; \
curl -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": [
        {
            "account": {
            	"id": "2b38766c25a309dc4906a2ca27b7951e",
            	"name": "steve@example.com"
            },
            "created_on": "2018-01-27T17:39:39.206820Z",
            "development_mode": 0,
            "id": "8b717207bcee4047af2e9dff95832996",
            "meta": {
                "custom_certificate_quota": 0,
                "multiple_railguns_allowed": false,
                "page_rule_quota": 3,
                "phishing_detected": false,
                "step": 4,
                "wildcard_proxiable": false
            },
            "modified_on": "2018-01-27T17:39:39.206820Z",
            "name": "example.com",
            "name_servers": [
                "elsa.ns.cloudflare.com",
                "sid.ns.cloudflare.com"
            ],
            "original_dnshost": null,
            "original_name_servers": [
                "ns1.sedoparking.com",
                "ns2.sedoparking.com"
            ],
            "original_registrar": null,
            "owner": {
                "email": "steve@example.com",
                "id": "4ca324382cc5077590a1808267ebd523",
                "type": "user"
            },
            "paused": false,
            "permissions": [
                "#access:edit",
                "#access:read",
                "#analytics:read",
                "#app:edit",
                "#billing:edit",
                "#billing:read",
                "#cache_purge:edit",
                "#dns_records:edit",
                "#dns_records:read",
                "#lb:edit",
                "#lb:read",
                "#logs:read",
                "#member:edit",
                "#member:read",
                "#organization:edit",
                "#organization:read",
                "#ssl:edit",
                "#ssl:read",
                "#subscription:edit",
                "#subscription:read",
                "#waf:edit",
                "#waf:read",
                "#worker:edit",
                "#worker:read",
                "#zone:edit",
                "#zone:read",
                "#zone_settings:edit",
                "#zone_settings:read"
            ],
            "plan": {
                "can_subscribe": false,
                "currency": "USD",
                "externally_managed": false,
                "frequency": "",
                "id": "0daaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                "is_subscribed": true,
                "legacy_discount": false,
                "legacy_id": "free",
                "name": "Free Website",
                "price": 0
            },
            "status": "pending",
            "type": "full"
        }
    ],
    "result_info": {
        "count": 1,
        "page": 1,
        "per_page": 20,
        "total_count": 1,
        "total_pages": 1
    },
    "success": true
}
{
    "errors": [],
    "messages": [],
    "result": [],
    "result_info": {
        "count": 0,
        "page": 1,
        "per_page": 20,
        "total_count": 0,
        "total_pages": 0
    },
    "success": true
}

 

 

Alternatively, to limit the data that is displayed use:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
DOMAIN="example.com"; \
ALL="false"; \
curl -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    | if $ALL; then python -m json.tool; else python -c "import sys,json;data=json.loads(sys.stdin.read()); print 'ZONE_ID: ' + data['result'][0]['id'] if data['result'] else 'ERROR: Does a zone record for \"$DOMAIN\" exist?'"; fi
ZONE_ID: 8b717207bcee4047af2e9dff95832996
ERROR: Does a zone record for "example.com" exist?

 

 

 

 

4.1.3 Delete an Existing Zone Record for a Domain

To delete the existing zone record for example.com and all its related DNS records, use the following code. Note that we need to provide the unique ID of the domain’s existing zone record:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": {
        "id": "8b717207bcee4047af2e9dff95832996"
    },
    "success": true
}
{
    "errors": [
        {
            "code": 1001,
            "message": "Invalid zone identifier"
        }
    ],
    "messages": [],
    "result": null,
    "success": false
}

 

 

Alternatively, to limit the data that is displayed use:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
ALL="false"; \
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    | if $ALL; then python -m json.tool; else python -c "import sys,json;data=json.loads(sys.stdin.read()); print 'Zone for ID \"$ZONE_ID\" deleted.' if data['success'] else 'ERROR: ' + data['errors'][0]['message']"; fi
Zone for ID 8b717207bcee4047af2e9dff95832996 deleted.
ERROR: Invalid zone identifier

 

 

 

 

4.2 CREATE NEW DNS RECORDS

4.2.1 Create a New DNS [A] Record for a Domain

To create a DNS record that points example.com to the IP address 203.0.113.50, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="A"; \
NAME="example.com"; \
CONTENT="203.0.113.50"; \
PROXIED="true"; \
TTL="1"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","proxied":'"$PROXIED"',"ttl":'"$TTL"'}' \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": {
        "content": "203.0.113.50",
        "created_on": "2018-01-27T15:57:52.254408Z",
        "id": "02a929c163302fe6ad885e77ad7bd268",
        "locked": false,
        "meta": {
            "auto_added": false,
            "managed_by_apps": false
        },
        "modified_on": "2018-01-27T15:57:52.254408Z",
        "name": "example.com",
        "proxiable": true,
        "proxied": true,
        "ttl": 1,
        "type": "A",
        "zone_id": "8b717207bcee4047af2e9dff95832996",
        "zone_name": "example.com"
    },
    "success": true
}
{
    "errors": [
        {
            "code": 81057,
            "message": "The record already exists."
        }
    ],
    "messages": [],
    "result": null,
    "success": false
}

 

 

Alternatively, to limit the data that is displayed use:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="A"; \
NAME="example.com"; \
CONTENT="203.0.113.50"; \
PROXIED="true"; \
TTL="1"; \
ALL="false"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","proxied":'"$PROXIED"',"ttl":'"$TTL"'}' \
    | if $ALL; then python -m json.tool; else python -c "import sys,json;data=json.loads(sys.stdin.read()); print('Type: ' + data['result']['type'] + '\n' + 'DNS ID: ' + data['result']['id'] if data['success'] else 'ERROR: ' + data['errors'][0]['message'])"; fi
Type: A
DNS ID: 02a929c163302fe6ad885e77ad7bd268
ERROR: The record already exists.

 

 

The Cloudflare dashboard now shows:

Cloudflare dashboard showing the newly created A record for example.com
Cloudflare dashboard showing the newly created A record for example.com

 

 

 

 

4.2.2 Create a New DNS [A] Record for a Sub-domain

To create a DNS record that points sub-domain.example.com to the IP address 203.0.113.50, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="A"; \
NAME="sub-domain"; \
CONTENT="203.0.113.50"; \
PROXIED="true"; \
TTL="1"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","proxied":'"$PROXIED"',"ttl":'"$TTL"'}' \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": {
        "content": "203.0.113.50",
        "created_on": "2018-01-31T10:05:17.945648Z",
        "id": "1edaebfd2c02a69beec51da4476e743e",
        "locked": false,
        "meta": {
            "auto_added": false,
            "managed_by_apps": false
        },
        "modified_on": "2018-01-31T10:05:17.945648Z",
        "name": "sub-domain.example.com",
        "proxiable": true,
        "proxied": true,
        "ttl": 1,
        "type": "A",
        "zone_id": "8b717207bcee4047af2e9dff95832996",
        "zone_name": "example.com"
    },
    "success": true
}
{
    "errors": [
        {
            "code": 81057,
            "message": "The record already exists."
        }
    ],
    "messages": [],
    "result": null,
    "success": false
}

 

 

Alternatively, to limit the data that is displayed use:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="A"; \
NAME="sub-domain"; \
CONTENT="203.0.113.50"; \
PROXIED="true"; \
TTL="1"; \
ALL="false"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","proxied":'"$PROXIED"',"ttl":'"$TTL"'}' \
    | if $ALL; then python -m json.tool; else python -c "import sys,json;data=json.loads(sys.stdin.read()); print('Type: ' + data['result']['type'] + '\n' + 'DNS ID: ' + data['result']['id'] if data['success'] else 'ERROR: ' + data['errors'][0]['message'])"; fi
Type: A
DNS ID: 1edaebfd2c02a69beec51da4476e743e
ERROR: The record already exists.

 

 

The Cloudflare dashboard now shows:

Cloudflare dashboard showing the newly created A record for sub-domain.example.com
Cloudflare dashboard showing the newly created A record for sub-domain.example.com

 

 

 

 

4.2.3 Create a New DNS [CNAME] Record for an Alias

To create a DNS record that makes www.example.com an alias of example.com, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="CNAME"; \
NAME="www"; \
CONTENT="example.com"; \
PROXIED="true"; \
TTL="1"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","proxied":'"$PROXIED"',"ttl":'"$TTL"'}' \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": {
        "content": "example.com",
        "created_on": "2018-01-31T10:27:57.075092Z",
        "id": "7bdb2e46037df332e5abdd45f8f981f5",
        "locked": false,
        "meta": {
            "auto_added": false,
            "managed_by_apps": false
        },
        "modified_on": "2018-01-31T10:27:57.075092Z",
        "name": "www.example.com",
        "proxiable": true,
        "proxied": true,
        "ttl": 1,
        "type": "CNAME",
        "zone_id": "8b717207bcee4047af2e9dff95832996",
        "zone_name": "example.com"
    },
    "success": true
}
{
    "errors": [
        {
            "code": 81053,
            "message": "An A, AAAA or CNAME record already exists with that host."
        }
    ],
    "messages": [],
    "result": null,
    "success": false
}

 

 

Alternatively, to limit the data that is displayed use:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="CNAME"; \
NAME="www"; \
CONTENT="example.com"; \
PROXIED="true"; \
TTL="1"; \
ALL="false"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","proxied":'"$PROXIED"',"ttl":'"$TTL"'}' \
    | if $ALL; then python -m json.tool; else python -c "import sys,json;data=json.loads(sys.stdin.read()); print('Type: ' + data['result']['type'] + '\n' + 'DNS ID: ' + data['result']['id'] if data['success'] else 'ERROR: ' + data['errors'][0]['message'])"; fi
Type: CNAME
DNS ID: 7bdb2e46037df332e5abdd45f8f981f5
ERROR: An A, AAAA or CNAME record already exists with that host.

 

 

The Cloudflare dashboard now shows:

Cloudflare dashboard showing the newly created CNAME record for www.example.com
Cloudflare dashboard showing the newly created CNAME record for www.example.com

 

 

 

 

4.2.4 Create a New DNS [MX] Record for a Domain

To create a DNS record that specifies the primary mail server to handle mail for example.com, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="MX"; \
NAME="@"; \
CONTENT="aspmx.l.google.com"; \
PRIORITY="1"; \
TTL="1"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","priority":"'"$PRIORITY"'","ttl":'"$TTL"'}' \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": {
        "content": "aspmx.l.google.com",
        "created_on": "2018-01-31T10:36:15.396025Z",
        "id": "4983f68556095761d8f76af09f48b093",
        "locked": false,
        "meta": {
            "auto_added": false,
            "managed_by_apps": false
        },
        "modified_on": "2018-01-31T10:36:15.396025Z",
        "name": "example.com",
        "priority": 1,
        "proxiable": false,
        "proxied": false,
        "ttl": 1,
        "type": "MX",
        "zone_id": "8b717207bcee4047af2e9dff95832996",
        "zone_name": "example.com"
    },
    "success": true
}
{
    "errors": [
        {
            "code": 81057,
            "message": "The record already exists."
        }
    ],
    "messages": [],
    "result": null,
    "success": false
}

 

 

Alternatively, to limit the data that is displayed use:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="MX"; \
NAME="@"; \
CONTENT="aspmx.l.google.com"; \
PRIORITY="1"; \
TTL="1"; \
ALL="false"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","priority":"'"$PRIORITY"'","ttl":'"$TTL"'}' \
    | if $ALL; then python -m json.tool; else python -c "import sys,json;data=json.loads(sys.stdin.read()); print('Type: ' + data['result']['type'] + '\n' + 'DNS ID: ' + data['result']['id'] if data['success'] else 'ERROR: ' + data['errors'][0]['message'])"; fi
Type: MX
DNS ID: 4983f68556095761d8f76af09f48b093
ERROR: The record already exists.

 

 

The Cloudflare dashboard now shows:

Cloudflare dashboard showing newly created 1st MX record for example.com
Cloudflare dashboard showing the newly created 1st MX record for example.com

 

 

 

 

4.2.5 Create a Second New DNS [MX] Record for a Domain

To create a DNS record that specifies the secondary mail server to handle mail for example.com, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="MX"; \
NAME="@"; \
CONTENT="alt1.aspmx.l.google.com"; \
PRIORITY="5"; \
TTL="1"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","priority":"'"$PRIORITY"'","ttl":'"$TTL"'}' \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": {
        "content": "alt1.aspmx.l.google.com",
        "created_on": "2018-01-31T11:05:36.960561Z",
        "id": "6b21db8d6a20c0011971d4ec2c3b8445",
        "locked": false,
        "meta": {
            "auto_added": false,
            "managed_by_apps": false
        },
        "modified_on": "2018-01-31T11:05:36.960561Z",
        "name": "example.com",
        "priority": 1,
        "proxiable": false,
        "proxied": false,
        "ttl": 1,
        "type": "MX",
        "zone_id": "8b717207bcee4047af2e9dff95832996",
        "zone_name": "example.com"
    },
    "success": true
}
{
    "errors": [
        {
            "code": 81057,
            "message": "The record already exists."
        }
    ],
    "messages": [],
    "result": null,
    "success": false
}

 

 

Alternatively, to limit the data that is displayed use:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="MX"; \
NAME="@"; \
CONTENT="alt1.aspmx.l.google.com"; \
PRIORITY="5"; \
TTL="1"; \
ALL="false"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","priority":"'"$PRIORITY"'","ttl":'"$TTL"'}' \
    | if $ALL; then python -m json.tool; else python -c "import sys,json;data=json.loads(sys.stdin.read()); print('Type: ' + data['result']['type'] + '\n' + 'DNS ID: ' + data['result']['id'] if data['success'] else 'ERROR: ' + data['errors'][0]['message'])"; fi
Type: MX
DNS ID: 6b21db8d6a20c0011971d4ec2c3b8445
ERROR: The record already exists.

 

 

The Cloudflare dashboard now shows:

Cloudflare dashboard showing the newly created 2nd MX record for example.com
Cloudflare dashboard showing the newly created 2nd MX record for example.com

 

 

 

 

4.2.6 Create a New DNS [TXT] Record

To create a DNS record that specifies the sender policy framework (SPF) for example.com, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="TXT"; \
NAME="@"; \
CONTENT="v=spf1 include:_spf.google.com ~all"; \
TTL="1"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","ttl":'"$TTL"'}' \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": {
        "content": "v=spf1 include:_spf.google.com ~all",
        "created_on": "2018-01-31T11:13:04.971069Z",
        "id": "3c90b59fca40473f26d8edf4c7e5fdb1",
        "locked": false,
        "meta": {
            "auto_added": false,
            "managed_by_apps": false
        },
        "modified_on": "2018-01-31T11:13:04.971069Z",
        "name": "example.com",
        "proxiable": false,
        "proxied": false,
        "ttl": 1,
        "type": "TXT",
        "zone_id": "8b717207bcee4047af2e9dff95832996",
        "zone_name": "example.com"
    },
    "success": true
}
{
    "errors": [
        {
            "code": 81057,
            "message": "The record already exists."
        }
    ],
    "messages": [],
    "result": null,
    "success": false
}

 

 

Alternatively, to limit the data that is displayed use:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="TXT"; \
NAME="@"; \
CONTENT="v=spf1 include:_spf.google.com ~all"; \
TTL="1"; \
ALL="1"; \
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","ttl":'"$TTL"'}' \
    | if $ALL; then python -m json.tool; else python -c "import sys,json;data=json.loads(sys.stdin.read()); print('Type: ' + data['result']['type'] + '\n' + 'DNS ID: ' + data['result']['id'] if data['success'] else 'ERROR: ' + data['errors'][0]['message'])"; fi
Type: TXT
DNS ID: 3c90b59fca40473f26d8edf4c7e5fdb1
ERROR: The record already exists.

 

 

The Cloudflare dashboard now shows:

Cloudflare dashboard showing newly created TXT record for example.com
Cloudflare dashboard showing the newly created TXT record for example.com

 

 

 

 

4.3. LIST, UPDATE & DELETE EXISTING DNS RECORDS

4.3.1 List All DNS Records for a Zone

To list all the DNS records associated with the zone record for example.com, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
curl -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": [
        {
            "content": "203.0.113.50",
            "created_on": "2018-02-09T08:40:30.673141Z",
            "id": "02a929c163302fe6ad885e77ad7bd268",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:40:30.673141Z",
            "name": "example.com",
            "proxiable": true,
            "proxied": true,
            "ttl": 1,
            "type": "A",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        },
        {
            "content": "203.0.113.50",
            "created_on": "2018-02-09T08:43:22.134574Z",
            "id": "1edaebfd2c02a69beec51da4476e743e",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:43:22.134574Z",
            "name": "sub-domain.example.com",
            "proxiable": true,
            "proxied": true,
            "ttl": 1,
            "type": "A",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        },
        {
            "content": "example.com",
            "created_on": "2018-02-09T08:44:10.505243Z",
            "id": "7bdb2e46037df332e5abdd45f8f981f5",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:44:10.505243Z",
            "name": "www.example.com",
            "proxiable": true,
            "proxied": true,
            "ttl": 1,
            "type": "CNAME",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        },
        {
            "content": "alt1.aspmx.l.google.com",
            "created_on": "2018-02-09T08:47:23.832766Z",
            "id": "6b21db8d6a20c0011971d4ec2c3b8445",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:47:23.832766Z",
            "name": "example.com",
            "priority": 5,
            "proxiable": false,
            "proxied": false,
            "ttl": 1,
            "type": "MX",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        },
        {
            "content": "aspmx.l.google.com",
            "created_on": "2018-02-09T08:46:28.139571Z",
            "id": "4983f68556095761d8f76af09f48b093",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:46:28.139571Z",
            "name": "example.com",
            "priority": 1,
            "proxiable": false,
            "proxied": false,
            "ttl": 1,
            "type": "MX",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        },
        {
            "content": "v=spf1 include:_spf.google.com ~all",
            "created_on": "2018-02-09T08:48:36.208222Z",
            "id": "3c90b59fca40473f26d8edf4c7e5fdb1",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:48:36.208222Z",
            "name": "example.com",
            "proxiable": false,
            "proxied": false,
            "ttl": 1,
            "type": "TXT",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        }
    ],
    "result_info": {
        "count": 6,
        "page": 1,
        "per_page": 20,
        "total_count": 6,
        "total_pages": 1
    },
    "success": true
}
{
    "errors": [],
    "messages": [],
    "result": [],
    "result_info": {
        "count": 0,
        "page": 1,
        "per_page": 20,
        "total_count": 0,
        "total_pages": 0
    },
    "success": true
}

 

 

 

 

4.3.2 List DNS Records for a Zone Based on DNS Record Name

To list all the DNS records associated with the zone record for example.com whose name is example.com, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
NAME="example.com"; \
curl -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?name=$NAME" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": [
        {
            "content": "203.0.113.50",
            "created_on": "2018-02-09T08:40:30.673141Z",
            "id": "02a929c163302fe6ad885e77ad7bd268",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:40:30.673141Z",
            "name": "example.com",
            "proxiable": true,
            "proxied": true,
            "ttl": 1,
            "type": "A",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        },
        {
            "content": "alt1.aspmx.l.google.com",
            "created_on": "2018-02-09T08:47:23.832766Z",
            "id": "6b21db8d6a20c0011971d4ec2c3b8445",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:47:23.832766Z",
            "name": "example.com",
            "priority": 5,
            "proxiable": false,
            "proxied": false,
            "ttl": 1,
            "type": "MX",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        },
        {
            "content": "aspmx.l.google.com",
            "created_on": "2018-02-09T08:46:28.139571Z",
            "id": "4983f68556095761d8f76af09f48b093",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:46:28.139571Z",
            "name": "example.com",
            "priority": 1,
            "proxiable": false,
            "proxied": false,
            "ttl": 1,
            "type": "MX",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        },
        {
            "content": "v=spf1 include:_spf.google.com ~all",
            "created_on": "2018-02-09T08:48:36.208222Z",
            "id": "3c90b59fca40473f26d8edf4c7e5fdb1",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:48:36.208222Z",
            "name": "example.com",
            "proxiable": false,
            "proxied": false,
            "ttl": 1,
            "type": "TXT",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        }
    ],
    "result_info": {
        "count": 4,
        "page": 1,
        "per_page": 20,
        "total_count": 4,
        "total_pages": 1
    },
    "success": true
}
{
    "errors": [],
    "messages": [],
    "result": [],
    "result_info": {
        "count": 0,
        "page": 1,
        "per_page": 20,
        "total_count": 0,
        "total_pages": 0
    },
    "success": true
}

 

 

 

 

4.3.3 List DNS Records for a Zone Based on DNS Record Type

To list all the DNS records associated with the zone record for example.com whose type is MX, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
TYPE="MX"; \
curl -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?type=$TYPE" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": [
        {
            "content": "alt1.aspmx.l.google.com",
            "created_on": "2018-02-09T10:55:50.545902Z",
            "id": "6b21db8d6a20c0011971d4ec2c3b8445",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T10:55:50.545902Z",
            "name": "example.com",
            "priority": 5,
            "proxiable": false,
            "proxied": false,
            "ttl": 1,
            "type": "MX",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        },
        {
            "content": "aspmx.l.google.com",
            "created_on": "2018-02-09T10:55:01.615968Z",
            "id": "4983f68556095761d8f76af09f48b093",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T10:55:01.615968Z",
            "name": "example.com",
            "priority": 1,
            "proxiable": false,
            "proxied": false,
            "ttl": 1,
            "type": "MX",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "example.com"
        }
    ],
    "result_info": {
        "count": 2,
        "page": 1,
        "per_page": 20,
        "total_count": 2,
        "total_pages": 1
    },
    "success": true
}
{
    "errors": [],
    "messages": [],
    "result": [],
    "result_info": {
        "count": 0,
        "page": 1,
        "per_page": 20,
        "total_count": 0,
        "total_pages": 0
    },
    "success": true
}

 

 

 

 

4.3.4 List DNS Records for a Zone Based on DNS Record Name and Type

To list all the DNS records associated with the zone record for example.com whose name is example.com and type is MX, use the following code:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
NAME="example.com"; \
TYPE="MX"; \
curl -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?name=$NAME&type=$TYPE" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": [
        {
            "content": "alt1.aspmx.l.google.com",
            "created_on": "2018-02-09T08:47:23.832766Z",
            "id": "ec3045d58f0cde044d73198af3dc77f4",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:47:23.832766Z",
            "name": "dummy.com",
            "priority": 5,
            "proxiable": false,
            "proxied": false,
            "ttl": 1,
            "type": "MX",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "dummy.com"
        },
        {
            "content": "aspmx.l.google.com",
            "created_on": "2018-02-09T08:46:28.139571Z",
            "id": "cab6d9fa24a3946530f0c1868d83bf8d",
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false
            },
            "modified_on": "2018-02-09T08:46:28.139571Z",
            "name": "dummy.com",
            "priority": 1,
            "proxiable": false,
            "proxied": false,
            "ttl": 1,
            "type": "MX",
            "zone_id": "8b717207bcee4047af2e9dff95832996",
            "zone_name": "dummy.com"
        }
    ],
    "result_info": {
        "count": 2,
        "page": 1,
        "per_page": 20,
        "total_count": 2,
        "total_pages": 1
    },
    "success": true
}
{
    "errors": [],
    "messages": [],
    "result": [],
    "result_info": {
        "count": 0,
        "page": 1,
        "per_page": 20,
        "total_count": 0,
        "total_pages": 0
    },
    "success": true
}

 

 

 

 

4.3.5 Update an Individual DNS Record

To update an individual DNS record we need to pass its unique ID to the Cloudflare API. So, to update the CNAME record for www.example.com so that PROXIED is changed to false and TTL is changed to 2 minutes, use the following code. Note that even though TYPE, NAME and CONTENT are not changing, they still need to be included otherwise the Cloudflare API returns an error:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
DNS_ID="7bdb2e46037df332e5abdd45f8f981f5"; \
TYPE="CNAME"; \
NAME="www"; \
CONTENT="example.com"; \
PROXIED="false"; \
TTL="120";\
curl -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_ID" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    --data '{"type":"'"$TYPE"'","name":"'"$NAME"'","content":"'"$CONTENT"'","proxied":'"$PROXIED"',"ttl":'"$TTL"'}' \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": {
        "content": "example.com",
        "created_on": "2018-02-09T09:58:05.239777Z",
        "id": "7bdb2e46037df332e5abdd45f8f981f5",
        "locked": false,
        "meta": {
            "auto_added": false,
            "managed_by_apps": false
        },
        "modified_on": "2018-02-09T09:58:05.239777Z",
        "name": "www.example.com",
        "proxiable": true,
        "proxied": false,
        "ttl": 120,
        "type": "CNAME",
        "zone_id": "8b717207bcee4047af2e9dff95832996",
        "zone_name": "example.com"
    },
    "success": true
}
{
    "errors": [
        {
            "code": 1020,
            "message": "Invalid DNS record identifier"
        }
    ],
    "messages": [],
    "result": null,
    "success": false
}

 

 

DNS CNAME record pre-update for example.com
DNS CNAME record pre-update for example.com

 

 

DNS CNAME record post-update for example.com
DNS CNAME record post-update for example.com

 

 

 

 

4.3.6 Delete an Individual DNS Record

To delete an individual DNS record associated with the zone record for example.com, use the following code. Note thet the DNS record’s unique ID needs to be included:

Dummy Content
EMAIL="steve@example.com"; \
KEY="08n46q4ofo0v5pc3u3g3eu517o69axu8s6ml4"; \
ZONE_ID="8b717207bcee4047af2e9dff95832996"; \
DNS_ID="7bdb2e46037df332e5abdd45f8f981f5"; \
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_ID" \
    -H "X-Auth-Email: $EMAIL" \
    -H "X-Auth-Key: $KEY" \
    -H "Content-Type: application/json" \
    | python -m json.tool;
{
    "errors": [],
    "messages": [],
    "result": {
        "id": "7bdb2e46037df332e5abdd45f8f981f5"
    },
    "success": true
} 
{
    "errors": [
        {
            "code": 1032,
            "message": "Invalid DNS record identifier"
        }
    ],
    "messages": [],
    "result": null,
    "success": false
}

 

 

About the author

A native Brit exiled in Japan, Steve spends too much of his time struggling with the Japanese language, dreaming of fish & chips and writing the occasional blog post he hopes others will find helpful.

Add comment

Steve

Recent Comments

Recent Posts