> ## Content Index
> Fetch the complete content index at: https://serpapi.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# Qwen with real-time web search using SerpApi
- URL: https://serpapi.com/blog/qwen-with-real-time-web-search-using-serpapi/
- Published: 2026-11-13T05:03:15.000Z
- Updated: 2026-11-13T05:03:15.000Z
- Description: Learn how to connect Qwen to web search, and find out if a small local model with search can beat a larger one without it.
- Author: Pulkit Chowdry
- Tags: qwen, Local LLM, ai models

I asked a Qwen model, running locally, for the latest version of Next.js. It answered 15\. The latest release was 16.4.6 (as of November 2026). When I asked how it determined this answer, it admitted that it can't search the web and answers from its training data.

![](https://storage.ghost.io/c/a5/00/a5004977-0dd2-4bcd-9292-dd0e05d4c59e/content/images/2026/11/qwen_with_without_search_v2.png)

Qwen conversation: with vs without search

A local model is limited to its training data. This post shows how Qwen can use web search, with multiple search engines such as Google, Baidu and Naver, and compares the performance of different models.

## Does Qwen have web search?

Qwen offers open-weight local models, Qwen Code and the Qwen-Agent framework. All of them can be given access to web search. 

### Qwen local model

Open-weight models such as `qwen3.8:27b`, `qwen3.5:9b` or `qwen3-coder` running on your own device through Ollama, vLLM or LM Studio.

- **Built-in search**: Not available. The model can request search through a tool call, but it can't run one on its own.
- **Add web search**: Through tool calling in your application, or by connecting an [MCP server](https://serpapi.com/integrations/mcp) through an MCP-capable client.

### Qwen Code

A terminal coding agent that works with Qwen models and other providers through compatible APIs, including local models served through Ollama.

- **Built-in search**: Not available for local models or third-party providers such as OpenRouter and DeepSeek.
- **Add web search**: Through MCP servers such as [SerpApi MCP](https://serpapi.com/integrations/mcp).

### Qwen-Agent

A framework for building LLM applications and agents using Qwen models, with built-in support for function calling, MCP, a code interpreter and RAG.

- **Built-in search**: Yes. `web_search` and `web_extractor` tools are present.
- **Add web search**: Add a custom tool or connect an [MCP server](https://serpapi.com/integrations/mcp).

This post covers the Qwen local model with tool calling. I'll cover connecting Qwen Code and Qwen-Agent with [SerpApi's MCP server](https://serpapi.com/integrations/mcp) in a follow-up post.

## How do Qwen and SerpApi work together?

Local models can use tools to perform actions not natively available to them. We can provide web search as a tool to our Qwen model, and the model uses it when necessary to answer a question. Below is a flow diagram of how this works. 

![](https://storage.ghost.io/c/a5/00/a5004977-0dd2-4bcd-9292-dd0e05d4c59e/content/images/2026/10/local-qwen-serpapi--2-.png)

Local Qwen + SerpApi flow diagram

Suppose we ask the model about the latest PHP critical vulnerability. Below is the sequence of actions performed.

1. Our question, along with the prompt and the available tools, is sent to Qwen.
2. Qwen understands that the latest vulnerabilities won't be in its training data, so it requests a web search.
3. A real-time web search is performed through SerpApi, and the results are returned in token-efficient [markdown format](https://serpapi.com/blog/introducing-serpapi-markdown-output/).
4. Qwen checks whether the search results are enough to answer the question. If not, it requests another search.
5. Once Qwen has enough information, it answers the question.

## How to set this up?

Let's begin with what's required to build this.

- **Ollama** to run Qwen locally on your machine. vLLM and LM Studio should also work. Only `base_url` in the sample code changes.
- **Qwen model with tool support** that fits your machine ([see Step 1](#step-1-pick-a-qwen-model-and-start-ollama)).
- **SerpApi API key**: Get it [here](https://serpapi.com/manage-api-key). Free plan includes 250 searches per month.

Note: The commands below are for macOS and Linux.

### Step 1: Pick a Qwen model and start Ollama

Choose a model based on the available memory on your device. A model needs memory for its weights (download size) plus additional memory for the context (conversation and search results).

| Model           | Download size | Memory needed |
| --------------- | ------------- | ------------- |
| qwen3.5:4b      | 3.4 GB        | 6 GB          |
| qwen3.5:9b      | 6.6 GB        | 8 GB          |
| qwen3.8:27b     | 18 GB         | 24 GB         |
| qwen3-coder:30b | 19 GB         | 24 GB         |

Any Qwen model with the tools tag on [Ollama](https://ollama.com/search?c=tools&q=qwen) works. Download your pick using the command below. For example, for `qwen3.8:27b`:

```bash
ollama pull qwen3.8:27b
```

Download Qwen from Ollama

To keep memory in check, start Ollama with a 32k context and an 8-bit KV cache. This allows Qwen to perform several rounds of searches. Keep this terminal tab open.

```bash
OLLAMA_CONTEXT_LENGTH=32768 OLLAMA_FLASH_ATTENTION=1 OLLAMA_KV_CACHE_TYPE=q8_0 ollama serve
```

Start Ollama with settings for low memory usage

### Step 2: Set up Python environment

In a new terminal, create a project, install three packages and add your API key.

```bash
mkdir qwen-search && cd qwen-search
python3 -m venv .venv && source .venv/bin/activate
pip install openai serpapi python-dotenv
echo "SERPAPI_API_KEY=your_api_key" > .env

```

Replace `your_api_key` with the key from your [SerpApi dashboard](https://serpapi.com/manage-api-key).

### Step 3: Add the code

Create qwen\_search.py in the same folder and paste the code below. The script uses `qwen3.8:27b` by default. If you pulled a different model in Step 1, add `LOCAL_MODEL=<model name>` to your .env file.

```python
import json, os
from datetime import date
import serpapi
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()  # reads SERPAPI_API_KEY from .env
serpapi_client = serpapi.Client(api_key=os.environ["SERPAPI_API_KEY"], timeout=60)
qwen = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")  # Ollama's OpenAI-compatible API
MODEL = os.environ.get("LOCAL_MODEL", "qwen3.8:27b")  # set LOCAL_MODEL in .env to use another model
MAX_ROUNDS = 4  # calls to Qwen per question; the last one must answer

def serpapi_search(query):
    """Searches Google with SerpApi and returns the top 5 results as Markdown."""
    return serpapi_client.search(
        engine="google",
        q=query,
        json_restrictor="answer_box,organic_results[0:5].{title,link,snippet,date}",
        output="md",
    )

SYSTEM = f"""You are a helpful assistant with access to web search. Today's date is {date.today()}.
- Search when the answer depends on current or changing information, such as news, releases, prices or who holds a role. Answer directly when it can't have changed.
- Base your answer on the search results. If they don't answer the question, say so instead of guessing.
- Cite the sources you used as Markdown links.
- Reply in the user's language, and keep it concise."""
LAST_ROUND = "That was your last search. Answer now with the results you have."

TOOLS = [{"type": "function", "function": {
    "name": "serpapi_search",
    "description": "Web search for current information. Returns the top 5 results with titles, links, snippets and dates.",
    "parameters": {
        "type": "object",
        "properties": {"query": {"type": "string", "description": "A short, specific search query."}},
        "required": ["query"],
    },
}}]

def ask(question):
    """Lets Qwen search until it can answer, in at most MAX_ROUNDS calls."""
    messages = [{"role": "system", "content": SYSTEM}, {"role": "user", "content": question}]
    for round_number in range(1, MAX_ROUNDS + 1):
        tools = TOOLS
        if round_number == MAX_ROUNDS:
            tools = []
            messages.append({"role": "user", "content": LAST_ROUND})
        reply = qwen.chat.completions.create(model=MODEL, messages=messages, tools=tools).choices[0].message
        if not reply.tool_calls:
            return reply.content
        messages.append(reply.model_dump(exclude_none=True))
        for call in reply.tool_calls:
            query = json.loads(call.function.arguments)["query"]
            print(f"  [search] {query}")
            messages.append({"role": "tool", "tool_call_id": call.id, "content": serpapi_search(query)})

if __name__ == "__main__":
    while True:
        print("\nQwen:", ask(input("\nYou: ")))
```

Code: Qwen-SerpApi through tool calling

The code above has three parts:

- `serpapi_search`: Runs the web search through SerpApi. `json_restrictor` keeps the top 5 results and the fields we need. `output=md` returns search results as Markdown, which uses fewer tokens than JSON.
- `SYSTEM` prompt and `TOOLS` definition: `TOOLS` describes the search tool and its arguments, so Qwen knows how to call it. `SYSTEM` gives today's date, tells Qwen when to search and how to answer: from the search results, with cited sources.
- `ask()` loop: Qwen can call the tool multiple times with different queries, including parallel searches in one round. It answers once it no longer needs the tool or reaches the `MAX_ROUNDS` limit, where the tools are taken away so it has to answer.

### Step 4: Run

```python
python3 qwen_search.py
```

Here's how Qwen used SerpApi and answered a question about the latest PHP vulnerabilities.

```bash
You: What is the latest PHP critical vulnerability and which version fixes it?
  [search] latest PHP critical vulnerability 2026
  [search] PHP CVE-2026-109618 fix version number required
  [search] PHP PHP.net CVE-2026-109618 fix minimum version number

Qwen: The latest critical PHP vulnerabilities discovered in October 2026 are **CVE-2026-109618** and **CVE-2026-109619**, collectively known as **"PHP2Shell"** - two remote code execution (RCE) vulnerabilities in the PHP core interpreter.

### Fix Versions:
| PHP Major Version | Fixed Version |
|------------------|---------------|
| 8.5 | **8.5.12** |
| 8.4 | **8.4.27** |
| 8.3 | **8.3.36** |
| 8.2 | **8.2.35** |

### Important Notes:
*   Older versions (PHP 7.3 and below, including PHP 5) have no fix available [1][2]. Many distributions backport security patches without changing the version number in their package manager [1].

For complete remediation, update your PHP packages to at least **8.5.12** (or equivalent for your major version) and restart all PHP processes.

Sources:
*   [CERT-EU Security Advisory 2026-018](https://cert.europa.eu/publications/security-advisories/2026-018)
*   [CloudLinux Blog - PHP CVE Patch Details](https://blog.cloudlinux.com/php-cve-2026-109618-and-cve-2026-109619)
```

Run on 11 Nov 2026

A "\[search\]" line means Qwen called the tool and your code ran a SerpApi search. Press Ctrl+C to quit.

#### If something fails

Below are some possible errors and how to fix them.

| Error                                        | Fix                                                                                             |
| -------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| address already in use when you start Ollama | Ollama is already running. Quit the Ollama app, then start it again with the command in Step 1. |
| openai.APIConnectionError: Connection error  | Ollama isn't running. Start it as in Step 1.                                                    |
| model "qwen3.8:27b" not found                | Pull the model with ollama pull, or set LOCAL\_MODEL in .env to a name from ollama list.        |
| KeyError: 'SERPAPI\_API\_KEY'                | The .env file isn't in the same folder as qwen\_search.py.                                      |
| HTTPError: 401 Unauthorized                  | The key in .env is wrong. Enter a valid API key from your SerpApi dashboard.                    |

## Let Qwen choose from a wide range of search engines

Different search engines are strong in different areas. Baidu is China's main search engine, Naver is South Korea's, and Google News covers news from outlets worldwide.  
Through SerpApi, our model can use 100+ search engines, so instead of only using Google, we let Qwen pick the engine for each search.  
  
Only three parts of the earlier code change.

```python
# Update `serpapi_search` to accept `engine` as an argument
# Add `RESTRICTORS` for `json_restrictor` across different engines
RESTRICTORS = {
    "google": "answer_box,organic_results[0:5].{title,link,snippet,date}",
    "google_news": "news_results[0:5].{title,link,source.name,date}",
    "baidu": "answer_box,organic_results[0:5].{title,link,snippet}",
    "naver": "web_results[0:5].{title,link,snippet}",
}

def serpapi_search(engine, query):
    """Searches one SerpApi engine and returns the top 5 results as Markdown."""
    if engine not in RESTRICTORS:  # Qwen sometimes invents engine names; Ollama doesn't enforce the enum
        return f"Unknown engine '{engine}'. Use one of: {', '.join(RESTRICTORS)}."
    query_key = "query" if engine == "naver" else "q"  # Naver calls its query parameter "query"
    return serpapi_client.search({
        "engine": engine,
        query_key: query,
        "json_restrictor": RESTRICTORS[engine],
        "output": "md",
    })

# Replace TOOLS: Qwen now chooses the engine as well as the query.
TOOLS = [{"type": "function", "function": {
    "name": "serpapi_search",
    "description": "Search the web with SerpApi. Returns the top 5 results with titles, links, snippets and dates.",
    "parameters": {
        "type": "object",
        "properties": {
            "engine": {
                "type": "string",
                "enum": list(RESTRICTORS),  # the SerpApi engines Qwen can choose from
                "description": "google: Google web search. "
                               "google_news: Google News, recent news articles. "
                               "baidu: China's main search engine, Chinese-language web. "
                               "naver: South Korea's main search engine, Korean-language web.",
            },
            "query": {"type": "string", "description": "A short, specific search query."},
        },
        "required": ["engine", "query"],
    },
}}]

# Inside ask(), update the loop over Qwen's tool calls. 
for call in reply.tool_calls:  # Qwen can call several searches at once, for different engines
    args = json.loads(call.function.arguments)
    print(f"  [search] {args['engine']}: {args['query']}")
    results = serpapi_search(args["engine"], args["query"])
    messages.append({"role": "tool", "tool_call_id": call.id, "content": results})

```

Code: Qwen-SerpApi Multiple Engines

The `engine` argument is SerpApi's own `engine` parameter, so Qwen can directly pass the required search engine.  
Complete code: [qwen\_search\_multi\_engines.py](https://github.com/serpapi/qwen-web-search/blob/main/examples/qwen%5Fsearch.py).

## Add a chat UI

A chat interface makes it easier to compare answers, so I built a local chat app. You can run Qwen with or without search, see token usage, time taken and number of searches for each answer, and compare results side by side in a "battleground". 

![](https://storage.ghost.io/c/a5/00/a5004977-0dd2-4bcd-9292-dd0e05d4c59e/content/images/2026/11/chat-searching.png)

Dedicated mode on the app

Here's a link to the GitHub repo to access it.

[GitHub - serpapi/qwen-web-search: Run Qwen locally with web search through SerpApiRun Qwen locally with web search through SerpApi. Contribute to serpapi/qwen-web-search development by creating an account on GitHub.![](https://storage.ghost.io/c/a5/00/a5004977-0dd2-4bcd-9292-dd0e05d4c59e/content/images/icon/favicon-877e613c-443b-4467-a22a-56f709e18aa6.png)GitHub![](https://storage.ghost.io/c/a5/00/a5004977-0dd2-4bcd-9292-dd0e05d4c59e/content/images/thumbnail/f7f50fc3-9f34-4713-bd78-57630ef46b88-74d75a3e-6031-4423-8507-f3200a048d0d.png)](https://github.com/serpapi/qwen-web-search)

## Benchmark

Curious to find out how much model size matters, whether Qwen needs more search engines than Google, and whether a small model with search can beat a bigger model without it, I ran a few experiments with `qwen3.5:4b`, `qwen3.5:9b` and `qwen3.8:27b` on Ollama.

**Setup**: Each experiment used 100 questions in English, Chinese and Korean on a MacBook Pro with Ollama's default `Q4_K_M` quantization for the model weights. Answers were graded by text match followed by an AI agent review. With a single run, treat small gaps as noise. Below, 27b, 9b and 4b are short for `qwen3.8:27b`, `qwen3.5:9b` and `qwen3.5:4b`.

### Experiment 1: Which model searches best?

Every question was about a recent event in 2026, so the models had to search.

![](https://storage.ghost.io/c/a5/00/a5004977-0dd2-4bcd-9292-dd0e05d4c59e/content/images/2026/11/models.png)

Model performance with web search

**Winner**: `qwen3.8:27b`

**Highlights**

- `qwen3.8:27b` wrote **sharper queries**, searched again when the first results fell short, and was the only model to use Baidu and Naver regularly. The smaller models mostly failed because their searches didn't surface the right answer.
- **Biggest gap:** questions that combine two facts. Of 18, 27b answered 16 correctly, 9b 12 and 4b only 6.
- `qwen3.5:9b` was the **fastest model** at 18.5s per answer. 4b spent more time thinking, and 27b took about twice as long as 9b.
- When 27b was wrong, it usually **trusted its memory**: it skipped the search or filled its queries with outdated facts.

### Experiment 2: Google only vs Multiple search engines

These were local, long-tail questions mostly in Chinese and Korean, asked to `qwen3.8:27b`. I ran them once with Google only and once with a choice of Google, Google News, Baidu and Naver.

![](https://storage.ghost.io/c/a5/00/a5004977-0dd2-4bcd-9292-dd0e05d4c59e/content/images/2026/11/engines.png)

Google only vs Multiple engines on qwen3.8:27b

![](https://storage.ghost.io/c/a5/00/a5004977-0dd2-4bcd-9292-dd0e05d4c59e/content/images/2026/11/engine-choice.png)

Engine choice for Chinese and Korean questions

**Verdict**: Google alone is enough for most questions

**Highlights**

- Google through SerpApi is a strong default, even for regional questions. The score gap (93 vs 95 out of 100) is small enough to be noise.
- Extra engines **helped on very fresh or hyper-local facts**. For example, Naver found the new head of a Seoul district that six Google searches missed. But answers took 22% longer.
- Smaller models default to Google. In a separate test, `qwen3.5:9b` and `qwen3.5:4b` sent none of 20 Chinese and Korean questions to Baidu or Naver. Changing the tool descriptions barely helped, but an explicit line in the system prompt did. It worked well for Korean (Naver on 8 to 9 of 10 questions), while Baidu needed firmer wording to reach 6 to 7 of 10.

### Experiment 3: Small model with search vs Big model without

These were old, stable facts that a model could know from training.

![](https://storage.ghost.io/c/a5/00/a5004977-0dd2-4bcd-9292-dd0e05d4c59e/content/images/2026/11/known-facts.png)

Small model with search vs Big model without

**Winner**: Small model with search

**Highlights**

- A small model with search **beats** a big model answering from memory (97 and 95 vs 82).
- `qwen3.8:27b` lost points because it skipped search on many old facts. It used search for only 31 out of 100 questions, and 7/9 of its wrong answers came from questions where it skipped search.
- Search made the smaller models **faster and token-efficient**. Without search, `qwen3.5:9b` and `qwen3.5:4b` spent over 4,000 thinking tokens and about a minute per answer. With it, the average was around 8s.
- Without search, **the models mostly guessed instead of admitting they didn't know**. Old Korean facts were the worst: the models got 2 to 7 out of 20 right. With search, 9b got 19.

[Detailed benchmark results on GitHub](https://github.com/serpapi/qwen-web-search/blob/main/app/benchmark/insights.md)

## Summary

Giving a local Qwen model web search can substantially improve its accuracy on factual questions. In these experiments, small models with search beat the largest model answering from memory, and search made them far faster than when they tried to recall answers on their own.

Other takeaways:

- **`qwen3.8:27b` was the best at searching.** When questions required a search, it wrote sharper queries and scored highest.
- **Google is a good default engine.** Add Baidu, Naver or Google News for very recent or hyper-local questions, and tell smaller models in the system prompt when to use them.

## 

##