npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@molecule/api-web-search-brave

v1.1.2

Published

Brave Search web search provider for molecule.dev — independent index, free monthly credits, per-1k pricing beyond them

Readme

@molecule/api-web-search-brave

Brave Search web search provider for molecule.dev — independent index, free monthly credits, per-1k pricing beyond them

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Type

provider

Installation

npm install @molecule/api-web-search-brave @molecule/api-web-search @molecule/api-secrets

API

Interfaces

BraveWebSearchConfig

Options for {@link createProvider}. Every field falls back to an env var or Brave's documented default.

interface BraveWebSearchConfig {
  /**
   * The Brave Search API subscription token. Defaults to
   * `BRAVE_SEARCH_API_KEY`. Create one at https://brave.com/search/api/ —
   * the Search plan includes free monthly credits.
   */
  apiKey?: string
  /** API base URL. Defaults to `https://api.search.brave.com`. */
  baseUrl?: string
  /** Per-request timeout in milliseconds. Default 15000. */
  timeoutMs?: number
  /** Default result count when a call passes none. Default 5. */
  count?: number
  /** Default country code, e.g. `us`. */
  country?: string
  /** Default search language, e.g. `en`. */
  searchLang?: string
}

ProcessEnv

Environment variables this provider reads.

interface ProcessEnv {
  BRAVE_SEARCH_API_KEY?: string
}

Classes

BraveWebSearchError

Error thrown when the search endpoint refuses or fails.

class BraveWebSearchError extends Error {
  /** HTTP status from Brave (0 when the request never completed). */
  readonly status: number

  /**
   * Create the error.
   *
   * @param message - Human-readable message.
   * @param status - HTTP status.
   */
  constructor(message: string, status: number) {
    super(message)
    this.name = 'BraveWebSearchError'
    this.status = status
  }
}

BraveWebSearchProvider

Web search provider backed by the Brave Search API.

class BraveWebSearchProvider implements WebSearchProvider {
  readonly name = 'brave'

  private readonly apiKey: string
  private readonly baseUrl: string
  private readonly timeoutMs: number
  private readonly defaults: { count?: number; country?: string; searchLang?: string }

  /**
   * Create the provider.
   *
   * @param config - Options; each falls back to an env var or default.
   */
  constructor(config: BraveWebSearchConfig = {}) {
    this.apiKey = config.apiKey ?? process.env.BRAVE_SEARCH_API_KEY ?? ''
    this.baseUrl = (config.baseUrl ?? 'https://api.search.brave.com').replace(/\/+$/, '')
    this.timeoutMs = config.timeoutMs ?? 15_000
    this.defaults = { count: config.count, country: config.country, searchLang: config.searchLang }
  }

  /**
   * Search the web.
   *
   * @param query - The search query (at most 400 characters).
   * @param options - Count (1–20) and localization hints.
   * @returns Results in Brave's relevance order.
   */
  async search(query: string, options?: WebSearchOptions): Promise<WebSearchResult> {
    if (typeof query !== 'string' || query.trim().length === 0) {
      throw new BraveWebSearchError('"query" must be non-empty text.', 0)
    }
    if (query.length > MAX_QUERY_CHARS) {
      throw new BraveWebSearchError(
        `The query is ${query.length} characters; the limit is ${MAX_QUERY_CHARS}.`,
        0,
      )
    }
    const count = Math.max(1, Math.min(MAX_COUNT, options?.count ?? this.defaults.count ?? 5))
    const params = new URLSearchParams({ q: query, count: String(count) })
    const country = options?.country ?? this.defaults.country
    const searchLang = options?.searchLang ?? this.defaults.searchLang
    if (country) params.set('country', country)
    if (searchLang) params.set('search_lang', searchLang)

    if (!this.apiKey) {
      throw new BraveWebSearchError(
        'BRAVE_SEARCH_API_KEY is not set. Create a subscription at https://brave.com/search/api/ and put the key in the API .env.',
        0,
      )
    }
    const response = await fetch(`${this.baseUrl}/res/v1/web/search?${params}`, {
      headers: { Accept: 'application/json', 'X-Subscription-Token': this.apiKey },
      signal: AbortSignal.timeout(this.timeoutMs),
    })
    const text = await response.text()
    if (!response.ok) {
      throw new BraveWebSearchError(
        `Brave web search failed (${response.status}): ${text.slice(0, 200)}`,
        response.status,
      )
    }
    let data: {
      query?: { original?: string }
      web?: { results?: Array<{ title?: string; url?: string; description?: string }> }
    }
    try {
      data = JSON.parse(text)
    } catch (_error) {
      // A proxy/gateway error page, not JSON: report the status, not the body.
      throw new BraveWebSearchError(
        `Brave returned ${response.status} with a non-JSON body.`,
        response.status,
      )
    }
    const results = (data.web?.results ?? []).map((r) => ({
      title: r.title ?? '',
      url: r.url ?? '',
      ...(r.description ? { description: r.description } : {}),
    }))
    return { query: data.query?.original ?? query, results }
  }
}

Functions

createProvider(config)

Create a Brave web search provider.

function createProvider(config?: BraveWebSearchConfig): WebSearchProvider
  • config — Options; each falls back to an env var or default.

Returns: A WebSearchProvider backed by the Brave Search API.

Constants

provider

The provider implementation (wire with setProvider).

const provider: WebSearchProvider

braveWebSearchSecretDefinitions

Secret definitions required by the Brave web search bond.

const braveWebSearchSecretDefinitions: SecretDefinition[]

Core Interface

Implements @molecule/api-web-search interface.

Bond Wiring

Setup function to register this provider with the core interface:

import { setProvider } from '@molecule/api-web-search'
import { provider } from '@molecule/api-web-search-brave'

export function setupWebSearchBrave(): void {
  setProvider(provider)
}

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-web-search >=1.0.0
  • @molecule/api-secrets ^1.0.1

Environment Variables

  • BRAVE_SEARCH_API_KEY (required) — Brave Search API key
    • Setup: Subscribe at https://brave.com/search/api/ (the Search plan includes free monthly credits); the key starts with BSAV.
    • Get it here: https://brave.com/search/api/
    • Example: BSAV...

Runtime Dependencies

  • @molecule/api-web-search
  • @molecule/api-secrets