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
- 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 --inactivenextdnsctl denylist remove <profile> domain1.com domain2.comnextdnsctl denylist import <profile> /path/to/blocklist.txt
nextdnsctl denylist import <profile> https://example.com/blocklist.txt
nextdnsctl denylist import <profile> blocklist.txt --inactiveThe import file format supports:
- One domain per line
- Comments starting with
# - Inline comments (e.g.,
example.com # reason) - Empty lines (ignored)
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] Would add 2 domain(s):
- bad.com
- evil.com
[DRY-RUN] No changes made.Pull requests welcome! See docs/contributing.md for details.
MIT License - see LICENSE.