Python Sync Script (Cloud-First Mirror)

What this script does
  1. Logs in with your email and password and receives an access token.
  2. Lists every purchase you own and every subscription group you belong to.
  3. Compares that list against your local drive and downloads only what is missing.
  4. Tries the Cloudflare CDN first, falling back to our origin server automatically.
Download the script

A single file with no dependencies other than requests. It is heavily commented throughout so you can read and modify it without needing to ask an AI to explain it.

Download dnfilevault_sync_mirror.py
Works on Windows, Linux, and macOS. Requires Python 3.8 or newer.

Why it downloads from the cloud first

Every file record returned by the API may include a cloud_share_link field pointing at our Cloudflare R2 CDN. When that link is present the script uses it instead of the origin server, because Cloudflare serves the bytes from an edge location near you rather than from our server in the United States.

The difference is substantial. In our own testing, an identical 325 KB file took under 1 second from the CDN versus 19 seconds from the origin. The gap widens on multi-gigabyte files and on connections far from our data center.

If you are running your automation from a cloud server (AWS, Azure, GCP), using the CDN route matters even more — those hosts are often routed poorly to our origin.

Automatic fallback

The CDN is not always an option. Newly published files are pushed to Cloudflare by a background uploader, so for a short window after publication a file exists on our origin but not yet on the CDN and has no cloud_share_link. The script handles this without any intervention:

ATTEMPT 1 -> CLOUD   https://vault.dnfilevault.com/<uuid>
             No Authorization header is sent. The UUID in the URL
             is itself the access token, so your DNFileVault
             credentials are never exposed to the CDN host.
             A 404 aborts immediately (retrying cannot help).

ATTEMPT 2 -> LOCAL   https://api.dnfilevault.com/download/<uuid>
             Authenticated with your Bearer token. Used when there
             is no cloud link yet, or when the CDN attempt failed.
             401 / 403 / 410 abort without retrying, since those
             mean your purchase or subscription has expired.

Both failed -> the file is reported and the script moves on to
               the next one. Nothing is deleted or corrupted.

Safe to re-run at any time

The script mirrors rather than re-downloads. On every run it checks each expected file against what is already on disk and skips anything present at the correct size, so a nightly scheduled run only transfers that day's new files.

Downloads stream to a temporary .part file and are renamed into place only after the transfer completes and the byte count matches. An interrupted transfer can never leave behind a truncated file that looks complete — the next run simply picks it up again.

How to run it

pip install requests

# See what would be downloaded, without transferring anything:
python dnfilevault_sync_mirror.py --dry-run

# Mirror everything into a folder of your choosing:
python dnfilevault_sync_mirror.py --dir D:\MarketData\DNFileVault

You will be prompted for your email and password. For scheduled or unattended runs, set them as environment variables instead so nothing is typed and no credentials live inside the script:

Windows:
    set [email protected]
    set DNFILEVAULT_PASSWORD=yourpassword
    set DNFILEVAULT_SYNC_DIR=D:\MarketData\DNFileVault

Linux / macOS:
    export [email protected]
    export DNFILEVAULT_PASSWORD=yourpassword
    export DNFILEVAULT_SYNC_DIR=/data/dnfilevault

The script exits with code 1 if any file failed, so Task Scheduler or cron can detect a bad run and alert you.

Folder layout it creates

DNFileVault\
    purchases\
        152 - Level 2 Full History\
            L2_2026_January.zip
            L2_2026_February.zip
    groups\
        eodLevel3\
            L3_20260723.zip
            L3_20260724.zip
        stockhistory\
            StockHistory.zip
            dividends.csv

Purchase folders include the purchase number because the same product can be bought more than once (for example on renewal), and each purchase is a distinct set of files. Your own code then simply copies from these folders — no API or FTP logic needs to live inside your projects.

A note on timeouts

DNFileVault has anti-scanner protection on the API. Requests that look bot-like (a blank or default User-Agent) may be deliberately slowed to protect the service. This script already sends a proper descriptive User-Agent, so you should not encounter this — but if you adapt the code into your own client, keep that header. See the Automation & API page for more detail, or the API Reference for the full endpoint documentation.