NotPixel Python SDK (notpixel)
Official Python SDK for NotPixel — privacy-first contextual monetization for LLM applications, agents, and backends (FastAPI, Django, Flask, LangChain, LlamaIndex, CrewAI).
Installation
pip install "notpixel>=0.3.0"
Quick Start (Async — FastAPI / LangChain)
from notpixel import AsyncAds
# Ad matching uses local embeddings automatically.
# Prompt text is not sent to the NotPixel API.
ads = AsyncAds(publisher_id="pub_10565")
# 1. Fetch a contextual ad + run your LLM in parallel (best-effort)
result = await ads.respond(
input="How do I optimize PostgreSQL queries with indexes?",
llm=lambda: call_my_llm("How do I optimize PostgreSQL queries with indexes?"),
)
print(result.text) # LLM response + sponsored ad block (if matched)
# 2. Track events
if result.ad:
await ads.impression(result.ad)
await ads.track_click(result.ad, metadata={"source": "fastapi_chat"})
await ads.track_conversion(
result.ad,
type="signup",
value_cents=2900,
external_id="order_12345",
)
Synchronous Usage (Django WSGI / Scripts)
from notpixel import Ads
ads = Ads(publisher_id="pub_10565")
ad = ads.get_ad(input="Best serverless Postgres database")
if ad:
print(ad.text)
ads.track_click(ad)
Privacy
Ad matching uses local embeddings automatically. The SDK sends a numerical vector to NotPixel instead of the prompt text. No privacy flag is needed.
If the local model cannot generate an embedding, get_ad() reports the error through
on_error and returns None, without sending the prompt to NotPixel.
Your LLM calls remain under your application's control and follow your provider's own data handling rules. Keep personal data out of optional context and event metadata.
All-in-one inference
from notpixel import Ads, AsyncAds
# Set NOTPIXEL_MODEL=provider/model and its API key, or pass model= explicitly.
ads = Ads(publisher_id="pub_xxx", model="openai/your-model")
result = ads.offer(input="How can I optimize PostgreSQL?")
print(result.text)
# Same contract, asynchronous I/O.
async_ads = AsyncAds(publisher_id="pub_xxx", model="anthropic/your-model")
result = await async_ads.offer(input="How can I optimize PostgreSQL?")
offer() runs inference and ad selection concurrently. The original prompt goes
only to your selected LLM provider. Only a local embedding goes to NotPixel. A
sponsored block is appended after inference; no ad is injected into the LLM prompt.
When no ad is available, the exact LLM output is returned unchanged.
Supported prefixes: openai, openrouter, anthropic, google, xai, deepseek,
groq, mistral, perplexity, together, github, nvidia, alibaba, minimax,
llama, lmstudio, vercel, netlify. Unknown prefixes and identifiers without
a prefix route through OpenRouter. Gateway model suffixes may contain slashes.
Availability of any particular model depends on your provider account.
Streaming
from contextlib import aclosing, closing
with closing(ads.stream(input="Explain database indexes")) as stream:
for chunk in stream:
if chunk.type == "text":
print(chunk.content, end="", flush=True)
elif chunk.type == "ad":
print(chunk.content) # Structured ad is also available in chunk.ad.
async with aclosing(async_ads.stream(input="Explain database indexes")) as stream:
async for chunk in stream:
if chunk.type == "text":
print(chunk.content, end="", flush=True)
Events are text, then optionally one ad, then done. Provider failures emit
an error event and raise LLMError when iteration resumes, without a successful
done. Configuration errors raise before streaming starts. Ad failures never
interrupt LLM output. An ad is emitted only after the text stream finishes.
Use closing/aclosing when breaking out early. Cancelling the consuming asyncio
task closes upstream HTTP streams and releases ad work owned by that consumer.
Shared ad requests continue while another consumer is waiting. A synchronous
thread already computing an embedding cannot be forcibly interrupted; it finishes
in the background when its work/network timeout completes.
The default ad timeout is 1,500 ms; inference uses a separate configurable
llm_timeout_ms=60000 network timeout. Inference is never automatically retried,
including after partial output. The ad retries option applies only to NotPixel
requests and preserves the request ID across attempts.
Batch, prefetch and callbacks
batch = ads.ads_batch(inputs=["SQL indexes", "Cloud hosting"], limit=1)
batch = await async_ads.ads_batch(inputs=["SQL indexes", "Cloud hosting"],
max_concurrency=8, dedupe=True)
await async_ads.prefetch(["SQL indexes", "Cloud hosting"])
await async_ads.embedding.preload()
Both batch clients default to eight concurrent operations, preserve input order,
count every outcome before deduplication, and apply limit only to the final ad
list. Empty lists return empty results. Prefetch enables cache automatically;
ads.cache.stats(), clear() and cleanup() are available on both clients.
respond() continues to accept your own LLM callable. Its optional context,
publisher_id and request_id are forwarded to ad selection. AsyncAds awaits
async LLM/callback functions and moves synchronous LLM work off the event loop.
Analytics hooks can be synchronous in both clients or asynchronous in AsyncAds.
Async hooks finish before the operation returns; hook failures do not fail serving.
The synchronous client requires synchronous callbacks.
Configuration and adapters
Precedence is call arguments, then constructor configuration, then environment (where an environment equivalent exists). Input has no environment default.
| Variable | Purpose |
|---|---|
NOTPIXEL_MODEL |
Default provider/model |
NOTPIXEL_LOCALE |
Default locale (pt) |
NOTPIXEL_BASE_URL |
NotPixel API origin |
NOTPIXEL_TIMEOUT_MS |
Ad HTTP timeout (default 1500) |
NOTPIXEL_RETRIES |
Ad retries (default 0) |
NOTPIXEL_MIN_SCORE |
Optional lexical post-filter (default 0, disabled) |
NOTPIXEL_MOCK |
1 mocks ads; LLM inference still uses its configured transport |
NOTPIXEL_LOG |
1 opts into console inference logs |
Provider keys: OPENAI_API_KEY, OPENROUTER_API_KEY, ANTHROPIC_API_KEY,
GOOGLE_API_KEY (or GEMINI_API_KEY), XAI_API_KEY, DEEPSEEK_API_KEY,
GROQ_API_KEY, MISTRAL_API_KEY, PERPLEXITY_API_KEY, TOGETHER_API_KEY,
GITHUB_TOKEN, NVIDIA_API_KEY, DASHSCOPE_API_KEY, MINIMAX_API_KEY,
LLAMA_API_KEY, VERCEL_API_KEY, NETLIFY_API_KEY. LM Studio needs no key.
For custom endpoints or per-call credentials, use provider_respond() /
async_provider_respond() with provider, model, input, api_key and optional
base_url. Named helpers such as anthropic_respond() and
async_anthropic_respond() share that contract. openai_respond_http() uses
Responses; openai_respond(client, ...) accepts an existing provider SDK client.
openai_compatible_respond(base_url="https://host/v1", ...) and its async
counterpart support arbitrary OpenAI-compatible endpoints and custom headers.
For connection pooling, pass llm_client=httpx.Client(...) or AsyncClient(...)
to the constructor and close it in your application lifecycle. Injected clients
are owned by your application. The existing transport option remains exclusively
for NotPixel ad/event requests. No provider SDK is a runtime dependency.
logger=callback receives typed LogEvent objects. Logs are off by default and
contain prompts/output when enabled. API keys and raw HTTP error bodies are never
included in SDK-generated inference errors or log events.
PrivacyConfig(dtype="q8" | "fp16" | "fp32", on_progress=callback) selects the
default BGE artifact. Progress reports loading/ready/error states, not downloaded
byte counts. Custom FastEmbed models use their registered precision; unsupported
overrides fail explicitly. Custom embedder callables retain responsibility for
their own precision. Backend/model compatibility is required for custom vectors.
auto_track="server" (default) documents the API's serving-time impression;
auto_track="manual" is available for explicit impression() calls. This option
does not change server billing or imply viewability measurement. Track impressions
only when appropriate to your integration's lifecycle.
Examples and validation
See FastAPI streaming, Django view,
and the backend parity matrix. Install example dependencies using the
dev extra. These examples keep credentials and inference in your backend.
The contract suite runs against simulated HTTP transports and embeddings. It does not certify live provider/model availability or production serving. Version 0.3.0 provides the backend capabilities described in the parity matrix.
Metadata
Release files for notpixel 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| notpixel-0.3.0.tar.gz | 40.1 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| notpixel-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 67.4 kB
Release files / notpixel-0.3.0.tar.gz
| Download URL | notpixel-0.3.0.tar.gz |
|---|---|
| Size | 40.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2f226ebe39f88b2345a4970ca5ba7be9a3caf862df3e0ae0036e966352223230
|
|
BLAKE2b-256 checksum How to use checksums |
a7d11908197e52024692ededb6450d99f28696d55f9fb7f5327589888156734c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / notpixel-0.3.0-py3-none-any.whl
| Download URL | notpixel-0.3.0-py3-none-any.whl |
|---|---|
| Size | 27.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
48737f567031170328f78f4787cf54341575f0f9fbf60f1812f2daea914aa8b5
|
|
BLAKE2b-256 checksum How to use checksums |
dd5b8df4fa95b45398e008ecace8deebf0bfca8b3388b9a78b453e20b0a5b309
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logSecurity for notpixel 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for notpixel-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.