This is a simple script that can automate backing up of ODK central using the python
import requests
from requests.auth import HTTPBasicAuth
from pprint import pprint
# π User credentials
ODK_USERNAME = "something@something.com"
ODK_PASSWORD = "passwords" # Replace with your actual password
ODK_DOMAIN = "odk.xyz.com" # e.g., nationalttsurvey.aiims.edu
BACKUP_PASSPHRASE = "backup-password"
# π API endpoint
BASEURL = f"https://{ODK_DOMAIN}/v1/backup"
# π Auth
auth = HTTPBasicAuth(ODK_USERNAME, ODK_PASSWORD)
# π Backup request payload
payload = {
"passphrase": BACKUP_PASSPHRASE
}
# π Send POST request
response = requests.post(BASEURL, auth=auth, headers={"Content-Type": "application/json"}, json=payload, stream=True)
# π Print headers in a gentlemanly fashion
print("\nπ© Response Headers:")
for key, value in response.headers.items():
print(f"{key}: {value}")
# π Check for errors
if response.status_code == 200:
# π Determine filename
content_disposition = response.headers.get('Content-Disposition')
if content_disposition and "filename=" in content_disposition:
filename = content_disposition.split("filename=")[-1].strip('"')
filename = filename.replace(':', '-').replace('/', '-').replace('\\', '-')
else:
filename = "backup.zip"
# π Save file
chunk_size = 10 * 1024 * 1024 # 10 MB
total_bytes = 0
with open(filename, "wb") as f:
for chunk in response.iter_content(chunk_size=chunk_size):
if chunk:
f.write(chunk)
total_bytes += len(chunk)
print(f"π© Received {total_bytes / (1024 * 1024):.2f} MB so far...")
print(f"\nβ
Backup saved as: {filename}")
else:
print(f"\nβ Failed to download backup! Status code: {response.status_code}")
print(response.text)
Tested and used 2 days back
I had to wait almost 10 minutes before data actually started downloading. I guess during that time, the backup was getting created on the server.
Bests
Vivek
4 Likes
I would appriciate about your effort. Have a look on https://pypi.org/project/centralpy/ , it;s more fater than your code. It's python package which is doing same thing with more secure way, feel free to use this it's open source.
Best,
@iamnarendrasingh
Thank You. The central.py package is interesting, but I do not think it can do the API based Direct Backup which the script i had shared intends to do.
A slighly improved version that displays downloaded size
import requests
from requests.auth import HTTPBasicAuth
from pprint import pprint
# π User credentials
ODK_USERNAME = "cccc@ccc.com"
ODK_PASSWORD = "cccccccccccc" # Replace with your actual password
ODK_DOMAIN = "cccc.vvvv.zzzzzzz" #
BACKUP_PASSPHRASE = "backup-password"
# π API endpoint
BASEURL = f"https://{ODK_DOMAIN}/v1/backup"
# π Auth
auth = HTTPBasicAuth(ODK_USERNAME, ODK_PASSWORD)
# π Backup request payload
payload = {
"passphrase": BACKUP_PASSPHRASE
}
# π Send POST request
response = requests.post(BASEURL, auth=auth, headers={"Content-Type": "application/json"}, json=payload, stream=True)
# π Print headers in a gentlemanly fashion
print("\nπ© Response Headers:")
for key, value in response.headers.items():
print(f"{key}: {value}")
# π Check for errors
if response.status_code == 200:
# π Determine filename
content_disposition = response.headers.get('Content-Disposition')
if content_disposition and "filename=" in content_disposition:
filename = content_disposition.split("filename=")[-1].strip('"')
filename = filename.replace(':', '-').replace('/', '-').replace('\\', '-')
else:
filename = "backup.zip"
# π Save file
chunk_size = 10 * 1024 * 1024 # 10 MB
total_bytes = 0
with open(filename, "wb") as f:
for chunk in response.iter_content(chunk_size=chunk_size):
if chunk:
f.write(chunk)
total_bytes += len(chunk)
print(f"π© Received {total_bytes / (1024 * 1024):.2f} MB so far...")
print(f"\nβ
Backup saved as: {filename}")
else:
print(f"\nβ Failed to download backup! Status code: {response.status_code}")
print(response.text)
4 Likes
Thanks for sharing this script. I tried it and it works. However, it seems not actually encrypt the βpassphraseβ into the zip file. I donβt need the passphrase to open the zip file. And also, inside the zip file, there are bunch of *.dat.gz files, if I try to open them with 7-zip, it shows errors. Any ideas?
Hey @Alexander ! 
Just to clarify, the passphrase used in the script above isn't meant to encrypt the .zip file itself. Instead, it's used to encrypt the backup inside the zip - specifically the .dat.gz files, which is why they can't be opened directly using tools like 7Zip.
This same passphrase will be required later when you restore the backup on an ODK Central instance. Without it, the restore process won't work.
If it helps, the following documentation sections explain this flow really well and might give you a clearer picture of how things fit together:
Hope this helps, and wishing you a great day ahead! 
@MinimalPotato Thanks for your clarification. I misunderstood the original ODK Direct Backup/Restore documents. Now my questions were solved.
Thanks again.