Skip to content

Instantly share code, notes, and snippets.

@ashleykleynhans
Forked from dlage/README.md
Last active November 6, 2025 12:38
Show Gist options
  • Save ashleykleynhans/69e4fb525d4f32d766313d3f9d22b688 to your computer and use it in GitHub Desktop.
Save ashleykleynhans/69e4fb525d4f32d766313d3f9d22b688 to your computer and use it in GitHub Desktop.
Namecheap DNS to zone file
#!/usr/bin/env python3
#######################################################################################################################
# Generate DNS Zone file from Namecheap
#
# Modification History:
# Date Version Modified by Github URL Description
# 2016-03-11 1.0 Judotens Budiarto https://github.com/judotens Initial creation
# 2020-01-17 1.1 Andrew https://github.com/andrew-nuwber Resolve CAPTCHA issue
# 2020-12-07 1.2 Dinis https://github.com/dlage Cloudflare and AAAA record support
# 2022-08-30 1.3 Ashley Kleynhans https://github.com/ashleykleynhans Python3 and more DNS records support,
# Refactored code to break out of loop
# sooner, use argparse to validate
# command line arguments, option to
# choose default or cloudflare format.
# improved error handling, autodetect
# domain name.
#######################################################################################################################
"""
1. Login to Namecheap Account
2. Get JSON from https://ap.www.namecheap.com/Domains/dns/GetAdvancedDnsInfo?fillTransferInfo=false&domainName=YOURDOMAINNAME.com
3. Save it to file
4. `python get_namecheap_dns_records.py data.json`
"""
import argparse
import json
RECORD_TYPES = {
1: 'A',
2: 'CNAME',
3: 'MX',
5: 'TXT',
8: 'AAAA',
9: 'NS',
10: 'URL Redirect',
11: 'SRV',
12: 'CAA',
13: 'ALIAS'
}
def get_args():
parser = argparse.ArgumentParser(
description='Get Namecheap DNS records.',
)
parser.add_argument(
'filename',
type=str,
help='Filename'
)
parser.add_argument(
'--format', '-format', '--f', '-f',
type=str,
required=False,
default='default',
choices={'default', 'cloudflare'},
help='Output format (default/cloudflare)'
)
return parser.parse_args()
def parse_dns_info(dns_info, output_format):
items = []
if 'Result' in dns_info and\
'CustomHostRecords' in dns_info['Result'] and\
'Records' in dns_info['Result']['CustomHostRecords']:
records = dns_info['Result']['CustomHostRecords']['Records']
else:
raise KeyError('JSON is in an unexpected format')
if not len(records):
raise Exception('No DNS records found in JSON')
for record in records:
# Skip inactive records
if not record['IsActive']:
continue
# Skip unknown record types
if record['RecordType'] not in RECORD_TYPES.keys():
continue
record_type = RECORD_TYPES[record['RecordType']]
value = record['Data']
host = record['Host']
if record_type == 'MX':
value = f"{record['Priority']} {value}"
elif record_type == 'TXT':
value = f'"{value}"'
if output_format == 'cloudflare':
domain = dns_info['Result']['DomainBasicDetails']['DomainName']
if host == '@':
host = domain
else:
host = f'{host}.{domain}.'
items.append([
host,
str(record['Ttl']),
'IN',
record_type,
value
])
return items
if __name__ == '__main__':
try:
args = get_args()
filename = args.filename
output_format = args.format
file = open(filename, 'r')
dns_info = json.loads(file.read())
file.close()
records = parse_dns_info(dns_info, output_format)
for record in records:
print('\t'.join(record))
except (IOError, KeyError, Exception) as e:
print(f'ERROR: {e}')
except json.decoder.JSONDecodeError as e:
print(f'ERROR: Unable to decode JSON from {filename}: {e}')
@zorbathut
Copy link

thank you for saving me from manually transcribing several dozen DNS entries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment