aitoolsblocklist
aitoolsblocklist gives Python code a direct line to AI blocking data. You pass it a domain, and it tells you whether that domain is an AI tool, what the tool does, and what its vendor promises about training on your data. It also downloads the whole classified list for systems that need to match locally.
Who reaches for it: security engineers writing proxy plugins, network admins seeding a DNS sinkhole, compliance analysts building an AI inventory in a notebook, and school IT staff scripting a filtering policy. The list behind it holds more than 20,000 AI tool domains, sorted into 18 functional categories with subcategories, so a rule can separate a tutoring assistant from a voice cloner rather than treating "AI" as one thing. Each record also carries the vendor's training terms and the date they were checked.
Installation
pip install aitoolsblocklist
It needs Python 3.7 or later and pulls in one dependency, the requests library.
Quick start
from aitoolsblocklist import AIToolsBlocklistClient
client = AIToolsBlocklistClient("YOUR_API_KEY")
# Single lookup: is this domain an AI tool, and what kind?
result = client.lookup("chatgpt.com")
print(result["blocked"]) # True
print(result["primary_category"]) # "Text & Language"
print(result["ai_type"]) # "ai_native"
print(result["categories"]) # [{"category": "Text & Language", "subcategory": "General assistants & chatbots"}]
print(result["trains_on_data"]) # "opt_out_default"
print(result["terms_checked"]) # "2026-09-17"
# A convenience boolean for policy gates
if client.is_blocked("midjourney.com"):
enforce_block_policy("midjourney.com")
Every paid plan comes with a key, which you copy from your account page. The client puts it in the X-API-Key header for you. Billing counts calls to lookup() only: stats(), taxonomy() and clause() are free and work without a key at all.
Three ways people use it
Per request. A proxy add-on, a browser extension backend or a SOAR playbook calls lookup() when a new domain appears and caches the answer. This suits low volume and moments when a decision has to be current.
In batches. An analyst has a spreadsheet of domains from a log export, a vendor questionnaire or an M&A due-diligence list. bulk_lookup() walks the list, skips duplicates and returns rows in the original order, ready for pandas.
From a local copy. Anything that sees every DNS query, such as a resolver, sinkhole or firewall, should never call out per query. Feed and database plans let download_database() fetch the full CSV, and matching happens in your own memory, SQLite or Redis.
The sections below cover each path.
Client reference
Constructor
client = AIToolsBlocklistClient(
api_key="YOUR_API_KEY",
base_url="https://www.aitoolsblocklist.com", # default
timeout=30, # per-request timeout, seconds; downloads use at least 300
max_retries=3, # automatic backoff on 429, 503 and network errors
)
Retries use exponential backoff and respect a Retry-After header if the server sends one. Only throttling (429), temporary unavailability (503) and network faults are retried. A rejected key fails at once, since repeating the call cannot help.
Methods at a glance
| Method | Endpoint | Key | Purpose |
|---|---|---|---|
lookup(domain) |
GET /api/check?domain= |
yes | Classify one domain |
is_blocked(domain) |
same | yes | Convenience boolean |
bulk_lookup(domains, pause) |
same, sequential | yes | Deduplicated lookups, {"results": [...]} in input order |
bulk_lookup_all(domains, pause) |
same | yes | The flat list |
data_use(domain) |
same | yes | The five vendor data-use fields |
stats() |
GET /api/stats.php |
no | Totals and the 18 categories with counts |
taxonomy() |
same | no | {name: {total, subcategories}} |
clause(domain, field) |
GET /api/data-use-clause.php |
no | Verbatim vendor clause with URL |
database_status() |
GET /api/database/?action=status |
feed or database plan | Plan and file state |
database_info() |
GET /api/database/?action=database_info |
feed or database plan | File name, timestamp, size |
download_database(path) |
GET /api/database/?action=download_database |
feed or database plan | Stream the full CSV to disk |
download_categories(path) |
GET /api/database/?action=download_categories |
feed or database plan | Stream the category tree CSV |
Input handling and responses
You can hand lookup() anything from chatgpt.com to a full link with a path. The client removes the scheme, the path and any leading www. before sending. A subdomain is judged by its registrable parent, which is why chat.openai.com comes back with the record for openai.com. Unknown domains are not an error: they return HTTP 200 with blocked: false, so your code branches on one boolean.
report = client.bulk_lookup(["openai.com", "github.com", "notion.so"], pause=0.05)
for row in report["results"]:
print(row["domain"], row["blocked"], row.get("primary_category"), row.get("trains_on_data"))
Here is what a hit looks like:
{
"domain": "chatgpt.com",
"blocked": true,
"primary_category": "Text & Language",
"ai_type": "ai_native",
"categories": [{"category": "Text & Language", "subcategory": "General assistants & chatbots"}],
"trains_on_data": "opt_out_default",
"opt_out_available": "yes",
"enterprise_no_training": "yes",
"api_no_training": "yes",
"terms_checked": "2026-09-17",
"quota_remaining": 9999986
}
The four data-use fields take one of yes, no, opt_out_default or unstated. unstated is a result, not a gap: the terms were read and say nothing on that point. ai_type separates products whose core is AI (ai_native) from ordinary products that have added an AI feature (ai_enabled). For a domain outside the list, categories is empty.
Working from a local copy
On a feed or database plan, pull the whole classified CSV once and do the matching in memory:
info = client.database_info()
print(info["database_file"], info["last_updated"], info["file_size_human"])
client.download_database("/var/lib/atb/ai_tools_full.csv")
client.download_categories("/var/lib/atb/ai_tools_categories.csv")
import csv
blocked = {row["domain"] for row in csv.DictReader(open("/var/lib/atb/ai_tools_full.csv", encoding="utf-8"))
if row["primary_category"] in {"Image & Visual", "Audio & Voice"}}
The file is rebuilt every day, so schedule the download for the night. After that, lookups cost nothing, however many millions your network makes. If your firewall or resolver prefers to fetch its own list, the account area also offers hosted EDL, PAC, hosts and DNS feeds.
Quoting the vendor's own words
c = client.clause("chatgpt.com", "trains_consumer_default")
if c:
print(c["clause"], c["url"])
Pick one of four fields: trains_consumer_default, optout_available, enterprise_no_training or api_no_training. You get back the exact wording from the vendor's terms plus the URL of that page, ready to paste into a procurement or security review.
Exceptions
Each failure type has its own class, so an except clause can target exactly the case it handles:
from aitoolsblocklist import (
AIToolsBlocklistError, AuthenticationError, QuotaError,
PlanError, RateLimitError, NotFoundError,
)
try:
result = client.lookup("example.com")
except AuthenticationError:
... # 401: rotate or renew the key
except QuotaError:
... # 403: inactive account or monthly quota exhausted
except PlanError as exc:
... # 403 on the database endpoints: lookup-only plan, exc.body["plan"] names it
except RateLimitError:
... # 429 after retries: back off or upgrade the plan
except AIToolsBlocklistError:
... # any other API or network failure
Use a with block and the HTTP session closes itself:
with AIToolsBlocklistClient("YOUR_API_KEY") as client:
print(client.stats()["total_tools"])
Background: the problem this data addresses
AI tools outnumber the rules written for them
Every week brings new AI products, each on its own domain and each happy to accept whatever a user pastes: a contract, a spreadsheet, a block of source code. Rules written by hand name the famous services and miss the long tail. A single "block AI" switch breaks tools the organisation has approved. What remains is shadow AI: tools nobody signed off on, handling data nobody meant to share.
What leaves the building
The risk is simple. Text submitted to an unfamiliar service may be stored, reviewed by staff, or used to train future models, depending on that vendor's terms. The NIST AI Risk Management Framework names confidentiality and third-party dependencies among the risks organisations should map, and it recommends an inventory of AI systems in actual use. Building that inventory starts with recognising which destinations in your traffic are AI tools. That is exactly what a domain classification provides, and the training fields turn a yes-or-no question into a more useful one: allowed, and on which plan?
Schools carry an extra duty
US districts that receive E-rate funding must filter under the Children's Internet Protection Act, as the FCC describes in its CIPA guidance. Generative AI makes that harder. A district may welcome an approved tutoring tool, reject essay generators on integrity grounds, and keep companion chat apps away from minors. That policy needs subcategories. One "AI" label cannot express it. University teaching centres have moved the same way, asking which tools suit which assignments instead of banning AI outright.
Why a separate, daily feed
Topic databases sort the web into shopping, news, social media and so on. Those labels change slowly, and they were never meant to tell a code assistant from a voice cloner. AI tools, by contrast, launch and vanish within weeks. A dedicated list rebuilt daily catches new tools soon after launch and organises them around the distinctions a policy needs. Digital-rights groups such as the Electronic Frontier Foundation have long argued that filtering must be precise and accountable to be legitimate. Precise categories let an admin block a real risk without breaking the tools people depend on.
How the pieces connect
Put lookup() wherever a live decision happens, and put download_database() in the nightly job that refreshes your resolver or firewall list. Heavy matching stays local, so the same code works for a hobby script and for a network making millions of queries. If you want an enforcement-oriented client instead, with a feeds sub-client, a Lookup object and a command line tool, see aiblocklist.
Before writing rules, most teams want to know where they stand. The hosted audit lets you find the AI tools employees use from a DNS, proxy or firewall export. It lists each AI tool seen, who reached it and whether the vendor trains on inputs, and delivers the results as a dated CSV and PDF, checked against the same list this package queries.
When you are ready to enforce, the AI Tools Blocklist lookup API supplies the data and this package connects it to Python.
AI rules rarely live alone. The same firewalls and resolvers usually enforce acceptable-use and security categories too, and our internet filtering database covers 120 million domains in 59 categories as a download for exactly those devices. With both lists loaded, one policy engine handles AI tools, acceptable use and security blocking.
For schools, the school web filtering solution provides the wider CIPA category coverage, refreshed daily and multi-labelled to cut over-blocking of learning material. Phishing is a constant threat on school networks, and an anti-phishing threat feed of 390,000+ DNS-verified active phishing domains lets the resolver that blocks AI tools stop credential theft pages as well.
Frequently asked questions
What exactly does this Python package query? It queries the classified register of AI tool domains, a list of more than 20,000 domains rebuilt every day. Each domain sits in one or more of 18 categories with subcategories, from chat assistants and coding tools to image and video generators, voice cloning, autonomous agents, companion apps and research tools. Besides the API used here, the same data ships as EDL, PAC, hosts and DNS feeds for firewalls, resolvers, gateways and DLP tools.
Which Python code blocks ChatGPT or Midjourney on my network?
None on its own: this package informs the device that enforces. Load the feed into your firewall (EDL), browsers (PAC), resolver (DNS feed) or hosts file, then allow the categories you approve. For decisions made in code, for instance in a proxy add-on, lookup() or is_blocked() gives the answer in one call.
Is it all or nothing, or can a policy be selective? Selective. Because a lookup returns the main category, the full category list, the AI type and the training terms, your code can let an approved coding assistant through and still stop voice cloning or companion chat. Paid plans add 15 sector profiles, each with a Block, Controls or Allow verdict for every tool, if you would rather start from a ready policy.
Will I learn whether a tool uses my prompts for training?
Five fields in every lookup cover it: trains_on_data, opt_out_available, enterprise_no_training, api_no_training and terms_checked. When you need proof rather than a flag, clause() fetches the relevant sentence of the terms together with its source URL.
My filter already has a generative AI category. Why add this? A topic-based filter usually lumps every AI site into one bucket and refreshes it when the vendor gets round to it. Here you get 18 categories with subcategories, AI types and training verdicts, rebuilt daily so new launches show up fast. It is sold as data, which means it sits next to whatever filter you run instead of replacing it.
How fresh is the data?
It is rebuilt once a day. Call stats() (no key needed) for current totals, or database_info() for the timestamp of your downloadable file, and let a nightly job keep your copy in step.
Does it help a school district meet CIPA duties? It covers the AI slice of the problem. Districts and libraries use the categories to stop essay writers, deepfake apps and companion bots while keeping approved tutoring tools open. For the rest of a CIPA filtering policy, pair it with a general filtering database built for schools.
Which delivery formats can I choose from? This JSON lookup API, a firewall External Dynamic List, a PAC file, a hosts file, DNS feeds, and full CSV or JSON exports with every category attached.
Which company maintains it? Alpha Quantum. The same team runs the web filtering database and the website categorization API, plus the AI agent allow list, which handles the reverse problem: which web pages an organisation's own AI agents may open.
Further reading
- Product site and API documentation: https://www.aitoolsblocklist.com
- NIST AI Risk Management Framework (AI RMF 1.0)
- FCC guidance on the Children's Internet Protection Act (CIPA)
- NVIDIA NeMo Guardrails, programmable rails for LLM applications
- OWASP Top 10 for Large Language Model Applications
License
MIT
Blocking tools solves half of shadow AI. The other half is what people paste into the tools that stay open. A GDPR PII detection service scans prompts, chat exports and DLP logs for personal data before it reaches an outside model. Pair a daily-refreshed AI tool blocklist with automated PII removal, and a compliance team controls both which AI services can be reached and what data may go into them.
Governance also runs the other way. Your own AI agents browse the web, and an AI agent allow list marks verified page-type URLs on 40 million+ domains, up to 28 page types each, so agents can read freely while login and payment pages stay off limits. Tool blocking plus agent access policy data covers both directions.
Related packages
aiblockliston PyPI and on npm, the enforcement-point client for the same APIaitoolsblockliston npm, the Node.js version of this packageshadowaitoolson PyPI and on npm, local log scanner for shadow AI toolsaiagentallowliston PyPI and on npm, client for the AI agent allow listphishingdetectionapion PyPI and on npm, from phishingdetectionapi.comwebfilteringdatabaseon npm, from webfilteringdatabase.comwebsiteclassificationapion PyPI andwebsitecategorizationon npm, from websitecategorizationapi.comcipawebfilteringon PyPI and on npm, from cipawebfiltering.com- PII detection API
The Python source is kept in the explainableaixai GitHub repository, and a GitLab copy mirrors it.
Release files for aitoolsblocklist 1.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aitoolsblocklist-1.1.2.tar.gz | 20.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aitoolsblocklist-1.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.6 kB
Release files / aitoolsblocklist-1.1.2.tar.gz
| Download URL | aitoolsblocklist-1.1.2.tar.gz |
|---|---|
| Size | 20.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4b155a3aa21afb33a19604baa32931d647ad49c45d1b37ea454f2fa1658bce15
|
|
BLAKE2b-256 checksum How to use checksums |
6dfcf8c92d83539daff971f706697b6ee5a183a2f9eea75ed2a3966a5a1e3073
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.8.10
|
Release files / aitoolsblocklist-1.1.2-py3-none-any.whl
| Download URL | aitoolsblocklist-1.1.2-py3-none-any.whl |
|---|---|
| Size | 13.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f487dee7056636639f9dd361f9b24b1db97a2e07ca212e689ee49fe07a2a8141
|
|
BLAKE2b-256 checksum How to use checksums |
5de6f06294db86f1513e8545319a46e1a69c7039fb77d1033058144bc2853c7a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.8.10
|