Python client library for Diffbot APIs.
Install the standalone CLI binary for agentic use:
curl -fsSL https://raw.githubusercontent.com/diffbot/diffbot-python/main/install.sh | shIf you prefer, the full Python library can also be installed with pip:
python3 -m pip install diffbot-pythonFor local development:
pip install -e ".[dev]"The CLI and the library can share a single credential. The token always has to be
passed to the client explicitly, but resolve_token() gives you the same lookup the
CLI uses, in this order:
- An explicit token passed to
resolve_token(token). - The
DIFFBOT_API_TOKENenvironment variable. - A
DIFFBOT_API_TOKEN=...line in~/.diffbot/credentials.
Set it once and it works for both the CLI and your scripts. Either export it:
export DIFFBOT_API_TOKEN=<TOKEN>…or write it to the shared credentials file (handy for keeping it out of your shell environment):
mkdir -p ~/.diffbot
printf 'DIFFBOT_API_TOKEN=%s\n' '<TOKEN>' > ~/.diffbot/credentials
chmod 600 ~/.diffbot/credentialsWith either in place, resolve the token and pass it to the client:
from diffbot import Diffbot, resolve_token
db = Diffbot(token=resolve_token()) # from env var or ~/.diffbot/credentials
data = db.extract("https://www.example.com")Diffbot and DiffbotAsync take the same keyword arguments — the client is the single
place to configure the SDK.
| Argument | Default | Used by |
|---|---|---|
token |
— (required) | all |
timeout |
30.0 (seconds) |
all |
transport |
httpx default | all |
analyze_url |
https://api.diffbot.com/v3 |
extract |
crawler_url |
https://api.diffbot.com/v3/crawl |
crawl, crawl_list_jobs, crawl_get_job, crawl_delete_job |
llm_url |
https://llm.diffbot.com/rag/v1/chat/completions |
ask, ask_json |
web_search_url |
https://llm.diffbot.com/api/v1/web_search |
web_search |
nlp_url |
https://nl.diffbot.com/v1/ |
entities |
dql_url |
https://kg.diffbot.com/kg/v3/dql |
dql, dql_parallel |
ontology_url |
https://kg.diffbot.com/kg/ontology |
dql_fetch_ontology, dql_refresh_ontology |
from diffbot import Diffbot
db = Diffbot(
token="YOUR_TOKEN",
timeout=60.0,
dql_url="http://localhost:8080/kg/v3/dql",
)analyze_url is a base the SDK appends /{api} to, and crawler_url is used as given
for job management and with /data appended for crawl results. The rest are complete
endpoints, used as given.
Passing transport replaces the httpx transport, which is the hook for retries, proxies,
or mocking in tests. Diffbot takes an httpx.BaseTransport, DiffbotAsync an
httpx.AsyncBaseTransport:
import httpx
from diffbot import Diffbot
db = Diffbot(token="YOUR_TOKEN", transport=httpx.HTTPTransport(retries=3))from diffbot import Diffbot
db = Diffbot(token="YOUR_TOKEN")
data = db.extract("https://www.example.com")from diffbot import Diffbot
db = Diffbot(token="YOUR_TOKEN")
for chunk in db.ask([{"role": "user", "content": "What's the capital of France?"}]):
print(chunk, end="")Pass a JSON Schema to constrain the answer. The model is held to the schema by a grammar during decoding, so the result parses reliably even though the answer is retrieved live from the web.
from diffbot import Diffbot
db = Diffbot(token="YOUR_TOKEN")
schema = {
"type": "object",
"properties": {
"country": {"type": "string"},
"capital": {"type": "string"},
},
"required": ["country", "capital"],
}
answer = db.ask_json([{"role": "user", "content": "What's the capital of France?"}], schema)
print(answer["capital"])Omit the schema to let the model choose the shape, or use ask with response_format to stream a constrained answer:
from diffbot import Diffbot, json_schema_format
db = Diffbot(token="YOUR_TOKEN")
answer = db.ask_json([{"role": "user", "content": "What's the capital of France?"}])
for chunk in db.ask(
[{"role": "user", "content": "What's the capital of France?"}],
response_format=json_schema_format(schema),
):
print(chunk, end="")Avoid
response_format={"type": "json_object"}. The endpoint accepts it, but applies no grammar to it — the RAG loop's internal tool call is itself a JSON object, so it can be returned as the final answer. This is reproducible whenever the request includes a system message.ask_jsontherefore defaults to a permissive JSON Schema instead, and raisesValidationErrorif it ever sees a tool call come back.
from diffbot import Diffbot
db = Diffbot(token="YOUR_TOKEN")
for event in db.crawl("https://www.example.com", hops=1):
print(event)from diffbot import Diffbot
db = Diffbot(token="YOUR_TOKEN")
results = db.dql('type:Organization name:"Diffbot"')from diffbot import Diffbot
db = Diffbot(token="YOUR_TOKEN")
results = db.web_search("diffbot knowledge graph")
for r in results["search_results"]:
print(r["score"], r["title"], r["pageUrl"])
print(r["content"])from diffbot import Diffbot
db = Diffbot(token="YOUR_TOKEN")
result = db.entities("Apple CEO Tim Cook announced record quarterly earnings.")
for entity in result["entities"]:
print(entity["name"], entity.get("type"), entity.get("id"))
print("sentiment:", result.get("sentiment"))import asyncio
from diffbot import DiffbotAsync
async def main():
async with DiffbotAsync(token="YOUR_TOKEN") as db:
data = await db.extract("https://www.example.com")
print(data)
asyncio.run(main())import asyncio
from diffbot import DiffbotAsync
async def main():
async with DiffbotAsync(token="YOUR_TOKEN") as db:
async for chunk in db.ask([{"role": "user", "content": "What's the capital of France?"}]):
print(chunk, end="")
asyncio.run(main())import asyncio
from diffbot import DiffbotAsync
schema = {
"type": "object",
"properties": {
"country": {"type": "string"},
"capital": {"type": "string"},
},
"required": ["country", "capital"],
}
async def main():
async with DiffbotAsync(token="YOUR_TOKEN") as db:
answer = await db.ask_json(
[{"role": "user", "content": "What's the capital of France?"}], schema
)
print(answer["capital"])
asyncio.run(main())import asyncio
from diffbot import DiffbotAsync
async def main():
async with DiffbotAsync(token="YOUR_TOKEN") as db:
async for event in db.crawl("https://www.example.com", hops=1):
print(event)
asyncio.run(main())import asyncio
from diffbot import DiffbotAsync
async def main():
async with DiffbotAsync(token="YOUR_TOKEN") as db:
results = await db.dql('type:Organization name:"Diffbot"')
print(results)
asyncio.run(main())import asyncio
from diffbot import DiffbotAsync
async def main():
async with DiffbotAsync(token="YOUR_TOKEN") as db:
results = await db.web_search("diffbot knowledge graph")
for r in results["search_results"]:
print(r["score"], r["title"], r["pageUrl"])
print(r["content"])
asyncio.run(main())import asyncio
from diffbot import DiffbotAsync
async def main():
async with DiffbotAsync(token="YOUR_TOKEN") as db:
result = await db.entities("Apple CEO Tim Cook announced record quarterly earnings.")
for entity in result["entities"]:
print(entity["name"], entity.get("type"), entity.get("id"))
print("sentiment:", result.get("sentiment"))
asyncio.run(main())This library also includes a CLI exposed as the db command.
To make db available from anywhere, install it as an isolated tool with uv:
uv tool install .This drops a db executable into ~/.local/bin (ensure it is on your PATH). Use --force to reinstall or upgrade after changes, or --editable to have source edits take effect immediately. Alternatively, a plain pip install . (or pip install -e .) also installs the db entry point into the active environment.
Every release also ships a self-contained db binary for Linux (x86_64 and aarch64) and macOS (Apple Silicon) as a Python-free option. The installer detects your platform, verifies the SHA256 checksum, and installs (or upgrades) db into ~/.local/bin:
curl -fsSL https://raw.githubusercontent.com/diffbot/diffbot-python/main/install.sh | shPin a specific release or install location with flags (or the DB_VERSION / DB_INSTALL_DIR environment variables); re-running the installer upgrades an existing install in place:
curl -fsSL https://raw.githubusercontent.com/diffbot/diffbot-python/main/install.sh | sh -s -- --version v0.2.1 --bin-dir ~/binexport DIFFBOT_API_TOKEN=your-token-here
db extract https://www.example.com
db ask "What's the capital of France?"
db ask "What's the capital of France?" --json
db ask "What's the capital of France?" --schema capital.json
db crawl https://www.example.com --hops 1
db crawl-list-jobs
db crawl-delete-job crawl-1234567890
db web-search "diffbot knowledge graph"
db web-search "diffbot knowledge graph" -n 5 -f json
db entities "Apple CEO Tim Cook announced record quarterly earnings."
db entities "Apple CEO Tim Cook announced record quarterly earnings." -f dqlOnce installed, this library will work alongside diffbot-skills to enable your agent full access to structuring web knowledge with Diffbot. Diffbot Agent Skills even unlocks some additional skills like crafting DQL from natural language.
diffbot-skills will pick up or install this library automatically.
Run the mock test suite:
python -m pytestRun live integration tests against the real API (requires a valid token).
The token is resolved the same way as everywhere else — the DIFFBOT_API_TOKEN
environment variable or ~/.diffbot/credentials:
DIFFBOT_API_TOKEN=your_token python -m pytest -m live