A community-driven CLI tool for managing NextDNS profiles declaratively.
Disclaimer: This is an unofficial tool, not affiliated with NextDNS. Built by a user, for users.
Note: While
nextdnsctlhandles API rate limiting and retries, it is not recommended for importing very large blocklists. For large-scale filtering, prefer using NextDNS's built-in curated blocklists under the Privacy tab, and use thedenylistfeature for specific overrides or fine-tuning.
- Bulk add/remove domains to the NextDNS denylist and allowlist
- Import domains from a file or URL
- Export current list to a file for backup
- List and clear all entries in a list
- Delta-aware add/import/remove operations that skip unchanged entries
- Parallel API requests for faster bulk operations
- Dry-run mode to preview changes before applying
- Use profile names or IDs interchangeably
pip install nextdnsctlRequires Python 3.10+.
# Authenticate (find your API key at https://my.nextdns.io/account)
nextdnsctl auth <your-api-key>
# List your profiles
nextdnsctl profile-list
# Add domains to denylist (using profile name or ID)
nextdnsctl denylist add "My Profile" bad.com evil.com
# Preview changes without applying them
nextdnsctl --dry-run denylist import myprofile blocklist.txtThe API key can be provided in two ways (in order of priority):
-
Environment variable (recommended for CI/CD):
export NEXTDNS_API_KEY=your-api-key nextdnsctl profile-list -
Config file (created by
authcommand):nextdnsctl auth <your-api-key> # Stored in ~/.nextdnsctl/config.json with secure permissions
| Option | Description |
|---|---|
--concurrency N |
Number of parallel API requests (1-20, default: 5) |
--dry-run |
Show what would be done without making changes |
--retry-attempts N |
Number of retry attempts for API calls (default: 4) |
--retry-delay N |
Initial delay between retries in seconds (default: 1) |
--timeout N |
Request timeout in seconds (default: 10) |
All commands accept either a profile ID or profile name (case-insensitive):
# Using profile ID
nextdnsctl denylist list abc123
# Using profile name
nextdnsctl denylist list "My Profile"nextdnsctl denylist list <profile>
nextdnsctl denylist list <profile> --active-only
nextdnsctl denylist list <profile> --inactive-onlynextdnsctl denylist add <profile> domain1.com domain2.com
nextdnsctl denylist add <profile> domain.com --inactive
nextdnsctl denylist add <profile> domain.com --update-existingAdd operations fetch the current list first and only create missing domains. Domains
already present with the requested active/inactive state are skipped. If a domain is
already present with the opposite state, it is reported and left unchanged unless
--update-existing is passed.
nextdnsctl denylist remove <profile> domain1.com domain2.comRemove operations compare against the current list first and skip domains that are not present.
nextdnsctl denylist import <profile> /path/to/blocklist.txt
nextdnsctl denylist import <profile> https://example.com/blocklist.txt
nextdnsctl denylist import <profile> blocklist.txt --inactive
nextdnsctl denylist import <profile> blocklist.txt --update-existingThe import file format supports:
- One domain per line
- Comments starting with
# - Inline comments (e.g.,
example.com # reason) - Empty lines (ignored)
Import is delta-aware: nextdnsctl fetches the current list once, deduplicates the
input, and only sends API writes for missing domains. This reduces rate-limit pressure
when re-importing the same or overlapping lists.
nextdnsctl denylist export <profile> backup.txt
nextdnsctl denylist export <profile> # outputs to stdout
nextdnsctl denylist export <profile> --active-only > active.txtnextdnsctl denylist clear <profile> # asks for confirmation
nextdnsctl denylist clear <profile> --yes # skip confirmationAll denylist commands are available for allowlist with the same syntax:
nextdnsctl allowlist list <profile>
nextdnsctl allowlist add <profile> good.com trusted.com
nextdnsctl allowlist remove <profile> domain.com
nextdnsctl allowlist import <profile> allowlist.txt
nextdnsctl allowlist export <profile> backup.txt
nextdnsctl allowlist clear <profile> --yesBy default, bulk operations run 5 concurrent API requests. Adjust with --concurrency:
# Faster (more concurrent requests)
nextdnsctl --concurrency 10 denylist import myprofile blocklist.txt
# Sequential mode (verbose per-domain output, like v0.2.0)
nextdnsctl --concurrency 1 denylist import myprofile blocklist.txtPreview changes before applying them:
$ nextdnsctl --dry-run denylist add myprofile bad.com evil.com
[DRY-RUN] Denylist plan:
New domains to add: 2
- bad.com
- evil.com
[DRY-RUN] No changes made.Pull requests welcome! See docs/contributing.md for details.
MIT License - see LICENSE.