Of course! Here's a comprehensive guide on how to use the DNSPod API with Python, covering everything from setup to practical examples.

DNSPod (now often referred to as Tencent Cloud DNSPod) provides a robust API for managing your domains and DNS records. Using Python to interact with this API is a common task for automation, such as updating dynamic IPs or managing records in bulk.
Prerequisites
- A DNSPod Account: You need an account on the DNSPod website.
- An API Token: This is the most crucial part. The API token authenticates your requests.
- Log in to your DNSPod account.
- Go to 用户中心 (User Center) -> 安全设置 (Security Settings) -> API Token.
- Create a new token. Give it a descriptive name (e.g., "My Python Script").
- Important: Copy the
IDandTokenimmediately. You will not be able to see the full token again. Store it securely (e.g., in an environment variable, not hardcoded in your script).
- Python 3: Ensure you have Python 3 installed on your system.
requestslibrary: This is the standard library for making HTTP requests in Python. If you don't have it, install it:pip install requests
Understanding the DNSPod API
- Endpoint: All API requests are sent to
https://dnsapi.cn. - Authentication: You authenticate using your API Token ID and Token as parameters in every request.
- Method: The API uses
POSTrequests. All parameters (including the authentication ones) are sent in the request body asapplication/x-www-form-urlencodeddata. - Response: The API returns a JSON object. A successful response will have
"status": {"code": "1"}. Any other code indicates an error.
Step 1: Setting Up Authentication
It's a bad practice to hardcode your API token directly into your script. The best way is to use environment variables.
On Linux/macOS:
export DNSPOD_ID='your_token_id' export DNSPOD_TOKEN='your_token_value'
On Windows (Command Prompt):

set DNSPOD_ID=your_token_id set DNSPOD_TOKEN=your_token_value
On Windows (PowerShell):
$env:DNSPOD_ID='your_token_id' $env:DNSPOD_TOKEN='your_token_value'
Now, in your Python script, you can load these variables:
import os
import requests
# Load credentials from environment variables
DNSPOD_API_ID = os.environ.get('DNSPOD_ID')
DNSPOD_API_TOKEN = os.environ.get('DNSPOD_TOKEN')
if not DNSPOD_API_ID or not DNSPOD_API_TOKEN:
raise ValueError("DNSPOD_ID and DNSPOD_TOKEN environment variables must be set.")
# The base URL for the DNSPod API
API_BASE_URL = "https://dnsapi.cn"
Step 2: Creating a Reusable API Client Function
To avoid repeating the authentication logic for every API call, let's create a helper function.
def make_dnspod_request(action, params):
"""
Makes a request to the DNSPod API.
:param action: The API action to perform (e.g., 'Record.List').
:param params: A dictionary of parameters for the specific action.
:return: The JSON response from the API.
"""
url = f"{API_BASE_URL}/{action}"
# All API calls require login_token
request_params = {
'login_token': f"{DNSPOD_API_ID},{DNSPOD_API_TOKEN}",
**params # Unpack other parameters
}
try:
response = requests.post(url, data=request_params)
response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
return response.json()
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
return None
Step 3: Practical Examples
Let's perform some common tasks.

