LLM4Free Search Module

July 16, 2026 ยท View on GitHub

Last updated: 2026-07-16 Audience: Developers integrating web search into Python applications

LLM4Free's search module provides unified access to multiple search engines through a consistent Python API and CLI. All engines return typed result dataclasses that support both attribute and dict-style access.

Tip

Prefer chat, image, or audio generation instead of search? Use the unified Client, which automatically picks any working provider/model (no provider wiring needed):

from llm4free.client import Client
client = Client()
client.chat.completions.create(model="auto", messages=[{"role": "user", "content": "Hello"}])

Table of Contents


Quick Start

from llm4free import DuckDuckGoSearch

search = DuckDuckGoSearch()
results = search.text("python programming", max_results=5)
for r in results:
    print(f"{r['title']}: {r['href']}")

Note

All results support both attribute access (result.title) and dict-style access (result['title']). URL aliases link and url both map to href.


Engine Capabilities

CategoryEngines
textDuckDuckGo, Bing, Brave, Yahoo, Mojeek, Wikipedia, SerpBase
imagesDuckDuckGo, Bing, Brave, Yahoo, SerpBase
videosDuckDuckGo, Brave, Yahoo
newsDuckDuckGo, Bing, Brave, Yahoo
suggestionsDuckDuckGo, Bing, Brave, Yahoo
weatherDuckDuckGo, Yahoo
answersDuckDuckGo
translateDuckDuckGo
mapsDuckDuckGo

Warning

SerpBase requires an API key (required_auth = True). All other engines work without authentication. The engine registry is defined in llm4free/search/__init__.py.


Imports

The search engines are exported from the top-level package:

from llm4free import (
    DuckDuckGoSearch,  # Full-featured: text, images, videos, news, maps, translate, weather, answers, suggestions
    BingSearch,        # Text, images, news, suggestions
    BraveSearch,       # Text, images, videos, news, suggestions
    YahooSearch,       # Text, images, videos, news, suggestions, weather
    Mojeek,            # Text only (independent European engine)
    Wikipedia,         # Text only (encyclopedia)
    SerpBase,          # Text, images (requires API key)
)

Result Types

The main interfaces (DuckDuckGoSearch, BingSearch, BraveSearch, YahooSearch, SerpBase) return typed dataclasses. Low-level engines (Mojeek, Wikipedia) return TextResult.

from llm4free.search.results import TextResult, ImagesResult, VideosResult, NewsResult

# Both access styles work:
result.title      # attribute
result['title']   # dict-style
result['href']    # URL
result['link']    # alias for href
result['url']     # alias for href

TextResult

FieldTypeAliases for dict access
titlestr
hrefstrlink, url
bodystrsnippet

ImagesResult

FieldType
titlestr
imagestr
thumbnailstr
urlstr
heightint
widthint
sourcestr

VideosResult

FieldType
titlestr
urlstr
thumbnailstr
contentstr
descriptionstr
durationstr
embed_htmlstr
embed_urlstr
publisherstr
uploaderstr

NewsResult

FieldType
titlestr
bodystr
urlstr
datestr
imagestr
sourcestr

DuckDuckGo

The most feature-complete engine. Privacy-focused, no tracking.

from llm4free import DuckDuckGoSearch

ddg = DuckDuckGoSearch()
results = ddg.text(
    keywords="artificial intelligence",
    region="wt-wt",          # Region code
    safesearch="moderate",   # "on", "moderate", "off"
    timelimit="y",           # "d"=day, "w"=week, "m"=month, "y"=year
    backend="api",           # "api" or "html"
    max_results=10,
)
results = ddg.images(
    keywords="nature photography",
    size="large",            # "small", "medium", "large", "wallpaper"
    color="green",           # Color filter
    type_image="photo",      # "photo", "clipart", "line", "animated", "face"
    layout="square",         # "square", "tall", "wide"
    license_image="commercial",
    max_results=50,
)
results = ddg.videos(
    keywords="python tutorials",
    resolution="hd",          # "sd", "hd"
    duration="medium",        # "short", "medium", "long"
    license_videos="creativeCommon",
    max_results=30,
)
results = ddg.news(
    keywords="technology trends",
    timelimit="w",  # Last week
    max_results=20,
)
for item in results:
    print(f"{item['title']} - {item['date']}")
results = ddg.maps(
    keywords="coffee shops",
    place="new york",
    city="New York",
    radius=5,
    max_results=30,
)

Translate

results = ddg.translate(
    keywords="Hola mundo",
    from_lang="es",
    to_lang="en",
)

Weather

weather = ddg.weather("New York")
print(f"Temperature: {weather['current']['temperature_c']}C")

Answers

results = ddg.answers("python programming language")

Suggestions

results = ddg.suggestions("python prog", region="wt-wt")

Bing

from llm4free import BingSearch

bing = BingSearch()

Text Search

results = bing.text(
    keywords="machine learning",
    region="us",
    safesearch="moderate",
    unique=True,              # Deduplicate results
    max_results=10,
)

Image Search

results = bing.images(
    keywords="landscape photography",
    region="us",
    max_results=20,
)

