Search code examples
jsondnspython-requestsdns-over-https

Unable to make dns-over-https with cloudflare and python requests


I'm trying to write a quick script that could do dns lookups using the new 1.1.1.1 DNS over HTTPS public DNS server from CloudFlare.

Looking at their docs here https://developers.cloudflare.com/1.1.1.1/dns-over-https/json-format/ I'm not sure what I'm doing wrong and why I'm getting a 415 status code (415 Unsupported content type).

Here is my script: #!/usr/bin/env python import requests import json from pprint import pprint

url = 'https://cloudflare-dns.com/dns-query'
client = requests.session() 

json1 = {'name': 'example.com','type': 'A'}

ae = client.get(url, headers = {'Content-Type':'application/dns-json'}, json = json1)


print ae.raise_for_status()
print ae.status_code

print ae.json()

client.close()

Here is the output:

    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 415 Client Error: Unsupported Media Type for url: https://cloudflare-dns.com/dns-query

and for the json response (expected I believe):

raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

Using curl this works perfectly fine.

Many thanks


Solution

  • You should not set a JSON request at all. The response uses JSON.

    Put the application/dns-json value in a ct parameter:

    JSON formatted queries are sent using a GET request. When making requests using GET, the DNS query is encoded into the URL. An additional URL parameter of ‘ct’ should indicate the MIME type (application/dns-json).

    A GET request never has a body, so don't try to send JSON:

    params = {
        'name': 'example.com',
        'type': 'A',
        'ct': 'application/dns-json',
    }
    ae = client.get(url, params=params)
    

    Demo:

    >>> import requests
    >>> url = 'https://cloudflare-dns.com/dns-query'
    >>> client = requests.session()
    >>> params = {
    ...     'name': 'example.com',
    ...     'type': 'A',
    ...     'ct': 'application/dns-json',
    ... }
    >>> ae = client.get(url, params=params)
    >>> ae.status_code
    200
    >>> from pprint import pprint
    >>> pprint(ae.json())
    {'AD': True,
     'Answer': [{'TTL': 2560,
                 'data': '93.184.216.34',
                 'name': 'example.com.',
                 'type': 1}],
     'CD': False,
     'Question': [{'name': 'example.com.', 'type': 1}],
     'RA': True,
     'RD': True,
     'Status': 0,
     'TC': False}