Example 1: List Your Domains
First, you need to get the ID of the domain you want to manage.
def get_domains():
"""Fetches a list of all domains associated with the account."""
response = make_dnspod_request('Domain.List', {})
if response and response.get('status', {}).get('code') == '1':
domains = response['domains']
print("Your domains:")
for domain in domains:
print(f" - ID: {domain['id']}, Name: {domain['name']}")
return domains
else:
print("Failed to list domains.")
if response:
print("Error:", response.get('status', {}).get('message', 'Unknown error'))
return []
# --- Execute ---
# domains = get_domains()
Example 2: List DNS Records for a Specific Domain
Let's say you want to list all A records for the domain example.com. You'll need its ID from the previous step.
def list_records(domain_id, record_type='A', sub_domain='www'):
"""
Lists DNS records for a given domain.
:param domain_id: The ID of the domain.
:param record_type: The type of record (A, AAAA, CNAME, MX, etc.).
:param sub_domain: The subdomain to filter by.
:return: A list of records.
"""
params = {
'domain_id': domain_id,
'record_type': record_type,
'sub_domain': sub_domain,
'record_line': '默认' # 'Default' line
}
response = make_dnspod_request('Record.List', params)
if response and response.get('status', {}).get('code') == '1':
records = response['records']
print(f"Found {len(records)} '{record_type}' records for subdomain '{sub_domain}':")
for record in records:
print(f" - ID: {record['id']}, Value: {record['value']}, TTL: {record['ttl']}")
return records
else:
print("Failed to list records.")
if response:
print("Error:", response.get('status', {}).get('message', 'Unknown error'))
return []
# --- Execute ---
# Replace with your actual domain ID
# DOMAIN_ID = '12345'
# list_records(DOMAIN_ID)
Example 3: Update a DNS Record (Dynamic IP Update)
This is a very common use case. We'll find an existing record and update its IP address.
def update_record_ip(domain_id, record_id, new_ip):
"""
Updates the IP address of a specific DNS record.
:param domain_id: The ID of the domain.
:param record_id: The ID of the record to update.
:param new_ip: The new IP address.
:return: True on success, False on failure.
"""
params = {
'domain_id': domain_id,
'record_id': record_id,
'record_type': 'A',
'value': new_ip,
'ttl': '600', # Set a TTL, e.g., 600 seconds
'record_line': '默认'
}
response = make_dnspod_request('Record.Modify', params)
if response and response.get('status', {}).get('code') == '1':
print(f"Successfully updated record ID {record_id} to IP {new_ip}.")
return True
else:
print("Failed to update record.")
if response:
print("Error:", response.get('status', {}).get('message', 'Unknown error'))
return False
# --- Execute ---
# This is a full workflow example
def main():
# 1. Get your domain ID (hardcoded for this example)
DOMAIN_ID = '12345' # <--- REPLACE WITH YOUR DOMAIN ID
SUBDOMAIN_TO_UPDATE = 'home' # e.g., 'home.example.com'
NEW_IP = '1.2.3.4' # <--- REPLACE WITH THE NEW IP
# 2. Find the record ID you want to update
records = list_records(DOMAIN_ID, sub_domain=SUBDOMAIN_TO_UPDATE)
if not records:
print(f"Could not find a record for '{SUBDOMAIN_TO_UPDATE}'. Exiting.")
return
# DNSPod returns a list, we'll take the first match
record_to_update = records[0]
record_id = record_to_update['id']
old_ip = record_to_update['value']
print(f"Found record ID {record_id} with current IP {old_ip}.")
# 3. Only update if the IP has actually changed
if old_ip == NEW_IP:
print("The IP address has not changed. No update needed.")
else:
print(f"Updating IP from {old_ip} to {NEW_IP}...")
update_record_ip(DOMAIN_ID, record_id, NEW_IP)
# if __name__ == "__main__":
# main()
Full Script: Dynamic DNS Updater
Here is a complete, runnable script that you can adapt for your own use. It finds a record by name and updates its IP.
#!/usr/bin/env python3
import os
import json
import requests
import sys
# --- Configuration ---
# Load credentials from environment variables
DNSPOD_API_ID = os.environ.get('DNSPOD_ID')
DNSPOD_API_TOKEN = os.environ.get('DNSPOD_TOKEN')
# Configuration for the record to update
DOMAIN_NAME = 'example.com' # The domain name
SUBDOMAIN = 'ddns' # The subdomain to update (e.g., 'ddns.example.com')
RECORD_TYPE = 'A' # Record type (A, AAAA, CNAME, etc.)
TTL = '600' # Time-to-live in seconds
RECORD_LINE = '默认' # The DNS line (e.g., '默认', '默认' is 'Default')
API_BASE_URL = "https://dnsapi.cn"
def make_dnspod_request(action, params):
"""Helper function to make authenticated API requests."""
if not DNSPOD_API_ID or not DNSPOD_API_TOKEN:
print("Error: DNSPOD_ID and DNSPOD_TOKEN environment variables are not set.", file=sys.stderr)
sys.exit(1)
url = f"{API_BASE_URL}/{action}"
request_params = {
'login_token': f"{DNSPOD_API_ID},{DNSPOD_API_TOKEN}",
**params
}
try:
response = requests.post(url, data=request_params)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"API request failed: {e}", file=sys.stderr)
return None
def get_domain_id(domain_name):
"""Gets the domain ID for a given domain name."""
response = make_dnspod_request('Domain.Info', {'domain': domain_name})
if response and response.get('status', {}).get('code') == '1':
return response['domain']['id']
else:
print(f"Could not get domain ID for {domain_name}.", file=sys.stderr)
if response:
print("API Error:", response.get('status', {}).get('message', 'Unknown error'), file=sys.stderr)
return None
def update_dns_record(domain_id, subdomain, record_type, new_ip):
"""Finds and updates a DNS record with a new IP."""
# First, list the records to find the one we want to update
list_params = {
'domain_id': domain_id,
'sub_domain': subdomain,
'record_type': record_type,
'record_line': RECORD_LINE
}
response = make_dnspod_request('Record.List', list_params)
if not response or response.get('status', {}).get('code') != '1':
print("Failed to list records.", file=sys.stderr)
return False
records = response.get('records', [])
if not records:
print(f"No records found for {subdomain}.{DOMAIN_NAME}", file=sys.stderr)
return False
# We'll assume the first match is the one we want
record = records[0]
record_id = record['id']
old_ip = record['value']
print(f"Found record: {record['name']} -> {old_ip}")
if old_ip == new_ip:
print("IP address has not changed. No update needed.")
return True
# Now, modify the record
modify_params = {
'domain_id': domain_id,
'record_id': record_id,
'sub_domain': subdomain,
'record_type': record_type,
'value': new_ip,
'ttl': TTL,
'record_line': RECORD_LINE
}
response = make_dnspod_request('Record.Modify', modify_params)
if response and response.get('status', {}).get('code') == '1':
print(f"Successfully updated {subdomain}.{DOMAIN_NAME} to {new_ip}")
return True
else:
print("Failed to update record.", file=sys.stderr)
if response:
print("API Error:", response.get('status', {}).get('message', 'Unknown error'), file=sys.stderr)
return False
def get_current_ip():
"""Gets the current public IP address."""
try:
# Use a reliable service to get the public IP
ip = requests.get('https://api.ipify.org?format=text', timeout=5).text
return ip.strip()
except Exception as e:
print(f"Failed to get current IP: {e}", file=sys.stderr)
return None
def main():
"""Main function to run the update process."""
print("Starting DNSPod Dynamic DNS update...")
current_ip = get_current_ip()
if not current_ip:
print("Could not determine current IP. Aborting.", file=sys.stderr)
sys.exit(1)
print(f"Current public IP is: {current_ip}")
domain_id = get_domain_id(DOMAIN_NAME)
if not domain_id:
sys.exit(1)
success = update_dns_record(domain_id, SUBDOMAIN, RECORD_TYPE, current_ip)
sys.exit(0 if success else 1)
if __name__ == "__main__":
main()
How to Use the Full Script
- Save: Save the code above as a file, for example,
dnspod_ddns.py. - Configure:
- Set your
DNSPOD_IDandDNSPOD_TOKENenvironment variables. - Modify the configuration variables at the top of the script (
DOMAIN_NAME,SUBDOMAIN, etc.) to match your needs.
- Set your
- Run:
python dnspod_ddns.py
This script will automatically detect your public IP, find the corresponding DNS record in your DNSPod account, and update it if the IP has changed. You can run this script periodically (e.g., via a cron job) to maintain a dynamic DNS setup.
