An async Python client for Brave Search, providing streaming AI answers and structured web search in a single, typed interface - with a built-in Model Context Protocol (MCP) server.
- Brave Ask — complete answers with citations, incremental streaming, follow-up conversations, and optional image input.
- Brave Search — typed results for web, images, news, videos, and Brave Goggles, with page-based pagination and autocomplete suggestions.
- Reliable async client — one
async with BraveClient()interface with typed Pydantic models, configurable language/region/safe search, timeouts, retries, concurrency, and proxies. - MCP server — expose Ask and Search tools to MCP-compatible AI applications over stdio or HTTP.
- Developer examples — runnable examples for vertical search, streaming, conversations, multimodal input, configuration, and MCP.
Brave Daily is the live showcase built with this package. It turns Brave Search and Brave Ask into a daily intelligence dashboard with six modules:
- Global Pulse — technology, geopolitics, finance, cybersecurity, and science coverage with source diversity and editorial summaries.
- Trend Radar — article-volume signals for topics such as AI, quantum computing, space, climate, robotics, and semiconductors.
- Threat Wire — cybersecurity and OSINT news with severity classification and extracted CVE/IP indicators.
- Market Scanner — crypto, equities, and macroeconomic headlines with Ask-based sentiment summaries.
- Data Lab — downloadable JSON, CSV, Markdown, and a lightweight threat feed.
- Search Playground — live examples of
search(),search_news(),search_images(),search_videos(), andask()with the corresponding Python snippets.
The dashboard is generated by brave_daily/generate.py
and deployed to GitHub Pages by .github/workflows/brave-daily.yml.
To generate it locally:
uv run python brave_daily/generate.py --output brave_daily/dist
python -m http.server 8000 --directory brave_daily/distThen open http://127.0.0.1:8000. A fresh edition requires a working Brave connection; optional enrichment failures fall back to an explicit unavailable or fallback result so the static dashboard can still be published.
The complete documentation is available at brave-api.readthedocs.io.
It includes detailed guides, configuration, MCP setup, examples, error handling, and the generated API reference.
Requires Python 3.11+.
uv add brave-api-pythonFor MCP support:
uv add "brave-api-python[mcp]"With pip:
pip install brave-api-pythonFrom source:
git clone https://github.com/iqbalmh18/brave-api.git
cd brave-api
uv sync --group devimport asyncio
from brave_api import BraveClient
async def main() -> None:
async with BraveClient() as client:
result = await client.ask("What is quantum computing?")
print(result.text)
print(f"Sources: {len(result.urls)}")
asyncio.run(main())async with BraveClient() as client:
result = await client.search("Python asyncio tutorial")
for item in result.web[:3]:
print(item.title, item.url)All public methods are asynchronous and should normally be used inside
async with BraveClient().
Every search method returns the same SearchResult response envelope:
async with BraveClient() as client:
web = await client.search("Python asyncio")
images = await client.search_images("Python logo")
news = await client.search_news("Python release")
videos = await client.search_videos("Python tutorial")
goggles = await client.search_goggles("privacy search")
print(web.web)
print(images.images)
print(news.news)
print(videos.videos)
print(goggles.web)Pagination uses Brave's page-based offset value, where 0 is the first page:
async with BraveClient() as client:
first_page = await client.search_news("Python release", offset=0)
second_page = await client.search_news("Python release", offset=1)Use spellcheck=False for exact keyword matching. Use client.suggest() for
autocomplete suggestions.
from brave_api import BraveClient, StreamEventType
async with BraveClient() as client:
async for event in client.ask_stream("Explain WebAssembly"):
if event.type is StreamEventType.TEXT_DELTA:
print(event.delta, end="", flush=True)from brave_api import BraveClient, ClientConfig
config = ClientConfig(
language="id",
ui_lang="id-id",
country="id",
safesearch="moderate",
timeout=60.0,
max_retries=3,
proxies=["http://user:password@proxy.example:8080"],
)
async with BraveClient(config) as client:
result = await client.search("berita teknologi")See the configuration guide for all supported options.
Install the optional MCP dependency:
uv add "brave-api-python[mcp]"Run locally over stdio:
brave-api-mcpOr run an HTTP server:
brave-api-mcp --http --host 127.0.0.1 --port 8000Available search tools include search, search_images, search_news,
search_videos, search_goggles, and suggest, in addition to ask.
Runnable examples are available in examples/:
search_verticals.py— all search verticals and paginationsearch_suggest.py— web search and autocompletestreaming.py— streaming eventsmultimodal.py— image inputconfiguration.py— configuration and proxies
Run one with:
uv run python examples/search_verticals.pyuv sync --group dev
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run pyrightFor API details, error handling, conversations, and complete MCP configuration, see the full documentation.
MIT. See LICENSE.