News Search

results = bing.news(
    keywords="AI breakthroughs",
    max_results=15,
)

Suggestions

results = bing.suggestions(
    query="how to learn python",
    region="en-US",
)

Brave

Privacy-focused modern search engine.

from llm4free import BraveSearch

brave = BraveSearch()

Text Search

results = brave.text(
    keywords="cybersecurity",
    region="us-en",
    safesearch="moderate",
    max_results=10,
)

Image Search

results = brave.images(
    keywords="cyberpunk art",
    max_results=15,
)

Video Search

results = brave.videos(
    keywords="python tutorial",
    max_results=10,
)

News Search

results = brave.news(
    keywords="space exploration",
    max_results=10,
)

Suggestions

results = brave.suggestions(
    query="artificial i",
    rich=True,
    country="US",
)

Yahoo

from llm4free import YahooSearch

yahoo = YahooSearch()

Text Search

results = yahoo.text(
    keywords="web development",
    region="us",
    max_results=10,
)

Image Search

results = yahoo.images(
    keywords="landscapes",
    region="us",
    max_results=20,
)

Video Search

results = yahoo.videos(
    keywords="python tutorials",
    max_results=10,
)

News Search

results = yahoo.news(
    keywords="AI news",
    max_results=15,
)

Weather

weather = yahoo.weather("London")

Suggestions

results = yahoo.suggestions("web dev", region="us")

Low-Level Engines

These engines only support text search and are accessed via their run() method.

Mojeek

Independent European search engine, privacy-first.

from llm4free import Mojeek

mojeek = Mojeek()
results = mojeek.run("privacy tools", region="us-en", max_results=5)

Wikipedia

Encyclopedia search returning article summaries.

from llm4free import Wikipedia

wiki = Wikipedia()
results = wiki.run("Quantum Computing", region="us-en", max_results=3)
for r in results:
    print(f"{r['title']}: {r['body'][:200]}")

SerpBase

SerpBase proxies a third-party search API and requires authentication.

from llm4free import SerpBase

serpbase = SerpBase(api_key="your-serpbase-key")
results = serpbase.text("machine learning papers", max_results=5)

CLI

The CLI uses --engine (-e) to select the backend. DuckDuckGo is the default.

# Text search
llm4free text -k "python programming"
llm4free text -k "python programming" -e brave
llm4free text -k "quantum physics" -e wikipedia

# Image search
llm4free images -k "cyberpunk art" -e bing

# News
llm4free news -k "space exploration" -e yahoo

# Weather
llm4free weather -l "London"

# Suggestions
llm4free suggestions -q "artificial i"

# Translate
llm4free translate -k "Hola mundo" --to en

See cli.md for the full CLI reference.


Processing Results

Extract URLs

from llm4free import DuckDuckGoSearch

search = DuckDuckGoSearch()
results = search.text("api design", max_results=5)

urls = [r['href'] for r in results]
for url in urls:
    print(url)

Filter by Keyword

results = search.text("python", max_results=20)
official = [r for r in results if "python.org" in r['href']]

Group by Domain

from urllib.parse import urlparse

results = search.text("web development", max_results=15)
grouped = {}
for r in results:
    domain = urlparse(r['href']).netloc
    grouped.setdefault(domain, []).append(r)

for domain, items in sorted(grouped.items(), key=lambda x: len(x[1]), reverse=True):
    print(f"{domain} ({len(items)} results)")

Convert to Dict

results = search.text("python", max_results=5)
dicts = [r.to_dict() for r in results]

Save to JSON

import json

results = search.text("python programming", max_results=10)
with open("results.json", "w") as f:
    json.dump([r.to_dict() for r in results], f, indent=2)

from llm4free import DuckDuckGoSearch, BingSearch, BraveSearch

def search_all(query, max_results=5):
    engines = [DuckDuckGoSearch(), BingSearch(), BraveSearch()]
    seen = set()
    combined = []

    for engine in engines:
        results = engine.text(query, max_results=max_results)
        for r in results:
            url = r['href']
            if url not in seen:
                seen.add(url)
                combined.append(r)
    return combined

results = search_all("python programming", max_results=5)
for r in results:
    print(f"{r['title']}: {r['href']}")

Combining Search with AI

Tip

The unified Client exposes OpenAI-compatible chat completions. Use a free provider such as HeckAI to summarize results โ€” no API key required.

Summarize Results

from llm4free import DuckDuckGoSearch
from llm4free.llm.heckai import HeckAI

search = DuckDuckGoSearch()
results = search.text("quantum computing", max_results=3)

context = "\n".join(f"{r['title']}: {r['body']}" for r in results)
ai = HeckAI()
response = ai.chat.completions.create(
    model="auto",
    messages=[{"role": "user", "content": f"Summarize these search results:\n{context}"}],
)
print(response.choices[0].message.content)

Research Assistant

from llm4free import DuckDuckGoSearch
from llm4free.llm.heckai import HeckAI

def research(query: str):
    search = DuckDuckGoSearch()
    results = search.text(query, max_results=5)

    context = "Search Results:\n"
    for i, r in enumerate(results, 1):
        context += f"{i}. {r['title']}: {r['body'][:100]}...\n"

    ai = HeckAI()
    answer = ai.chat.completions.create(
        model="auto",
        messages=[{"role": "user", "content": f"{context}\nBased on these results, explain: {query}"}],
    )

    print(f"Answer: {answer.choices[0].message.content}\n")
    print("Sources:")
    for r in results:
        print(f"  {r['href']}")

research("how does photosynthesis work")

News Analysis

from llm4free import DuckDuckGoSearch
from llm4free.llm.heckai import HeckAI

search = DuckDuckGoSearch()
news = search.news("artificial intelligence", max_results=3)

news_text = "\n".join(f"{item['title']}: {item['body']}" for item in news)
ai = HeckAI()
response = ai.chat.completions.create(
    model="auto",
    messages=[{"role": "user", "content": f"Key takeaways from this news:\n{news_text}"}],
)
print(response.choices[0].message.content)

Error Handling

from llm4free import DuckDuckGoSearch

try:
    search = DuckDuckGoSearch()
    results = search.text("python programming", max_results=5)
    print(f"Found {len(results)} results")
except Exception as e:
    print(f"Search failed: {e}")

For rate-limited scenarios, add delays between requests:

import time

for query in ["python", "javascript", "rust"]:
    results = search.text(query, max_results=5)
    print(f"{query}: {len(results)} results")
    time.sleep(1)

Custom Search Engine

Extend BaseSearchEngine to add a new engine. The base class is generic over the result type (e.g. TextResult) and exposes class attributes for the request configuration.

from llm4free.search.base import BaseSearchEngine
from llm4free.search.results import TextResult

class MyEngine(BaseSearchEngine[TextResult]):
    name = "myengine"
    category = "text"
    provider = "myengine"
    search_url = "https://example.com/search"
    search_method = "GET"
    items_xpath = "//div[@class='result']"
    elements_xpath = {
        "title": ".//h3/a/text()",
        "href": ".//h3/a/@href",
        "body": ".//p/text()",
    }

    def build_payload(self, query, region, safesearch, timelimit, page=1, **kwargs):
        return {"q": query, "p": page}

# Use it
engine = MyEngine()
results = engine.run("test query", max_results=5)

API Reference

DuckDuckGoSearch

MethodSignatureReturns
text(keywords, region="wt-wt", safesearch="moderate", timelimit=None, backend="api", max_results=None)List[TextResult]
images(keywords, region="wt-wt", safesearch="moderate", timelimit=None, size=None, color=None, type_image=None, layout=None, license_image=None, max_results=None)List[ImagesResult]
videos(keywords, region="wt-wt", safesearch="moderate", timelimit=None, resolution=None, duration=None, license_videos=None, max_results=None)List[VideosResult]
news(keywords, region="wt-wt", safesearch="moderate", timelimit=None, max_results=None)List[NewsResult]
answers(keywords)List[Dict]
suggestions(keywords, region="wt-wt")List[Dict]
maps(keywords, place=None, street=None, city=None, county=None, state=None, country=None, postalcode=None, latitude=None, longitude=None, radius=0, max_results=None)List[Dict]
translate(keywords, from_lang=None, to_lang="en")List[Dict]
weather(keywords)WeatherData

BingSearch

MethodSignatureReturns
text(keywords, region="us", safesearch="moderate", max_results=None, unique=True)List[TextResult]
images(keywords, region="us", safesearch="moderate", max_results=None)List[ImagesResult]
news(keywords, region="us", safesearch="moderate", max_results=None)List[NewsResult]
suggestions(query, region="en-US")List[Dict]

BraveSearch

MethodSignatureReturns
text(keywords, region="us-en", safesearch="moderate", max_results=None)List[TextResult]
images(keywords, region="us-en", safesearch="moderate", max_results=None)List[ImagesResult]
videos(keywords, region="us-en", safesearch="moderate", max_results=None)List[VideosResult]
news(keywords, region="us-en", safesearch="moderate", max_results=None)List[NewsResult]
suggestions(query, rich=True, country=None, max_results=None)List[Dict]

YahooSearch

MethodSignatureReturns
text(keywords, region="us", safesearch="moderate", max_results=None)List[TextResult]
images(keywords, region="us", safesearch="moderate", max_results=None)List[ImagesResult]
videos(keywords, region="us", safesearch="moderate", max_results=None)List[VideosResult]
news(keywords, region="us", safesearch="moderate", max_results=None)List[NewsResult]
suggestions(keywords, region="us")List[str]
weather(keywords)List[dict]

SerpBase

MethodSignatureReturns
text(keywords, max_results=None, **kwargs)List[TextResult]
images(keywords, max_results=None, **kwargs)List[ImagesResult]

Warning

SerpBase requires an API key passed to the constructor (SerpBase(api_key="...")).

Low-Level Engines (Mojeek, Wikipedia)

All share the same run() pattern:

Enginerun() SignatureReturns
Mojeek(*args, **kwargs) โ€” delegates to search()List[TextResult]
Wikipedia(*args, **kwargs) โ€” delegates to search()List[TextResult]