ai-visibility for Python
GEO & AEO toolkit for Django, Flask & FastAPI
ai-visibility (v0.5.0 on PyPI) is the Python port of the npm package of the same name — AI-crawler detection, HTML optimization, JSON-LD schema builders, llms.txt/ai.txt/robots.txt generators, seven-dimension GEO scoring, crawler-visit analytics, and drop-in middleware for Django, Flask, and FastAPI. The core library has zero required dependencies; framework extras only add that framework itself. Every signature on this page and the API referencewas read directly from the installed 0.5.0 package's source, which ships fully typed (mypy --strict clean).
Looking for Node.js/Next.js instead? See the npm docs.
Install
pip install ai-visibility # core, zero deps
pip install ai-visibility[django] # + Django middleware
pip install ai-visibility[flask] # + Flask extension
pip install ai-visibility[fastapi] # + FastAPI/Starlette middleware
pip install ai-visibility[cli] # + CLI
pip install ai-visibility[all] # everythingRequires Python ≥3.10 (checked against the package's published Requires-Python metadata: 3.10, 3.11, 3.12, and 3.13 are the classified versions). The framework extras (django, flask, fastapi) add only that framework as a dependency — installing the bare package pulls in nothing else at all, so it's safe to add to any Python codebase without inheriting an opinion about which web framework, HTTP client, or CLI toolkit you use.
Django quickstart
Add the middleware early in MIDDLEWARE — before anything that might short-circuit the response for a bot — and configure it with the AI_VISIBILITY settings dict:
MIDDLEWARE = [
"ai_visibility.middleware.django.AIVisibilityMiddleware",
# ...the rest of your middleware
]
AI_VISIBILITY = {
"optimize": True,
"inject_schemas": True,
"schemas": [],
"log_visits": True,
}See the Django guide for the full settings reference, adding schemas per-view, and serving llms.txt/robots.txt.
Flask quickstart
from flask import Flask
from ai_visibility.middleware.flask import AIVisibility
app = Flask(__name__)
ai_vis = AIVisibility(app, optimize=True, inject_schemas=True)See the Flask guide for configuration options, blueprints, and Flask-RESTX.
FastAPI quickstart
from fastapi import FastAPI
from ai_visibility.middleware.fastapi import AIVisibilityMiddleware
app = FastAPI()
app.add_middleware(AIVisibilityMiddleware, optimize=True, inject_schemas=True)See the FastAPI guide for dependency injection with schema builders and async notes.
All three adapters share one implementation — AIVisibilityCore in ai_visibility.middleware.base — so detection, HTML optimization, and analytics logging behave identically across frameworks. Every middleware detects AI crawlers first and is a complete no-op for regular visitors: zero added overhead on normal traffic.
Framework-agnostic core
Every framework adapter is built on plain functions that work anywhere — a script, a Lambda, a Celery task, a framework this package doesn't ship middleware for:
from ai_visibility import (
detect_crawler,
optimize_html,
article_schema,
render_jsonld,
generate_llms_txt,
score_page,
LlmsTxtConfig,
)
# Detect AI crawlers
crawler = detect_crawler(request.headers.get("User-Agent"))
if crawler:
print(f"{crawler.name} ({crawler.company}) — category: {crawler.category.value}")
# Optimize HTML for AI consumption (strips scripts/styles/tracking, keeps JSON-LD)
clean_html = optimize_html(page_html)
# Build structured data
schema = article_schema(headline="How AI Crawlers Work", author_name="Jane Doe")
jsonld_tag = render_jsonld(schema)
# Generate llms.txt
llms_txt = generate_llms_txt(LlmsTxtConfig(title="Acme", summary="Acme makes widgets."))
# Score a page's AI visibility across 7 dimensions
result = score_page(page_html, has_llms_txt=True)
print(result.overall_score, result.dimension_scores)Full signatures for every function above are on the API reference.
Module map
| Module | Contains |
|---|---|
ai_visibility.detector | detect_crawler(), is_ai_crawler() |
ai_visibility.crawlers | get_all_crawlers(), get_crawler_by_name(), get_crawlers_by_category() |
ai_visibility.optimizer | optimize_html(), inject_schemas() |
ai_visibility.schema | article_schema(), product_schema(), faq_schema(), and 7 more builders, render_jsonld() |
ai_visibility.generators | generate_llms_txt(), generate_llms_full_txt(), generate_ai_txt(), generate_robots_txt() |
ai_visibility.scoring | score_page() |
ai_visibility.analyzer | analyze_content() |
ai_visibility.analytics | CrawlerAnalytics, InMemoryAnalyticsStore, AnalyticsStore protocol |
ai_visibility.middleware | Django, Flask, FastAPI adapters — each imported from its own submodule |
ai_visibility.cli | the ai-visibility command (requires the cli extra) |
Everything except ai_visibility.middleware.* and ai_visibility.cli is also re-exported from the top-level ai_visibility barrel — see the import block above. Middleware submodules are never imported by the barrel, on purpose: each depends on an optional extra, so importing bare ai_visibility never requires Django, Flask, FastAPI, or Starlette to be installed.
One source of truth across ecosystems
ai_visibility.crawlers and ai_visibility.scoring_weights don't reimplement the crawler registry or the GEO scoring weights — they load crawlers.json and scoring_weights.json, vendored verbatim from the npm package's published dist/crawlers.json and dist/scoring-weights.json. A page classified as visible to GPTBot in Python is classified the same way in JavaScript/TypeScript, and a score_page() result uses the exact same seven dimension keys and weights as ContentAnalyzer in the npm package — see the Python scoring guidefor the one real difference: the per-dimension arithmetic is an original Python implementation written to match each dimension's published description, not a byte-for-byte port of unpublished TypeScript internals.
PyPI · GitHub · API reference · Crawler registry (shared with npm)