,

How to Add Web Search to Open WebUI with Brave Search & Playwright

Open WebUI + Brave Search: Web Search & Playwright Setup Guide

In the last post we got Open WebUI and Ollama running in Docker. It works. You can chat with your local model. But there’s a fundamental limitation — your LLM only knows what was in its training data. If something happened after its training cutoff, it’s flying blind.

That’s where web search comes in.

Over the last few weeks, I’ve been testing different web search integrations for Open WebUI — Brave Search, SearXNG, Tavily, and more. Here’s what I found: Brave Search + Playwright gives you the best balance of quality, cost, and setup simplicity for self-hosted deployments.

This guide walks you through setting up both. It takes about 15 minutes from start to finish, and you’ll need exactly one thing: a free Brave Search API key.

Why Brave Search and Playwright?

Before we dive into the setup, let’s talk about why these two tools work so well together.

Brave Search Is the Only Search API With Its Own Index

Most web search APIs for AI applications are really just resellers — they scrape Google or Bing results and repackage them. Brave is different. They maintain their own independent web index covering over 30 billion pages, updated 100 million times daily.

In blind tests, Brave Search performs on par with or better than incumbent search giants. That matters because the quality of your search results directly determines the quality of your LLM’s answers.

Playwright Handles What Simple Crawling Can’t

When Open WebUI’s model decides a search result needs deeper investigation, it needs to visit the actual page and read the full content. Most basic web loaders can’t handle JavaScript-rendered pages, lazy-loaded content, or modern single-page applications. Playwright runs a full Chromium instance, so it sees pages exactly as a real browser would.

Together, they form a complete pipeline: Brave Search finds the information, Playwright reads the pages.

Getting Your Brave Search API Key

Head to api-dashboard.search.brave.com/register and create an account. A credit card is required for anti-fraud purposes, but here’s the thing — you won’t be charged a penny.

Brave’s free tier gives you $5 in credits every month at no cost. At $5 per 1,000 requests, that’s roughly 1,000 web searches per month for free. For a personal or small team deployment, that’s more than enough.

Once registered, navigate to your dashboard and copy your X-Subscription-Token. That’s your API key — you’ll need it in the next step.

Updating Your Docker Compose

Remember the compose file from the last post? We’re going to extend it with three additions:

1. Brave Search environment variables on the `web` service

2. Playwright web loader configuration on the `web` service

3. A new Playwright container as its own service

Here’s your complete updated `docker-compose.yml`:

services:
  llm:
    image: ollama/ollama:0.21.1
    environment:
      - OLLAMA_KEEP_ALIVE=1h
      - OLLAMA_CONTEXT_LENGTH=32000
      - NVIDIA_VISIBLE_DEVICES=0
    ports:
      - 11434:11434
    volumes:
      - ~/ollama:/root/.ollama

  playwright:
    image: mcr.microsoft.com/playwright:v1.58.0-noble
    container_name: playwright
    command: npx -y playwright@1.58.0 run-server --port 3000 --host 0.0.0.0

  web:
    image: ghcr.io/open-webui/open-webui:v0.8.12
    depends_on:
      - llm
      - playwright
    environment:
      - OLLAMA_BASE_URLS=http://llm:11434
      - WEBUI_AUTH=false
      - WEBUI_SECRET=<your-secret>
      # Brave Search
      - ENABLE_WEB_SEARCH=true
      - WEB_SEARCH_ENGINE=brave
      - BRAVE_SEARCH_API_KEY=your-brave-api-key-here
      - WEB_SEARCH_RESULT_COUNT=3
      - WEB_SEARCH_CONCURRENT_REQUESTS=1
      # Playwright Web Loader
      - WEB_LOADER_ENGINE=playwright
      - PLAYWRIGHT_WS_URL=ws://playwright:3000
    restart: unless-stopped
    ports:
      - 8080:8080
    volumes:
      - ~/openweb-ui:/app/backend/data

Let me break down the new pieces.

