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
- Engine Capabilities
- Imports
- Result Types
- DuckDuckGo
- Bing
- Brave
- Yahoo
- Low-Level Engines
- CLI
- Processing Results
- Multi-Engine Search
- Combining Search with AI
- Error Handling
- Custom Search Engine
- API Reference
- Related Docs
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
| Category | Engines |
|---|---|
text | DuckDuckGo, Bing, Brave, Yahoo, Mojeek, Wikipedia, SerpBase |
images | DuckDuckGo, Bing, Brave, Yahoo, SerpBase |
videos | DuckDuckGo, Brave, Yahoo |
news | DuckDuckGo, Bing, Brave, Yahoo |
suggestions | DuckDuckGo, Bing, Brave, Yahoo |
weather | DuckDuckGo, Yahoo |
answers | DuckDuckGo |
translate | DuckDuckGo |
maps | DuckDuckGo |
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
| Field | Type | Aliases for dict access |
|---|---|---|
title | str | |
href | str | link, url |
body | str | snippet |
ImagesResult
| Field | Type |
|---|---|
title | str |
image | str |
thumbnail | str |
url | str |
height | int |
width | int |
source | str |
VideosResult
| Field | Type |
|---|---|
title | str |
url | str |
thumbnail | str |
content | str |
description | str |
duration | str |
embed_html | str |
embed_url | str |
publisher | str |
uploader | str |
NewsResult
| Field | Type |
|---|---|
title | str |
body | str |
url | str |
date | str |
image | str |
source | str |
DuckDuckGo
The most feature-complete engine. Privacy-focused, no tracking.
from llm4free import DuckDuckGoSearch
ddg = DuckDuckGoSearch()
Text Search
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,
)
Image Search
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,
)
Video Search
results = ddg.videos(
keywords="python tutorials",
resolution="hd", # "sd", "hd"
duration="medium", # "short", "medium", "long"
license_videos="creativeCommon",
max_results=30,
)
News Search
results = ddg.news(
keywords="technology trends",
timelimit="w", # Last week
max_results=20,
)
for item in results:
print(f"{item['title']} - {item['date']}")
Maps Search
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)
Multi-Engine Search
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
| Method | Signature | Returns |
|---|---|---|
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
| Method | Signature | Returns |
|---|---|---|
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
| Method | Signature | Returns |
|---|---|---|
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
| Method | Signature | Returns |
|---|---|---|
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
| Method | Signature | Returns |
|---|---|---|
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:
| Engine | run() Signature | Returns |
|---|---|---|
Mojeek | (*args, **kwargs) โ delegates to search() | List[TextResult] |
Wikipedia | (*args, **kwargs) โ delegates to search() | List[TextResult] |
Related Docs
- CLI Reference -- command-line usage
- Architecture -- how search fits into the system
- Client -- unified Python client with auto-failover
- Getting Started -- quick-start guide
- Troubleshooting -- common issues