| name | brave-search |
| description | Fallback keyword web search via the Brave Search API. Use exa-search for general web search instead; reach for Brave only when you specifically need its 2000 free requests/month for high-volume lookups, country-scoped results (--country), or a freshness window (--freshness pd/pw/pm/py). The free plan caps at 1 request/second, so never run calls in parallel. |
Brave Search
Keyword web search and content extraction using the official Brave Search API. No browser required.
exa-search is the default search surface — this skill is the fallback. Brave earns the call
only for what Exa does not give you cheaply:
- high-volume keyword lookups you want on a free quota (2000 requests/month)
- country-scoped results (
--country)
- a freshness window (
--freshness pd|pw|pm|py)
For anything else — one general question, several queries at once, intent-based phrasing, domain-scoped
research, or a URL whose text you need — use exa-search.
Setup
Requires a Brave Search API account with a free subscription. A credit card is required to create the free subscription (you won't be charged).
- Create an account at https://api-dashboard.search.brave.com/register
- Create a "Free AI" subscription
- Create an API key for the subscription
- Add to your shell profile (
~/.profile or ~/.zprofile for zsh):
export BRAVE_API_KEY="your-api-key-here"
- Install dependencies (run once):
cd {baseDir}
npm install
Rate limits — read before issuing calls
The free plan is 1 request/second and 2000 requests/month.
- Never launch
search.js calls in parallel. One query at a time; refine from the result.
search.js paces its own requests through a cross-process lock and retries 429 with backoff, so
three concurrent invocations now succeed — they just take ~1.1s apiece. Do not defeat this by
assuming a failure means the quota is gone.
- Every run prints the remaining monthly quota to stderr:
[brave] monthly quota remaining: 1965/2000. Read that line before concluding the key is exhausted.
- If 429 still survives the retries, switch to the
exa-search skill rather than retrying by hand.
Search
{baseDir}/search.js "query"
{baseDir}/search.js "query" -n 10
{baseDir}/search.js "query" --content
{baseDir}/search.js "query" --freshness pw
{baseDir}/search.js "query" --freshness 2024-01-01to2024-06-30
{baseDir}/search.js "query" --country DE
{baseDir}/search.js "query" -n 3 --content
Options
-n <num> - Number of results (default: 5, max: 20)
--content - Fetch and include page content as markdown
--country <code> - Two-letter country code (default: US)
--freshness <period> - Filter by time:
pd - Past day (24 hours)
pw - Past week
pm - Past month
py - Past year
YYYY-MM-DDtoYYYY-MM-DD - Custom date range
Extract Page Content
{baseDir}/content.js https://example.com/article
Fetches a URL and extracts readable content as markdown. Transient network failures are retried
up to 3 times. If it still fails, or the site blocks direct fetches, use the exa-search skill's
contents.js — it goes through Exa's crawler instead of a direct request.
Output Format
--- Result 1 ---
Title: Page Title
Link: https://example.com/page
Age: 2 days ago
Snippet: Description from search results
Content: (if --content flag used)
Markdown content extracted from the page...
--- Result 2 ---
...
When to Use
- Broad keyword lookups where the exact words matter
- Country-scoped results (
--country) or freshness windows (--freshness pd|pw|pm|py)
- Fetching content from a specific URL that answers to a plain request
When to use exa-search instead
- More than one query at once — Brave's 1 req/s makes parallel search a dead end
- Intent-based questions that do not translate into keywords
- Code examples for an unfamiliar library (
exa-search/code.js)
- A URL that Brave's
content.js cannot fetch
- Narrow
site: queries with long keyword lists — these frequently return nothing on Brave;
Exa's --include-domains is the better tool for domain-scoped research