Brave Search Environment Variables

  • ENABLE_WEB_SEARCH – Turns on web search capability globally
  • WEB_SEARCH_ENGINE=brave – Tells Open WebUI to use Brave as the search provider
  • BRAVE_SEARCH_API_KEY – Your API key from the Brave dashboard
  • WEB_SEARCH_RESULT_COUNT – How many results the model sees per query (3 is a good default)
  • WEB_SEARCH_CONCURRENT_REQUESTS – Controls parallel requests — set to `1` for the free tier

The concurrency setting is the one worth paying attention to. Brave’s free tier enforces a strict 1 request per second rate limit. If you set concurrency above 1, your model might fire multiple searches simultaneously and hit HTTP 429 errors.

Here’s the good news: Open WebUI handles rate limits gracefully. When it receives a 429, it waits one second, retries once, and only fails if the retry also errors. With `WEB_SEARCH_CONCURRENT_REQUESTS=1`, you’ll almost never see this happen.

Playwright Environment Variables

  • WEB_LOADER_ENGINE=playwright – Switches from the default `safe_web` engine to Playwright
  • PLAYWRIGHT_WS_URL=ws://playwright:3000 – Points to the Playwright WebSocket server

By default, Open WebUI uses `safe_web` as its web loader. It works for simple HTML pages but chokes on JavaScript-heavy sites. Playwright changes that by running a full Chromium browser under the hood.

The Playwright container I’ve added runs on port 3000 inside the Docker network. The `web` service connects to it via the WebSocket URL. No ports need to be exposed to the host — they communicate over Docker’s internal network.

The Playwright Container

playwright:
    image: mcr.microsoft.com/playwright:v1.58.0-noble
    container_name: playwright
    command: npx -y playwright@1.58.0 run-server --port 3000 --host 0.0.0.0

This is the official Microsoft Playwright image. It spins up a headless Chromium instance that Open WebUI connects to for full-page content extraction. The container consumes about 200-500MB of RAM, which is worth noting if you’re running this on a tight budget.

Starting It Up

From the directory containing your `docker-compose.yml`:

docker compose down
docker compose up -d

Give it about two minutes. Open WebUI needs to initialize the Playwright connection, and the Playwright container needs to start Chromium before the `web` service can fully connect.

Navigate to `http://localhost:8080` and you should see your usual Open WebUI interface.

Configuring Web Search in the Admin Panel

Adding the environment variables is only half the equation. You also need to enable web search at the model level.

Step 1: Verify Global Web Search Settings

Go to Admin Panel → Settings → Web Search. You should see:

– “Enable Web Search” is checked
– “Web Search Engine” shows `brave`

These values come from your environment variables. If something looks wrong, you can override it here — or temporarily set `ENABLE_PERSISTENT_CONFIG=false` to force your environment variables to take effect.

Step 2: Enable Web Search for Your Model

Go to Admin Panel → Settings → Models. Select your Ollama model and:

1. Enable the Web Search capability
2. Check Web Search under Default Features

This ensures every new chat session has web search available without manual toggling.

Step 3: Test It

Open a new chat and ask something like:

> “What are the latest developments in AI this month?”

You should see the model perform a Brave Search, show the search results, and incorporate the findings into its answer with source citations.

Agentic Search: Taking It Further

Here’s where things get interesting. Open WebUI’s web search isn’t just a one-and-done lookup. With the right model and configuration, you can unlock agentic (native) search mode, where the model independently decides when to search, what to search for, and which results to dig deeper into.

What Agentic Search Changes

The difference between standard web search and agentic search is fundamental:

FeatureStandard Web Search Agentic Search (Native Mode)
Search decisionOpen WebUI decides based on promptThe model decides if and when to search
Data processingFetches results, chunks them, uses RAGReturns snippets directly; no chunking
Link following Snippets from top resultsModel uses `fetch_url` to read full pages
ReasoningModel processes data after injectionModel searches, reads, checks, and searches again

How to Enable Native Mode

In Admin Panel → Settings → Models, select your model and under Advanced Parameters, set Function Calling to `Native`.

With Native Mode enabled, the model can:

