NextDNS-API
An awesome way to interface with your NextDNS account - via Python!
Explore the docs »
Report Bug
.
Request Feature
Table Of Contents
About The Project
I was getting increasingly frustrated with NextDNS's lack of API. I wanted to manage things on the fly. So, I did the most logical thing. I built a python script (library-to-be) to control my NextDNS account. I decided to make it public because why not?
Built With
Built using Python:
Prerequisites
This is an example of how to list things you need to use the software and how to install them.
Installation
-
pip install nextdnsapi
-
Open your IDE
-
Import library
from nextdnsapi.api import *
or
from nextdnsapi import api
from api import *
- Check Github for Usage
Usage
Usage is very easy, so I won't bother to go into the intricacies of the library, but I will go over some basic info. This library closely imitates the website.
Account
For logging in using 2FA, see 2FA.md
header = account.login("example@example.com", "password123")
account.login(email, password)
Example: account.login("example@example.com", "password123")
Response: Login credentials (headers and cookies) for NextDNS
account.list(header)
Example: account.list(header)
Response:
account.month(header)
Example: account.month(header)
Response: {"monthlyQueries":44065}
Settings
settings.listsettings(config,header):
Example: settings.listsettings("d46a5b", header)
Response: {'name': 'Config 1', 'logging': True, 'logging_disable_query': False, 'logging_disable_client': False, 'logging_retention': 164200, 'logging_location': 'ch', 'blockPage': True, 'ecs': True, 'cacheBoost': True, 'cnameFlattening': True, 'handshake': True, 'rewrites': []}
settings.setup(config,header)
Example: settings.setup("d46a5b", header)
Response: {'id': 'd46a5b', 'fingerprint': 'fpd7527ea9b798****', 'ipv4': [], 'ipv6': ['2a07:****::**:6a5a', '2a07:****::**:6a5a'], 'linkedIpDNSServers': ['45.90.**.105', '45.90.**.105'], 'ddnsHostname': '****.ddns.net', 'linkedIpUpdateToken': 'd1aa9fe86e9c****', 'linkedIp': '41.210.***.69', 'dnsStamp': 'sdns://AgE*********CjQ1LjkwLjI4LjAADmRucy5uZXh0ZG5zLmlvBy9kNDZhNWE'}
settings.downloadlogs(config,header)
Example: settings.downloadlogs("d46a5b", header)
Response: "d46a5b-2022-05-21T11 30 26.867Z.csv" if success, else ConfigNotFound
settings.clearlogs(config,header)
Example: settings.clearlogs("d46a5b", header)
Response: "OK" if success, else ConfigNotFound
settings.rename(name, config, header)
Example: settings.rename("Config One", "d46a5b", header)
Response: "Response renamed to {new name}" if success, else ConfigNotFound
settings.logclientips(bool, config, header)
Example: settings.logclientips(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
settings.logdomains(bool, config, header)
Example: settings.logdomains(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
settings.blockpage(bool, config, header)
Example: settings.blockpage(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
settings.adddnsrewrite(domain, answer, config, header)
Example: settings.adddnsrewrite("router.local", "192.168.1.1", "d46a5b", header)
Response: {"id":12345,"name":"router.local","answer":"192.168.1.1"} if success, else ConfigNotFound
settings.deletednsrewrite(id, config, header)
Example: settings.deletednsrewrite(12345, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
settings.updatelinkedip(config,header)
Example: settings.updatelinkedip(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
settings.delete(config, header)
Example: settings.rename("d46a5b", header)
Response: "{Config ID} deleted" if success, else ConfigNotFound
Security
security.list(config, header)
Example: security.list("d46a5b", header)
Response: {'threatIntelligenceFeeds': True, 'aiThreatDetection': True, 'googleSafeBrowsing': False, 'cryptojacking': True, 'dnsRebinding': False, 'homograph': True, 'typosquatting': True, 'dga': True, 'nrd': False, 'parked': False, 'csam': True, 'blocked_tlds': []}
security.threatintelligencefeeds(bool, config, header)
Example: security.threatintelligencefeeds(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
security.aidetection(bool, config, header)
Example: security.aidetection(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
security.safebrowsing(bool, config, header)
Example: security.safebrowsing(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
security.cryptojacking(bool, config, header)
Example: security.cryptojacking(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
security.dnsrebinding(bool, config, header)
Example: security.dnsrebinding(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
security.homograph(bool, config, header)
Example: security.homograph(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
security.typosquatting(bool, config, header)
Example: security.typosquatting(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
security.dga(bool, config, header)
Example: security.dga(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
security.newdomains(bool, config, header)
Example: security.newdomains(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
security.parked(bool, config, header)
Example: security.parked(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
security.csam(bool, config, header)
Example: security.csam(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
security.addtld(tld, config, header)
Example: security.addtld(".io", "d46a5b", header)
Response: "{tld} blocked" if success, else ConfigNotFound
security.removetld(tld, config, header)
Example: security.removetld(False, "d46a5b", header)
Response: "{tld} unblocked" if success, else ConfigNotFound
Privacy
privacy.list(config, header)
Example: privacy.list("d46a5b", header)
Response: {'blockDisguised': False, 'allowAffiliate': False, 'blocklists': [{'id': 'nextdns-recommended', 'name': None, 'website': None, 'description': None, 'entries': 95040, 'updatedOn': '2021-10-20T00:30:42.000Z'}], 'natives': [{'id': 'alexa'}, {'id': 'samsung'}]} if success, else ConfigNotFound
privacy.blockdisguised(bool, config, header):
Example: security.csam(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
privacy.blockaffiliate(bool, config, header):
Example: security.blockaffiliate(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
privacy.blocknative(native, config, header):
Example: security.blockaffiliate("xiaomi", "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
privacy.unblocknative(native, config, header):
Example: security.unblocknative("sonos", "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
Parental
parental.list(config, header)
Example: parental.list("d46a5b", header)
Response: {'safeSearch': False, 'youtubeRestrictedMode': True, 'blockBypass': False, 'services': [{'id': 'instagram', 'website': 'https://www.instagram.com', 'recreation': False, 'active': True}], 'categories': [{'id': 'porn', 'recreation': False, 'active': True}], 'recreation': {'tuesday': {'start': '18:00:00', 'end': '20:30:00'}, 'wednesday': {'start': '18:00:00', 'end': '20:30:00'}, 'thursday': {'start': '18:00:00', 'end': '20:30:00'}, 'friday': {'start': '18:00:00', 'end': '20:30:00'}, 'saturday': {'start': '09:00:00', 'end': '20:30:00'}, 'sunday': {'start': '09:00:00', 'end': '20:30:00'}}} if success, else ConfigNotFound
parental.porn(bool, config, header)
Example: parental.porn(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
parental.gambling(bool, config, header)
Example: parental.gambling(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
parental.dating(bool, config, header)
Example: parental.dating(True, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
parental.piracy(bool, config, header)
Example: parental.piracy(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
parental.socialnetworks(bool, config, header)
Example: parental.socialnetworks(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
parental.safesearch(bool, config, header)
Example: parental.safesearch(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
parental.youtubeRestrictedMode(bool, config, header)
Example: parental.youtubeRestrictedMode(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
parental.blockbypass(bool, config, header)
Example: parental.blockbypass(False, "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
parental.blocksite(site, config, header)
Example: parental.blocksite("Instagram", "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
parental.unblocksite(site, config, header)
Example: parental.unblocksite("Snapchat", "d46a5b", header)
Response: "OK" if success, else ConfigNotFound
Denylist
denylist.list(config, header)
Example: denylist.list("d46a5b", header)
Response: [{'domain': 'krunker.io', 'active': True}] if success else ConfigNotFound
denylist.blockdomain(domain, config, header)
Example: denylist.blockdomain("krunker.io", "d46a5b", header)
Response: "OK" if success else ConfigNotFound
denylist.unblockdomain(domain, config, header)
Example: parental.list("krunker.io", "d46a5b", header)
Response: "OK" if success else ConfigNotFound
Allowlist
allowlist.list(config, header)
Example: denylist.list("d46a5b", header)
Response: [{'domain': 'example.com', 'active': True}] if success else ConfigNotFound
allowlist.add(domain, config, header)
Example: allowlist.add("krunker.io", "d46a5b", header)
Response: "OK" if success else ConfigNotFound
allowlist.remove(domain, config, header)
Example: allowlist.remove("krunker.io", "d46a5b", header)
Response: "OK" if success else ConfigNotFound
Analytics
analytics.counter(config, header)
Example: analytics.counter("d46a5b", header)
Response: {'queries': 6736, 'blockedQueries': 208} if success else ConfigNotFound
analytics.topresolveddomains(config, header)
Example: analytics.topresolveddomains("d46a5b", header)
Response: [{'name': 'os-code.shalltry.com', 'queries': 61}, {'name': 'pull-f5.tiktokcdn.com', 'queries': 47}, {'name': 'pull-f5-tt01.fcdn.us.tiktokv.com', 'queries': 45}, {'name': 'pull-f5-va01.tiktokcdn.com', 'queries': 45}, {'name': 'clients3.google.com', 'queries': 45}, {'name': 'mqtt-mini.facebook.com', 'queries': 42}] if success else ConfigNotFound
analytics.topblockeddomains(config, header)
Example: analytics.topblockeddomains("d46a5b", header)
Response: [{'name': 'graph.instagram.com', 'queries': 71}, {'name': 'i.instagram.com', 'queries': 34}, {'name': 'app-measurement.com', 'queries': 26}, {'name': 'www.googleadservices.com', 'queries': 20}, {'name': 'data.flurry.com', 'queries': 15}, {'name': 'googleads.g.doubleclick.net', 'queries': 11}] if success else ConfigNotFound
analytics.toplists(config, header)
Example: analytics.toplists("d46a5b", header)
Response: [{'name': 'Instagram', 'queries': 106}, {'name': 'NextDNS Ads & Trackers Blocklist', 'queries': 103}] if success else ConfigNotFound
analytics.topdevices(config, header)
Example: analytics.topdevices("d46a5b", header)
Response: [{'id': '4SVEZ', 'queries': 6432, 'name': "John Appleseed's iPhone"}] if success else ConfigNotFound
analytics.topclientips(config, header)
Example: analytics.topclientips("d46a5b", header)
Response: [{'ip': '188.34.***.204', 'queries': 4680, 'isCellular': False, 'city': 'Gunzenhausen', 'country': 'Germany', 'countryCode': 'DE', 'isp': 'Hetzner Online GmbH'}, {'ip': '**.210.155.183', 'queries': 1752, 'isCellular': True, 'city': '*****', 'country': 'Timbuktu', 'countryCode': '**', 'isp': '***'}] if success else ConfigNotFound
analytics.toprootdomains(config, header)
Example: analytics.toprootdomains("d46a5b", header)
Response: [{'name': 'tiktokcdn.com', 'queries': 3472}, {'name': 'ttlivecdn.com', 'queries': 1061}, {'name': 'tiktokv.com', 'queries': 416}, {'name': 'gstatic.com', 'queries': 236}, {'name': 'facebook.com', 'queries': 152}, {'name': 'shalltry.com', 'queries': 150}] if success else ConfigNotFound
analytics.gafam(config, header)
Example: analytics.gafam("d46a5b", header)
Response: [{'company': 'google', 'queries': 622, 'percentage': 0.09670398009950248}, {'company': 'facebook', 'queries': 472, 'percentage': 0.07338308457711443}, {'company': 'amazon', 'queries': 0, 'percentage': 0}, {'company': 'apple', 'queries': 0, 'percentage': 0}, {'company': 'microsoft', 'queries': 0, 'percentage': 0}, {'company': 'others', 'queries': 5338, 'percentage': 0.8299129353233831}] if success else ConfigNotFound
analytics.trafficdest(config, header)
Example: analytics.trafficdest("d46a5b", header)
Response: {'DE': {'queries': 3097, 'topDomains': ['mqtt-mini.facebook.com', 'pull-hls-l1-sg01.ttlivecdn.com', 'pull-hls-f1-ab.tiktokcdn.com', 'pull-hls-l1-sg01.tiktokcdn.com', 'pull-hls-f1-sg01.tiktokcdn.com']}, 'US': {'queries': 691, 'topDomains': ['clients3.google.com', 'mtalk.google.com', 'frontier-va.tiktokv.com', 'pull-f5-va01.tiktokcdn.com', 'log22-normal-useast1a.tiktokv.com']}, 'IE': {'queries': 198, 'topDomains': ['os-code.shalltry.com', 'aireport.shalltry.com', 'ds.shalltry.com', 'af.shalltry.com', 'ire-dsu.shalltry.com']}} if success else ConfigNotFound
Contributing
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.
- If you have suggestions for adding or removing projects, feel free to open an issue to discuss it, or directly create a pull request after you edit the README.md file with necessary changes.
- Please make sure you check your spelling and grammar.
- Create individual PR for each suggestion.
- Please also read through the Code Of Conduct before posting your first idea as well.
Creating A Pull Request
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
License
Distributed under the MIT License. See LICENSE for more information.
Authors
Acknowledgements