aitoolsblocklist 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alpha Quantum
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ include README.md
2
+ include LICENSE
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.1
2
+ Name: aitoolsblocklist
3
+ Version: 1.0.0
4
+ Summary: Python client for the AI Tools Blocklist API — classified AI-tool domains for web filtering, DNS security, and DLP.
5
+ Home-page: https://www.aitoolsblocklist.com
6
+ Author: Alpha Quantum
7
+ Author-email: info@alpha-quantum.com
8
+ License: MIT
9
+ Project-URL: Homepage, https://www.aitoolsblocklist.com
10
+ Project-URL: API Documentation, https://www.aitoolsblocklist.com/ai-blocklist-api.php
11
+ Project-URL: Source, https://www.aitoolsblocklist.com
12
+ Description: # aitoolsblocklist
13
+
14
+ A lightweight, production-ready Python client for the [AI Tools Blocklist API](https://www.aitoolsblocklist.com) — a daily-refreshed database of classified AI-tool domains built for web filtering, DNS security, data-loss prevention, and acceptable-use enforcement. The package wraps the REST API in a small, typed, dependency-light interface so security engineers, network administrators, and compliance teams can look up, filter, and synchronize AI-tool domain intelligence directly from Python.
15
+
16
+ The underlying dataset is a specialized extraction from a 102-million-domain enterprise web filtering infrastructure. It contains tens of thousands of AI-tool domains — chatbots, code assistants, image and video generators, voice-cloning services, autonomous agents, AI companions, and more — each classified into functional categories and subcategories rather than a single flat "AI" label. That granularity is what makes per-category policy possible: permit an approved AI tutor while blocking a deepfake generator, or allow a coding assistant while flagging an unvetted document-processing service.
17
+
18
+ ---
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ pip install aitoolsblocklist
24
+ ```
25
+
26
+ The only runtime dependency is [`requests`](https://requests.readthedocs.io/). Python 3.7 and newer are supported.
27
+
28
+ ## Quick start
29
+
30
+ ```python
31
+ from aitoolsblocklist import AIToolsBlocklistClient
32
+
33
+ client = AIToolsBlocklistClient("atb_your_api_key_here")
34
+
35
+ # Single lookup — is this domain an AI tool, and what kind?
36
+ result = client.lookup("claude.ai")
37
+ print(result["in_blocklist"]) # True
38
+ print(result["primary_category"]) # "Text & Language"
39
+ print(result["subcategory"]) # "General assistants & chatbots"
40
+ print(result["risk_tier"]) # "high"
41
+
42
+ # A convenience boolean for policy gates
43
+ if client.is_blocked("midjourney.com"):
44
+ enforce_block_policy("midjourney.com")
45
+ ```
46
+
47
+ An API key is required and is available from the account dashboard after subscribing to any paid plan. Keys use the `atb_` prefix for easy identification in logs, and are passed automatically as a Bearer token on every request.
48
+
49
+ ## Technical overview
50
+
51
+ ### Authentication and configuration
52
+
53
+ The client sends your key in the `Authorization: Bearer` header, requests gzip-compressed responses, and sets a descriptive `User-Agent`. Construction takes a handful of options:
54
+
55
+ ```python
56
+ client = AIToolsBlocklistClient(
57
+ api_key="atb_your_api_key_here",
58
+ base_url="https://api.aitoolsblocklist.com/v1", # override for testing
59
+ timeout=30, # per-request timeout, seconds
60
+ max_retries=3, # automatic backoff on 429 and 5xx
61
+ )
62
+ ```
63
+
64
+ Transient failures — HTTP 429 rate limits and 5xx server errors — are retried automatically with exponential backoff, honoring the `Retry-After` header when present. Authentication problems raise immediately, because retrying a revoked key is pointless.
65
+
66
+ ### Endpoints and methods
67
+
68
+ Each REST endpoint maps to a single method:
69
+
70
+ | Method | Endpoint | Purpose |
71
+ | --- | --- | --- |
72
+ | `lookup(domain)` | `GET /v1/lookup/{domain}` | Classify one domain |
73
+ | `is_blocked(domain)` | — | Convenience boolean wrapper |
74
+ | `bulk_lookup(domains)` | `POST /v1/bulk-lookup` | Classify up to 1,000 domains |
75
+ | `bulk_lookup_all(domains)` | — | Auto-chunks any number of domains |
76
+ | `domains(**filters)` | `GET /v1/domains` | One filtered, paginated page |
77
+ | `iter_domains(**filters)` | — | Iterate the entire filtered list |
78
+ | `delta(since)` | `GET /v1/delta` | Changes since a timestamp |
79
+ | `taxonomy()` | `GET /v1/taxonomy` | Category tree with IDs |
80
+ | `stats()` | `GET /v1/stats` | Database statistics |
81
+
82
+ ### Single and bulk lookups
83
+
84
+ Pass a bare domain — `claude.ai`, not `https://claude.ai/chat`. Subdomains resolve to their registrable domain, so `chat.openai.com` returns the classification for `openai.com`. Both found and not-found responses are HTTP 200; your integration checks one unambiguous `in_blocklist` boolean instead of distinguishing "not found" from "bad request."
85
+
86
+ ```python
87
+ report = client.bulk_lookup(["openai.com", "github.com", "notion.so"])
88
+ for row in report["results"]:
89
+ print(row["domain"], row["in_blocklist"], row.get("primary_category"))
90
+
91
+ # For arbitrarily large inputs, chunking is handled for you:
92
+ everything = client.bulk_lookup_all(my_10000_domains)
93
+ ```
94
+
95
+ ### Loading and synchronizing the full list
96
+
97
+ For a local cache, DNS sinkhole, or firewall External Dynamic List, stream the full classified list. `iter_domains()` walks cursor-based pagination transparently:
98
+
99
+ ```python
100
+ with open("ai_blocklist.txt", "w") as fh:
101
+ for record in client.iter_domains(status="active", min_confidence=0.9):
102
+ fh.write(record["domain"] + "\n")
103
+ ```
104
+
105
+ Then keep it current with a daily delta sync instead of re-downloading everything:
106
+
107
+ ```python
108
+ changes = client.delta(since="2026-07-01T00:00:00Z")
109
+ for added in changes["added"]:
110
+ local_set.add(added["domain"])
111
+ for removed in changes["removed"]:
112
+ local_set.discard(removed["domain"])
113
+ ```
114
+
115
+ This "full load once, delta forever" pattern lets a modest request quota back millions of local lookups, because the actual matching happens in your own Redis, SQLite, or flat file.
116
+
117
+ ### Error handling
118
+
119
+ The client raises a small, specific exception hierarchy so callers can react precisely:
120
+
121
+ ```python
122
+ from aitoolsblocklist import (
123
+ AIToolsBlocklistError, AuthenticationError,
124
+ RateLimitError, NotFoundError,
125
+ )
126
+
127
+ try:
128
+ result = client.lookup("example.com")
129
+ except AuthenticationError:
130
+ ... # 401/403 — rotate or renew the key
131
+ except RateLimitError:
132
+ ... # 429 after retries — back off or upgrade the plan
133
+ except AIToolsBlocklistError:
134
+ ... # any other API or network failure
135
+ ```
136
+
137
+ The client is also a context manager, so the underlying HTTP session is cleaned up automatically:
138
+
139
+ ```python
140
+ with AIToolsBlocklistClient("atb_your_api_key_here") as client:
141
+ print(client.stats())
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Why domain-level AI classification is needed
147
+
148
+ The technical interface above solves a problem that has become urgent for nearly every organization that runs a network: **you can no longer see, let alone govern, where your data goes when employees and students use AI tools.**
149
+
150
+ Two years ago, "AI at work" meant a handful of well-known services. Today, thousands of AI products launch every month, each with its own domain, and each capable of receiving text, code, images, or documents that a user pastes in. A blanket firewall rule cannot keep up, and a hand-maintained list of the famous fifty tools is stale within a week. The result is *shadow AI*: unsanctioned tools processing sensitive information with no oversight. Surveys of enterprise security leaders consistently rank data exposure through generative AI among their fastest-growing risks, and the guidance emerging from public research institutions reflects the same concern.
151
+
152
+ ### The data-governance problem
153
+
154
+ When an employee pastes a customer contract into an unfamiliar AI summarizer, or a developer sends proprietary source code to an online "explain this function" tool, that data leaves the organization's control. It may be logged, used for model training, or retained indefinitely. This is not a hypothetical: the U.S. National Institute of Standards and Technology's [AI Risk Management Framework](https://www.nist.gov/itl/ai-risk-management-framework) explicitly identifies data confidentiality and third-party dependency as core risks to be mapped and managed, and encourages organizations to maintain an inventory of the AI systems their people actually use. You cannot inventory what you cannot see, and you cannot see AI-tool usage at the network layer without knowing which of the millions of domains crossing your egress are AI tools in the first place.
155
+
156
+ Foundational work on the risks of large-scale models — for example, research hosted on [arXiv](https://arxiv.org/) from academic and industry labs — has documented how readily these systems memorize and can surface training data, which is precisely why unsanctioned data submission matters. Domain-level classification is the practical control point: it turns an unbounded, ever-changing population of AI services into a queryable list your existing security stack can act on.
157
+
158
+ ### Education and duty of care
159
+
160
+ Schools face a sharper version of the same problem, layered on top of legal obligations. In the United States, districts that receive certain federal funding must operate a technology protection measure under the Children's Internet Protection Act — the [Federal Communications Commission's CIPA guidance](https://www.fcc.gov/consumer-governmental-affairs/childrens-internet-protection-act) sets out the requirement. AI chatbots, essay generators, and deepfake tools complicate that duty enormously: a district may want to *permit* an approved AI tutor that supports learning while *blocking* an essay-writing service that undermines academic integrity, or a companion-chat app inappropriate for minors. A single "AI" category cannot express that policy; per-subcategory classification can.
161
+
162
+ Academic-integrity offices are grappling with the same distinction. University teaching-and-learning centers — such as the guidance published by [Stanford University](https://www.stanford.edu/) and other institutions on generative AI in coursework — increasingly frame the question not as "AI or no AI" but as "which uses of which tools are appropriate for which assignments." Enforcing a nuanced policy at the network level requires data that is equally nuanced.
163
+
164
+ ### Why a purpose-built, refreshed feed
165
+
166
+ General web-categorization databases were not designed for this. They answer "is this a shopping site, a news site, a social network?" — not "is this an AI code assistant, an AI voice cloner, or an AI research agent?" The pace is also different: general categories are stable for years, whereas AI tools appear and disappear weekly. The dataset behind this client is rebuilt daily precisely so that new tools are caught close to launch rather than months later, and it is organized around the functional distinctions that policy actually turns on.
167
+
168
+ The public-interest research community has long argued that transparency and classification are prerequisites for governing new technologies. Digital-rights organizations such as the [Electronic Frontier Foundation](https://www.eff.org/) emphasize that filtering and monitoring must be precise and accountable rather than blunt — and precision is exactly what per-category domain intelligence enables. A well-classified feed lets an administrator write a rule that blocks a genuine risk category without collaterally breaking legitimate, sanctioned tools, which is the difference between a policy people follow and one they route around.
169
+
170
+ ### Where this package fits
171
+
172
+ This library is the thin, reliable bridge between that intelligence and your own systems. Drop `lookup()` into a proxy plugin or SOAR playbook for real-time decisions; use `iter_domains()` to seed a DNS sinkhole or firewall EDL; run `delta()` on a nightly cron to stay current. Because the heavy matching runs locally against data you have already synced, the approach scales from a single script to millions of lookups a day without hammering the API.
173
+
174
+ If AI-tool visibility and control are on your roadmap — for security, for compliance, or for duty of care — the [AI Tools Blocklist](https://www.aitoolsblocklist.com) provides the data, and this package provides the Python integration.
175
+
176
+ ---
177
+
178
+ ## Links
179
+
180
+ - Product and API documentation: [https://www.aitoolsblocklist.com](https://www.aitoolsblocklist.com)
181
+ - NIST AI Risk Management Framework: [https://www.nist.gov/itl/ai-risk-management-framework](https://www.nist.gov/itl/ai-risk-management-framework)
182
+ - FCC — Children's Internet Protection Act: [https://www.fcc.gov/consumer-governmental-affairs/childrens-internet-protection-act](https://www.fcc.gov/consumer-governmental-affairs/childrens-internet-protection-act)
183
+ - arXiv (open-access research): [https://arxiv.org/](https://arxiv.org/)
184
+
185
+ ## License
186
+
187
+ MIT
188
+
189
+ Keywords: ai tools blocklist,web filtering,dns filtering,content filtering,ai domain classification,shadow ai,data loss prevention,dlp,cipa,acceptable use policy,ai governance,domain categorization
190
+ Platform: UNKNOWN
191
+ Classifier: Development Status :: 5 - Production/Stable
192
+ Classifier: Intended Audience :: Developers
193
+ Classifier: Intended Audience :: Information Technology
194
+ Classifier: License :: OSI Approved :: MIT License
195
+ Classifier: Programming Language :: Python :: 3
196
+ Classifier: Programming Language :: Python :: 3.7
197
+ Classifier: Programming Language :: Python :: 3.8
198
+ Classifier: Programming Language :: Python :: 3.9
199
+ Classifier: Programming Language :: Python :: 3.10
200
+ Classifier: Programming Language :: Python :: 3.11
201
+ Classifier: Programming Language :: Python :: 3.12
202
+ Classifier: Topic :: Internet :: Proxy Servers
203
+ Classifier: Topic :: Security
204
+ Classifier: Topic :: System :: Networking :: Firewalls
205
+ Requires-Python: >=3.7
206
+ Description-Content-Type: text/markdown
@@ -0,0 +1,176 @@
1
+ # aitoolsblocklist
2
+
3
+ A lightweight, production-ready Python client for the [AI Tools Blocklist API](https://www.aitoolsblocklist.com) — a daily-refreshed database of classified AI-tool domains built for web filtering, DNS security, data-loss prevention, and acceptable-use enforcement. The package wraps the REST API in a small, typed, dependency-light interface so security engineers, network administrators, and compliance teams can look up, filter, and synchronize AI-tool domain intelligence directly from Python.
4
+
5
+ The underlying dataset is a specialized extraction from a 102-million-domain enterprise web filtering infrastructure. It contains tens of thousands of AI-tool domains — chatbots, code assistants, image and video generators, voice-cloning services, autonomous agents, AI companions, and more — each classified into functional categories and subcategories rather than a single flat "AI" label. That granularity is what makes per-category policy possible: permit an approved AI tutor while blocking a deepfake generator, or allow a coding assistant while flagging an unvetted document-processing service.
6
+
7
+ ---
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install aitoolsblocklist
13
+ ```
14
+
15
+ The only runtime dependency is [`requests`](https://requests.readthedocs.io/). Python 3.7 and newer are supported.
16
+
17
+ ## Quick start
18
+
19
+ ```python
20
+ from aitoolsblocklist import AIToolsBlocklistClient
21
+
22
+ client = AIToolsBlocklistClient("atb_your_api_key_here")
23
+
24
+ # Single lookup — is this domain an AI tool, and what kind?
25
+ result = client.lookup("claude.ai")
26
+ print(result["in_blocklist"]) # True
27
+ print(result["primary_category"]) # "Text & Language"
28
+ print(result["subcategory"]) # "General assistants & chatbots"
29
+ print(result["risk_tier"]) # "high"
30
+
31
+ # A convenience boolean for policy gates
32
+ if client.is_blocked("midjourney.com"):
33
+ enforce_block_policy("midjourney.com")
34
+ ```
35
+
36
+ An API key is required and is available from the account dashboard after subscribing to any paid plan. Keys use the `atb_` prefix for easy identification in logs, and are passed automatically as a Bearer token on every request.
37
+
38
+ ## Technical overview
39
+
40
+ ### Authentication and configuration
41
+
42
+ The client sends your key in the `Authorization: Bearer` header, requests gzip-compressed responses, and sets a descriptive `User-Agent`. Construction takes a handful of options:
43
+
44
+ ```python
45
+ client = AIToolsBlocklistClient(
46
+ api_key="atb_your_api_key_here",
47
+ base_url="https://api.aitoolsblocklist.com/v1", # override for testing
48
+ timeout=30, # per-request timeout, seconds
49
+ max_retries=3, # automatic backoff on 429 and 5xx
50
+ )
51
+ ```
52
+
53
+ Transient failures — HTTP 429 rate limits and 5xx server errors — are retried automatically with exponential backoff, honoring the `Retry-After` header when present. Authentication problems raise immediately, because retrying a revoked key is pointless.
54
+
55
+ ### Endpoints and methods
56
+
57
+ Each REST endpoint maps to a single method:
58
+
59
+ | Method | Endpoint | Purpose |
60
+ | --- | --- | --- |
61
+ | `lookup(domain)` | `GET /v1/lookup/{domain}` | Classify one domain |
62
+ | `is_blocked(domain)` | — | Convenience boolean wrapper |
63
+ | `bulk_lookup(domains)` | `POST /v1/bulk-lookup` | Classify up to 1,000 domains |
64
+ | `bulk_lookup_all(domains)` | — | Auto-chunks any number of domains |
65
+ | `domains(**filters)` | `GET /v1/domains` | One filtered, paginated page |
66
+ | `iter_domains(**filters)` | — | Iterate the entire filtered list |
67
+ | `delta(since)` | `GET /v1/delta` | Changes since a timestamp |
68
+ | `taxonomy()` | `GET /v1/taxonomy` | Category tree with IDs |
69
+ | `stats()` | `GET /v1/stats` | Database statistics |
70
+
71
+ ### Single and bulk lookups
72
+
73
+ Pass a bare domain — `claude.ai`, not `https://claude.ai/chat`. Subdomains resolve to their registrable domain, so `chat.openai.com` returns the classification for `openai.com`. Both found and not-found responses are HTTP 200; your integration checks one unambiguous `in_blocklist` boolean instead of distinguishing "not found" from "bad request."
74
+
75
+ ```python
76
+ report = client.bulk_lookup(["openai.com", "github.com", "notion.so"])
77
+ for row in report["results"]:
78
+ print(row["domain"], row["in_blocklist"], row.get("primary_category"))
79
+
80
+ # For arbitrarily large inputs, chunking is handled for you:
81
+ everything = client.bulk_lookup_all(my_10000_domains)
82
+ ```
83
+
84
+ ### Loading and synchronizing the full list
85
+
86
+ For a local cache, DNS sinkhole, or firewall External Dynamic List, stream the full classified list. `iter_domains()` walks cursor-based pagination transparently:
87
+
88
+ ```python
89
+ with open("ai_blocklist.txt", "w") as fh:
90
+ for record in client.iter_domains(status="active", min_confidence=0.9):
91
+ fh.write(record["domain"] + "\n")
92
+ ```
93
+
94
+ Then keep it current with a daily delta sync instead of re-downloading everything:
95
+
96
+ ```python
97
+ changes = client.delta(since="2026-07-01T00:00:00Z")
98
+ for added in changes["added"]:
99
+ local_set.add(added["domain"])
100
+ for removed in changes["removed"]:
101
+ local_set.discard(removed["domain"])
102
+ ```
103
+
104
+ This "full load once, delta forever" pattern lets a modest request quota back millions of local lookups, because the actual matching happens in your own Redis, SQLite, or flat file.
105
+
106
+ ### Error handling
107
+
108
+ The client raises a small, specific exception hierarchy so callers can react precisely:
109
+
110
+ ```python
111
+ from aitoolsblocklist import (
112
+ AIToolsBlocklistError, AuthenticationError,
113
+ RateLimitError, NotFoundError,
114
+ )
115
+
116
+ try:
117
+ result = client.lookup("example.com")
118
+ except AuthenticationError:
119
+ ... # 401/403 — rotate or renew the key
120
+ except RateLimitError:
121
+ ... # 429 after retries — back off or upgrade the plan
122
+ except AIToolsBlocklistError:
123
+ ... # any other API or network failure
124
+ ```
125
+
126
+ The client is also a context manager, so the underlying HTTP session is cleaned up automatically:
127
+
128
+ ```python
129
+ with AIToolsBlocklistClient("atb_your_api_key_here") as client:
130
+ print(client.stats())
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Why domain-level AI classification is needed
136
+
137
+ The technical interface above solves a problem that has become urgent for nearly every organization that runs a network: **you can no longer see, let alone govern, where your data goes when employees and students use AI tools.**
138
+
139
+ Two years ago, "AI at work" meant a handful of well-known services. Today, thousands of AI products launch every month, each with its own domain, and each capable of receiving text, code, images, or documents that a user pastes in. A blanket firewall rule cannot keep up, and a hand-maintained list of the famous fifty tools is stale within a week. The result is *shadow AI*: unsanctioned tools processing sensitive information with no oversight. Surveys of enterprise security leaders consistently rank data exposure through generative AI among their fastest-growing risks, and the guidance emerging from public research institutions reflects the same concern.
140
+
141
+ ### The data-governance problem
142
+
143
+ When an employee pastes a customer contract into an unfamiliar AI summarizer, or a developer sends proprietary source code to an online "explain this function" tool, that data leaves the organization's control. It may be logged, used for model training, or retained indefinitely. This is not a hypothetical: the U.S. National Institute of Standards and Technology's [AI Risk Management Framework](https://www.nist.gov/itl/ai-risk-management-framework) explicitly identifies data confidentiality and third-party dependency as core risks to be mapped and managed, and encourages organizations to maintain an inventory of the AI systems their people actually use. You cannot inventory what you cannot see, and you cannot see AI-tool usage at the network layer without knowing which of the millions of domains crossing your egress are AI tools in the first place.
144
+
145
+ Foundational work on the risks of large-scale models — for example, research hosted on [arXiv](https://arxiv.org/) from academic and industry labs — has documented how readily these systems memorize and can surface training data, which is precisely why unsanctioned data submission matters. Domain-level classification is the practical control point: it turns an unbounded, ever-changing population of AI services into a queryable list your existing security stack can act on.
146
+
147
+ ### Education and duty of care
148
+
149
+ Schools face a sharper version of the same problem, layered on top of legal obligations. In the United States, districts that receive certain federal funding must operate a technology protection measure under the Children's Internet Protection Act — the [Federal Communications Commission's CIPA guidance](https://www.fcc.gov/consumer-governmental-affairs/childrens-internet-protection-act) sets out the requirement. AI chatbots, essay generators, and deepfake tools complicate that duty enormously: a district may want to *permit* an approved AI tutor that supports learning while *blocking* an essay-writing service that undermines academic integrity, or a companion-chat app inappropriate for minors. A single "AI" category cannot express that policy; per-subcategory classification can.
150
+
151
+ Academic-integrity offices are grappling with the same distinction. University teaching-and-learning centers — such as the guidance published by [Stanford University](https://www.stanford.edu/) and other institutions on generative AI in coursework — increasingly frame the question not as "AI or no AI" but as "which uses of which tools are appropriate for which assignments." Enforcing a nuanced policy at the network level requires data that is equally nuanced.
152
+
153
+ ### Why a purpose-built, refreshed feed
154
+
155
+ General web-categorization databases were not designed for this. They answer "is this a shopping site, a news site, a social network?" — not "is this an AI code assistant, an AI voice cloner, or an AI research agent?" The pace is also different: general categories are stable for years, whereas AI tools appear and disappear weekly. The dataset behind this client is rebuilt daily precisely so that new tools are caught close to launch rather than months later, and it is organized around the functional distinctions that policy actually turns on.
156
+
157
+ The public-interest research community has long argued that transparency and classification are prerequisites for governing new technologies. Digital-rights organizations such as the [Electronic Frontier Foundation](https://www.eff.org/) emphasize that filtering and monitoring must be precise and accountable rather than blunt — and precision is exactly what per-category domain intelligence enables. A well-classified feed lets an administrator write a rule that blocks a genuine risk category without collaterally breaking legitimate, sanctioned tools, which is the difference between a policy people follow and one they route around.
158
+
159
+ ### Where this package fits
160
+
161
+ This library is the thin, reliable bridge between that intelligence and your own systems. Drop `lookup()` into a proxy plugin or SOAR playbook for real-time decisions; use `iter_domains()` to seed a DNS sinkhole or firewall EDL; run `delta()` on a nightly cron to stay current. Because the heavy matching runs locally against data you have already synced, the approach scales from a single script to millions of lookups a day without hammering the API.
162
+
163
+ If AI-tool visibility and control are on your roadmap — for security, for compliance, or for duty of care — the [AI Tools Blocklist](https://www.aitoolsblocklist.com) provides the data, and this package provides the Python integration.
164
+
165
+ ---
166
+
167
+ ## Links
168
+
169
+ - Product and API documentation: [https://www.aitoolsblocklist.com](https://www.aitoolsblocklist.com)
170
+ - NIST AI Risk Management Framework: [https://www.nist.gov/itl/ai-risk-management-framework](https://www.nist.gov/itl/ai-risk-management-framework)
171
+ - FCC — Children's Internet Protection Act: [https://www.fcc.gov/consumer-governmental-affairs/childrens-internet-protection-act](https://www.fcc.gov/consumer-governmental-affairs/childrens-internet-protection-act)
172
+ - arXiv (open-access research): [https://arxiv.org/](https://arxiv.org/)
173
+
174
+ ## License
175
+
176
+ MIT
@@ -0,0 +1,25 @@
1
+ """
2
+ aitoolsblocklist — Python client for the AI Tools Blocklist API.
3
+
4
+ A small, dependency-light wrapper around the REST API at
5
+ https://www.aitoolsblocklist.com that lets security, networking and
6
+ compliance teams look up, filter, and synchronize classified AI-tool
7
+ domains from Python.
8
+ """
9
+
10
+ from .client import (
11
+ AIToolsBlocklistClient,
12
+ AIToolsBlocklistError,
13
+ AuthenticationError,
14
+ RateLimitError,
15
+ NotFoundError,
16
+ )
17
+
18
+ __version__ = "1.0.0"
19
+ __all__ = [
20
+ "AIToolsBlocklistClient",
21
+ "AIToolsBlocklistError",
22
+ "AuthenticationError",
23
+ "RateLimitError",
24
+ "NotFoundError",
25
+ ]
@@ -0,0 +1,243 @@
1
+ """
2
+ AI Tools Blocklist API client.
3
+
4
+ Wraps the REST endpoints documented at
5
+ https://www.aitoolsblocklist.com/ai-blocklist-api.php:
6
+
7
+ GET /v1/lookup/{domain} single domain classification
8
+ GET /v1/domains full classified list with filters
9
+ GET /v1/delta changes since a timestamp
10
+ POST /v1/bulk-lookup classify up to 1,000 domains
11
+ GET /v1/taxonomy category tree
12
+ GET /v1/stats database statistics
13
+
14
+ Only the standard library and ``requests`` are required.
15
+ """
16
+
17
+ import time
18
+ from typing import Dict, Iterator, List, Optional
19
+
20
+ import requests
21
+
22
+ DEFAULT_BASE_URL = "https://api.aitoolsblocklist.com/v1"
23
+ DEFAULT_TIMEOUT = 30
24
+ USER_AGENT = "aitoolsblocklist-python/1.0.0 (+https://www.aitoolsblocklist.com)"
25
+
26
+
27
+ class AIToolsBlocklistError(Exception):
28
+ """Base exception for all client errors."""
29
+
30
+
31
+ class AuthenticationError(AIToolsBlocklistError):
32
+ """Raised on 401/403 — missing, invalid, expired or revoked API key."""
33
+
34
+
35
+ class RateLimitError(AIToolsBlocklistError):
36
+ """Raised on 429 — request quota exceeded for the current plan."""
37
+
38
+
39
+ class NotFoundError(AIToolsBlocklistError):
40
+ """Raised on 404 — resource or endpoint not found."""
41
+
42
+
43
+ class AIToolsBlocklistClient:
44
+ """
45
+ Client for the AI Tools Blocklist API.
46
+
47
+ Args:
48
+ api_key: Your ``atb_`` API key from the account dashboard.
49
+ base_url: Override the API base URL (useful for testing).
50
+ timeout: Per-request timeout in seconds.
51
+ max_retries: Automatic retries on 429 / 5xx with backoff.
52
+
53
+ Example:
54
+ >>> from aitoolsblocklist import AIToolsBlocklistClient
55
+ >>> client = AIToolsBlocklistClient("atb_your_api_key_here")
56
+ >>> result = client.lookup("claude.ai")
57
+ >>> result["in_blocklist"]
58
+ True
59
+ >>> result["primary_category"]
60
+ 'Text & Language'
61
+ """
62
+
63
+ def __init__(
64
+ self,
65
+ api_key: str,
66
+ base_url: str = DEFAULT_BASE_URL,
67
+ timeout: int = DEFAULT_TIMEOUT,
68
+ max_retries: int = 3,
69
+ ):
70
+ if not api_key:
71
+ raise ValueError("api_key is required")
72
+ self.api_key = api_key
73
+ self.base_url = base_url.rstrip("/")
74
+ self.timeout = timeout
75
+ self.max_retries = max_retries
76
+ self._session = requests.Session()
77
+ self._session.headers.update(
78
+ {
79
+ "Authorization": f"Bearer {api_key}",
80
+ "Accept": "application/json",
81
+ "Accept-Encoding": "gzip",
82
+ "User-Agent": USER_AGENT,
83
+ }
84
+ )
85
+
86
+ # ---- internal request helper -------------------------------------
87
+
88
+ def _request(self, method: str, path: str, **kwargs) -> Dict:
89
+ url = f"{self.base_url}/{path.lstrip('/')}"
90
+ last_exc = None
91
+ for attempt in range(self.max_retries + 1):
92
+ try:
93
+ resp = self._session.request(method, url, timeout=self.timeout, **kwargs)
94
+ except requests.RequestException as exc: # network-level errors
95
+ last_exc = exc
96
+ if attempt < self.max_retries:
97
+ time.sleep(2 ** attempt)
98
+ continue
99
+ raise AIToolsBlocklistError(f"Request to {url} failed: {exc}") from exc
100
+
101
+ if resp.status_code in (200, 201):
102
+ return resp.json()
103
+ if resp.status_code == 401:
104
+ raise AuthenticationError(self._msg(resp, "Invalid or missing API key."))
105
+ if resp.status_code == 403:
106
+ raise AuthenticationError(self._msg(resp, "API key revoked or plan does not include this endpoint."))
107
+ if resp.status_code == 404:
108
+ raise NotFoundError(self._msg(resp, "Resource not found."))
109
+ if resp.status_code == 429:
110
+ if attempt < self.max_retries:
111
+ retry_after = int(resp.headers.get("Retry-After", 2 ** attempt))
112
+ time.sleep(retry_after)
113
+ continue
114
+ raise RateLimitError(self._msg(resp, "Rate limit exceeded."))
115
+ if resp.status_code >= 500:
116
+ if attempt < self.max_retries:
117
+ time.sleep(2 ** attempt)
118
+ continue
119
+ raise AIToolsBlocklistError(self._msg(resp, "Server error."))
120
+ raise AIToolsBlocklistError(self._msg(resp, f"Unexpected status {resp.status_code}."))
121
+ raise AIToolsBlocklistError(f"Request failed after retries: {last_exc}")
122
+
123
+ @staticmethod
124
+ def _msg(resp: requests.Response, default: str) -> str:
125
+ try:
126
+ body = resp.json()
127
+ return body.get("message") or body.get("error") or default
128
+ except ValueError:
129
+ return default
130
+
131
+ # ---- public API --------------------------------------------------
132
+
133
+ def lookup(self, domain: str) -> Dict:
134
+ """
135
+ Classify a single domain.
136
+
137
+ Pass the bare domain (``claude.ai``), not a URL. Subdomains resolve
138
+ to their registrable domain, so ``chat.openai.com`` returns the
139
+ classification for ``openai.com``. Both found and not-found return
140
+ HTTP 200; check the ``in_blocklist`` boolean.
141
+ """
142
+ domain = self._clean_domain(domain)
143
+ return self._request("GET", f"/lookup/{domain}")
144
+
145
+ def is_blocked(self, domain: str) -> bool:
146
+ """Convenience helper returning just the ``in_blocklist`` boolean."""
147
+ return bool(self.lookup(domain).get("in_blocklist", False))
148
+
149
+ def bulk_lookup(self, domains: List[str]) -> Dict:
150
+ """
151
+ Classify up to 1,000 domains in a single request. For larger inputs,
152
+ use :meth:`bulk_lookup_all`, which chunks automatically.
153
+ """
154
+ if len(domains) > 1000:
155
+ raise ValueError("bulk_lookup accepts at most 1000 domains; use bulk_lookup_all().")
156
+ cleaned = [self._clean_domain(d) for d in domains]
157
+ return self._request("POST", "/bulk-lookup", json={"domains": cleaned})
158
+
159
+ def bulk_lookup_all(self, domains: List[str]) -> List[Dict]:
160
+ """Classify any number of domains by chunking into 1,000-item calls."""
161
+ results: List[Dict] = []
162
+ for i in range(0, len(domains), 1000):
163
+ chunk = domains[i : i + 1000]
164
+ resp = self.bulk_lookup(chunk)
165
+ results.extend(resp.get("results", resp.get("domains", [])))
166
+ return results
167
+
168
+ def domains(
169
+ self,
170
+ category: Optional[str] = None,
171
+ min_confidence: Optional[float] = None,
172
+ risk_tier: Optional[str] = None,
173
+ status: Optional[str] = None,
174
+ cursor: Optional[str] = None,
175
+ ) -> Dict:
176
+ """
177
+ Return one page of the classified domain list. Supports filtering by
178
+ ``category``, ``min_confidence``, ``risk_tier`` and ``status``, and
179
+ cursor-based pagination. For the entire list, use :meth:`iter_domains`.
180
+ """
181
+ params = {}
182
+ if category:
183
+ params["category"] = category
184
+ if min_confidence is not None:
185
+ params["min_confidence"] = min_confidence
186
+ if risk_tier:
187
+ params["risk_tier"] = risk_tier
188
+ if status:
189
+ params["status"] = status
190
+ if cursor:
191
+ params["cursor"] = cursor
192
+ return self._request("GET", "/domains", params=params)
193
+
194
+ def iter_domains(self, **filters) -> Iterator[Dict]:
195
+ """
196
+ Yield every domain record matching ``filters``, transparently walking
197
+ cursor-based pagination. Ideal for loading a local cache, DNS
198
+ sinkhole, or firewall External Dynamic List.
199
+ """
200
+ cursor = None
201
+ while True:
202
+ page = self.domains(cursor=cursor, **filters)
203
+ for record in page.get("domains", []):
204
+ yield record
205
+ cursor = page.get("next_cursor")
206
+ if not cursor:
207
+ break
208
+
209
+ def delta(self, since: str) -> Dict:
210
+ """
211
+ Return additions, changes and removals since an ISO-8601 timestamp.
212
+ Run this on a daily cron to keep a local copy current without
213
+ re-downloading the full list.
214
+ """
215
+ return self._request("GET", "/delta", params={"since": since})
216
+
217
+ def taxonomy(self) -> Dict:
218
+ """Return the category tree (18 functional categories and their subcategories)."""
219
+ return self._request("GET", "/taxonomy")
220
+
221
+ def stats(self) -> Dict:
222
+ """Return database statistics: total domains, per-category counts, last refresh."""
223
+ return self._request("GET", "/stats")
224
+
225
+ # ---- helpers -----------------------------------------------------
226
+
227
+ @staticmethod
228
+ def _clean_domain(domain: str) -> str:
229
+ d = domain.strip().lower()
230
+ for prefix in ("https://", "http://"):
231
+ if d.startswith(prefix):
232
+ d = d[len(prefix):]
233
+ d = d.split("/")[0].split("?")[0]
234
+ return d
235
+
236
+ def close(self) -> None:
237
+ self._session.close()
238
+
239
+ def __enter__(self):
240
+ return self
241
+
242
+ def __exit__(self, *exc):
243
+ self.close()
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.1
2
+ Name: aitoolsblocklist
3
+ Version: 1.0.0
4
+ Summary: Python client for the AI Tools Blocklist API — classified AI-tool domains for web filtering, DNS security, and DLP.
5
+ Home-page: https://www.aitoolsblocklist.com
6
+ Author: Alpha Quantum
7
+ Author-email: info@alpha-quantum.com
8
+ License: MIT
9
+ Project-URL: Homepage, https://www.aitoolsblocklist.com
10
+ Project-URL: API Documentation, https://www.aitoolsblocklist.com/ai-blocklist-api.php
11
+ Project-URL: Source, https://www.aitoolsblocklist.com
12
+ Description: # aitoolsblocklist
13
+
14
+ A lightweight, production-ready Python client for the [AI Tools Blocklist API](https://www.aitoolsblocklist.com) — a daily-refreshed database of classified AI-tool domains built for web filtering, DNS security, data-loss prevention, and acceptable-use enforcement. The package wraps the REST API in a small, typed, dependency-light interface so security engineers, network administrators, and compliance teams can look up, filter, and synchronize AI-tool domain intelligence directly from Python.
15
+
16
+ The underlying dataset is a specialized extraction from a 102-million-domain enterprise web filtering infrastructure. It contains tens of thousands of AI-tool domains — chatbots, code assistants, image and video generators, voice-cloning services, autonomous agents, AI companions, and more — each classified into functional categories and subcategories rather than a single flat "AI" label. That granularity is what makes per-category policy possible: permit an approved AI tutor while blocking a deepfake generator, or allow a coding assistant while flagging an unvetted document-processing service.
17
+
18
+ ---
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ pip install aitoolsblocklist
24
+ ```
25
+
26
+ The only runtime dependency is [`requests`](https://requests.readthedocs.io/). Python 3.7 and newer are supported.
27
+
28
+ ## Quick start
29
+
30
+ ```python
31
+ from aitoolsblocklist import AIToolsBlocklistClient
32
+
33
+ client = AIToolsBlocklistClient("atb_your_api_key_here")
34
+
35
+ # Single lookup — is this domain an AI tool, and what kind?
36
+ result = client.lookup("claude.ai")
37
+ print(result["in_blocklist"]) # True
38
+ print(result["primary_category"]) # "Text & Language"
39
+ print(result["subcategory"]) # "General assistants & chatbots"
40
+ print(result["risk_tier"]) # "high"
41
+
42
+ # A convenience boolean for policy gates
43
+ if client.is_blocked("midjourney.com"):
44
+ enforce_block_policy("midjourney.com")
45
+ ```
46
+
47
+ An API key is required and is available from the account dashboard after subscribing to any paid plan. Keys use the `atb_` prefix for easy identification in logs, and are passed automatically as a Bearer token on every request.
48
+
49
+ ## Technical overview
50
+
51
+ ### Authentication and configuration
52
+
53
+ The client sends your key in the `Authorization: Bearer` header, requests gzip-compressed responses, and sets a descriptive `User-Agent`. Construction takes a handful of options:
54
+
55
+ ```python
56
+ client = AIToolsBlocklistClient(
57
+ api_key="atb_your_api_key_here",
58
+ base_url="https://api.aitoolsblocklist.com/v1", # override for testing
59
+ timeout=30, # per-request timeout, seconds
60
+ max_retries=3, # automatic backoff on 429 and 5xx
61
+ )
62
+ ```
63
+
64
+ Transient failures — HTTP 429 rate limits and 5xx server errors — are retried automatically with exponential backoff, honoring the `Retry-After` header when present. Authentication problems raise immediately, because retrying a revoked key is pointless.
65
+
66
+ ### Endpoints and methods
67
+
68
+ Each REST endpoint maps to a single method:
69
+
70
+ | Method | Endpoint | Purpose |
71
+ | --- | --- | --- |
72
+ | `lookup(domain)` | `GET /v1/lookup/{domain}` | Classify one domain |
73
+ | `is_blocked(domain)` | — | Convenience boolean wrapper |
74
+ | `bulk_lookup(domains)` | `POST /v1/bulk-lookup` | Classify up to 1,000 domains |
75
+ | `bulk_lookup_all(domains)` | — | Auto-chunks any number of domains |
76
+ | `domains(**filters)` | `GET /v1/domains` | One filtered, paginated page |
77
+ | `iter_domains(**filters)` | — | Iterate the entire filtered list |
78
+ | `delta(since)` | `GET /v1/delta` | Changes since a timestamp |
79
+ | `taxonomy()` | `GET /v1/taxonomy` | Category tree with IDs |
80
+ | `stats()` | `GET /v1/stats` | Database statistics |
81
+
82
+ ### Single and bulk lookups
83
+
84
+ Pass a bare domain — `claude.ai`, not `https://claude.ai/chat`. Subdomains resolve to their registrable domain, so `chat.openai.com` returns the classification for `openai.com`. Both found and not-found responses are HTTP 200; your integration checks one unambiguous `in_blocklist` boolean instead of distinguishing "not found" from "bad request."
85
+
86
+ ```python
87
+ report = client.bulk_lookup(["openai.com", "github.com", "notion.so"])
88
+ for row in report["results"]:
89
+ print(row["domain"], row["in_blocklist"], row.get("primary_category"))
90
+
91
+ # For arbitrarily large inputs, chunking is handled for you:
92
+ everything = client.bulk_lookup_all(my_10000_domains)
93
+ ```
94
+
95
+ ### Loading and synchronizing the full list
96
+
97
+ For a local cache, DNS sinkhole, or firewall External Dynamic List, stream the full classified list. `iter_domains()` walks cursor-based pagination transparently:
98
+
99
+ ```python
100
+ with open("ai_blocklist.txt", "w") as fh:
101
+ for record in client.iter_domains(status="active", min_confidence=0.9):
102
+ fh.write(record["domain"] + "\n")
103
+ ```
104
+
105
+ Then keep it current with a daily delta sync instead of re-downloading everything:
106
+
107
+ ```python
108
+ changes = client.delta(since="2026-07-01T00:00:00Z")
109
+ for added in changes["added"]:
110
+ local_set.add(added["domain"])
111
+ for removed in changes["removed"]:
112
+ local_set.discard(removed["domain"])
113
+ ```
114
+
115
+ This "full load once, delta forever" pattern lets a modest request quota back millions of local lookups, because the actual matching happens in your own Redis, SQLite, or flat file.
116
+
117
+ ### Error handling
118
+
119
+ The client raises a small, specific exception hierarchy so callers can react precisely:
120
+
121
+ ```python
122
+ from aitoolsblocklist import (
123
+ AIToolsBlocklistError, AuthenticationError,
124
+ RateLimitError, NotFoundError,
125
+ )
126
+
127
+ try:
128
+ result = client.lookup("example.com")
129
+ except AuthenticationError:
130
+ ... # 401/403 — rotate or renew the key
131
+ except RateLimitError:
132
+ ... # 429 after retries — back off or upgrade the plan
133
+ except AIToolsBlocklistError:
134
+ ... # any other API or network failure
135
+ ```
136
+
137
+ The client is also a context manager, so the underlying HTTP session is cleaned up automatically:
138
+
139
+ ```python
140
+ with AIToolsBlocklistClient("atb_your_api_key_here") as client:
141
+ print(client.stats())
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Why domain-level AI classification is needed
147
+
148
+ The technical interface above solves a problem that has become urgent for nearly every organization that runs a network: **you can no longer see, let alone govern, where your data goes when employees and students use AI tools.**
149
+
150
+ Two years ago, "AI at work" meant a handful of well-known services. Today, thousands of AI products launch every month, each with its own domain, and each capable of receiving text, code, images, or documents that a user pastes in. A blanket firewall rule cannot keep up, and a hand-maintained list of the famous fifty tools is stale within a week. The result is *shadow AI*: unsanctioned tools processing sensitive information with no oversight. Surveys of enterprise security leaders consistently rank data exposure through generative AI among their fastest-growing risks, and the guidance emerging from public research institutions reflects the same concern.
151
+
152
+ ### The data-governance problem
153
+
154
+ When an employee pastes a customer contract into an unfamiliar AI summarizer, or a developer sends proprietary source code to an online "explain this function" tool, that data leaves the organization's control. It may be logged, used for model training, or retained indefinitely. This is not a hypothetical: the U.S. National Institute of Standards and Technology's [AI Risk Management Framework](https://www.nist.gov/itl/ai-risk-management-framework) explicitly identifies data confidentiality and third-party dependency as core risks to be mapped and managed, and encourages organizations to maintain an inventory of the AI systems their people actually use. You cannot inventory what you cannot see, and you cannot see AI-tool usage at the network layer without knowing which of the millions of domains crossing your egress are AI tools in the first place.
155
+
156
+ Foundational work on the risks of large-scale models — for example, research hosted on [arXiv](https://arxiv.org/) from academic and industry labs — has documented how readily these systems memorize and can surface training data, which is precisely why unsanctioned data submission matters. Domain-level classification is the practical control point: it turns an unbounded, ever-changing population of AI services into a queryable list your existing security stack can act on.
157
+
158
+ ### Education and duty of care
159
+
160
+ Schools face a sharper version of the same problem, layered on top of legal obligations. In the United States, districts that receive certain federal funding must operate a technology protection measure under the Children's Internet Protection Act — the [Federal Communications Commission's CIPA guidance](https://www.fcc.gov/consumer-governmental-affairs/childrens-internet-protection-act) sets out the requirement. AI chatbots, essay generators, and deepfake tools complicate that duty enormously: a district may want to *permit* an approved AI tutor that supports learning while *blocking* an essay-writing service that undermines academic integrity, or a companion-chat app inappropriate for minors. A single "AI" category cannot express that policy; per-subcategory classification can.
161
+
162
+ Academic-integrity offices are grappling with the same distinction. University teaching-and-learning centers — such as the guidance published by [Stanford University](https://www.stanford.edu/) and other institutions on generative AI in coursework — increasingly frame the question not as "AI or no AI" but as "which uses of which tools are appropriate for which assignments." Enforcing a nuanced policy at the network level requires data that is equally nuanced.
163
+
164
+ ### Why a purpose-built, refreshed feed
165
+
166
+ General web-categorization databases were not designed for this. They answer "is this a shopping site, a news site, a social network?" — not "is this an AI code assistant, an AI voice cloner, or an AI research agent?" The pace is also different: general categories are stable for years, whereas AI tools appear and disappear weekly. The dataset behind this client is rebuilt daily precisely so that new tools are caught close to launch rather than months later, and it is organized around the functional distinctions that policy actually turns on.
167
+
168
+ The public-interest research community has long argued that transparency and classification are prerequisites for governing new technologies. Digital-rights organizations such as the [Electronic Frontier Foundation](https://www.eff.org/) emphasize that filtering and monitoring must be precise and accountable rather than blunt — and precision is exactly what per-category domain intelligence enables. A well-classified feed lets an administrator write a rule that blocks a genuine risk category without collaterally breaking legitimate, sanctioned tools, which is the difference between a policy people follow and one they route around.
169
+
170
+ ### Where this package fits
171
+
172
+ This library is the thin, reliable bridge between that intelligence and your own systems. Drop `lookup()` into a proxy plugin or SOAR playbook for real-time decisions; use `iter_domains()` to seed a DNS sinkhole or firewall EDL; run `delta()` on a nightly cron to stay current. Because the heavy matching runs locally against data you have already synced, the approach scales from a single script to millions of lookups a day without hammering the API.
173
+
174
+ If AI-tool visibility and control are on your roadmap — for security, for compliance, or for duty of care — the [AI Tools Blocklist](https://www.aitoolsblocklist.com) provides the data, and this package provides the Python integration.
175
+
176
+ ---
177
+
178
+ ## Links
179
+
180
+ - Product and API documentation: [https://www.aitoolsblocklist.com](https://www.aitoolsblocklist.com)
181
+ - NIST AI Risk Management Framework: [https://www.nist.gov/itl/ai-risk-management-framework](https://www.nist.gov/itl/ai-risk-management-framework)
182
+ - FCC — Children's Internet Protection Act: [https://www.fcc.gov/consumer-governmental-affairs/childrens-internet-protection-act](https://www.fcc.gov/consumer-governmental-affairs/childrens-internet-protection-act)
183
+ - arXiv (open-access research): [https://arxiv.org/](https://arxiv.org/)
184
+
185
+ ## License
186
+
187
+ MIT
188
+
189
+ Keywords: ai tools blocklist,web filtering,dns filtering,content filtering,ai domain classification,shadow ai,data loss prevention,dlp,cipa,acceptable use policy,ai governance,domain categorization
190
+ Platform: UNKNOWN
191
+ Classifier: Development Status :: 5 - Production/Stable
192
+ Classifier: Intended Audience :: Developers
193
+ Classifier: Intended Audience :: Information Technology
194
+ Classifier: License :: OSI Approved :: MIT License
195
+ Classifier: Programming Language :: Python :: 3
196
+ Classifier: Programming Language :: Python :: 3.7
197
+ Classifier: Programming Language :: Python :: 3.8
198
+ Classifier: Programming Language :: Python :: 3.9
199
+ Classifier: Programming Language :: Python :: 3.10
200
+ Classifier: Programming Language :: Python :: 3.11
201
+ Classifier: Programming Language :: Python :: 3.12
202
+ Classifier: Topic :: Internet :: Proxy Servers
203
+ Classifier: Topic :: Security
204
+ Classifier: Topic :: System :: Networking :: Firewalls
205
+ Requires-Python: >=3.7
206
+ Description-Content-Type: text/markdown
@@ -0,0 +1,11 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ setup.py
5
+ aitoolsblocklist/__init__.py
6
+ aitoolsblocklist/client.py
7
+ aitoolsblocklist.egg-info/PKG-INFO
8
+ aitoolsblocklist.egg-info/SOURCES.txt
9
+ aitoolsblocklist.egg-info/dependency_links.txt
10
+ aitoolsblocklist.egg-info/requires.txt
11
+ aitoolsblocklist.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ requests>=2.20.0
@@ -0,0 +1 @@
1
+ aitoolsblocklist
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,46 @@
1
+ import pathlib
2
+ from setuptools import setup, find_packages
3
+
4
+ HERE = pathlib.Path(__file__).parent
5
+ README = (HERE / "README.md").read_text(encoding="utf-8")
6
+
7
+ setup(
8
+ name="aitoolsblocklist",
9
+ version="1.0.0",
10
+ description="Python client for the AI Tools Blocklist API — classified AI-tool domains for web filtering, DNS security, and DLP.",
11
+ long_description=README,
12
+ long_description_content_type="text/markdown",
13
+ author="Alpha Quantum",
14
+ author_email="info@alpha-quantum.com",
15
+ url="https://www.aitoolsblocklist.com",
16
+ project_urls={
17
+ "Homepage": "https://www.aitoolsblocklist.com",
18
+ "API Documentation": "https://www.aitoolsblocklist.com/ai-blocklist-api.php",
19
+ "Source": "https://www.aitoolsblocklist.com",
20
+ },
21
+ license="MIT",
22
+ packages=find_packages(exclude=("tests", "test")),
23
+ python_requires=">=3.7",
24
+ install_requires=["requests>=2.20.0"],
25
+ keywords=[
26
+ "ai tools blocklist", "web filtering", "dns filtering", "content filtering",
27
+ "ai domain classification", "shadow ai", "data loss prevention", "dlp",
28
+ "cipa", "acceptable use policy", "ai governance", "domain categorization",
29
+ ],
30
+ classifiers=[
31
+ "Development Status :: 5 - Production/Stable",
32
+ "Intended Audience :: Developers",
33
+ "Intended Audience :: Information Technology",
34
+ "License :: OSI Approved :: MIT License",
35
+ "Programming Language :: Python :: 3",
36
+ "Programming Language :: Python :: 3.7",
37
+ "Programming Language :: Python :: 3.8",
38
+ "Programming Language :: Python :: 3.9",
39
+ "Programming Language :: Python :: 3.10",
40
+ "Programming Language :: Python :: 3.11",
41
+ "Programming Language :: Python :: 3.12",
42
+ "Topic :: Internet :: Proxy Servers",
43
+ "Topic :: Security",
44
+ "Topic :: System :: Networking :: Firewalls",
45
+ ],
46
+ )