1. Search the web and see snippet results (like a human on a search results page)
2. Read full pages when snippets aren’t enough, using `fetch_url` with Playwright
3. Search multiple times with increasingly specific queries based on what it finds
4. Cross-reference information across multiple sources
5. Follow discovery chains — when reading a page, it can find new relevant URLs and fetch those too

This creates a research loop that’s genuinely powerful: the model acts as its own research assistant, iteratively gathering and verifying information until it has enough to answer with confidence.

A Word of Warning About Models

Agentic search works best with frontier models that have strong reasoning and tool-calling capabilities. Large local models like Llama 3.3 70B or Mixtral 8x22B will handle it decently. Smaller models (7B-13B range) may struggle with the multi-step reasoning required.

If you’re running a small model, standard web search will still serve you well. Agentic search is an upgrade path you can enable when you’re ready.

Understanding the Brave Search API

Before wrapping up, here’s a quick reference for what the Brave Search API actually gives you.

Pricing

TierCostMonthly Free Credits Rate Limit
Free$0$5 (~1,000 requests)1 request/second
Paid$5 per 1,000 requests$5 per month50 queries/second

The free tier is perfect for personal use. If you’re running a multi-user deployment where everyone triggers searches simultaneously, consider upgrading.

Search Types

The Brave Search API supports several specialized endpoints:

Web Search — General web results (what we’re using)
LLM Context — Pre-extracted content optimized for AI grounding
Image Search — Image results with metadata
Video Search — Video results with duration, views, creator info
News Search — Current news with freshness controls
Local Search — Business and place data (requires Pro plan)

A Note on Brave’s MCP Server

Brave also offers an official [MCP Server](https://github.com/brave/brave-search-mcp-server) (987 stars) that wraps the Brave Search API into the Model Context Protocol. This is useful if you want to plug Brave Search into Claude, Cursor, or other MCP-compatible tools. It’s not necessary for Open WebUI integration (we use the native provider), but it’s worth knowing about if you expand your AI toolset.

Troubleshooting

HTTP 429 Errors

If you’re seeing “Too Many Requests” errors, your concurrency is too high for the free tier. Set `WEB_SEARCH_CONCURRENT_REQUESTS=1` in your environment variables.

Playwright Connection Refused

If web search works but `fetch_url` fails with connection errors, the Playwright container might not be ready. Restart all services:

docker compose restart

Give it 30 seconds and try again.

Persistent Config Override

If your environment variables don’t seem to be taking effect, Open WebUI might be using persisted settings from a previous session. Either:

1. Update the settings through the Admin Panel UI (recommended), or
2. Temporarily set `ENABLE_PERSISTENT_CONFIG=false` to force env var priority

Brave Browser Conflict

If you’re using Brave browser to access Open WebUI, you may run into UI issues — this is a known conflict between Brave’s aggressive anti-tracking features and how Open WebUI loads certain assets. The fix is simple: access your Open WebUI instance in Firefox or Chrome instead.

Wrapping Up

Adding web search to Open WebUI transforms it from a nice chat interface into an actual research tool. Your local LLM can now answer questions about current events, verify facts against live sources, and dig into pages that simple snippet search can’t cover.

The Brave Search + Playwright combination gives you the best of both worlds: quality search results from an independent index, and the ability to read full pages on any site — no matter how modern or JavaScript-heavy.

If you’re running this setup, I’d love to hear about it. Are you using agentic search with Native Mode? What model are you running it on? Drop a comment — I read them all.

Next Steps

– Try the agentic search toggle and watch how the model independently researches topics
– Experiment with `WEB_SEARCH_RESULT_COUNT` (3, 5, or 10) to see how it affects answer depth
– Check out Open WebUI’s other web search providers — they support 22 different search engines
– Explore the Brave Search MCP Server if you want to use Brave in other AI tools

Resources:

Open WebUI Brave Provider Docs
Open WebUI Agentic Search Docs
Open WebUI Environment Variables Reference
Brave Search API
Brave Search MCP Server

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *