Hermes-agent duckduckgo-search

Free web search via DuckDuckGo — text, news, images, videos. No API key needed. Prefer the `ddgs` CLI when installed; use the Python DDGS library only after verifying that `ddgs` is available in the current runtime.

install
source · Clone the upstream repo
git clone https://github.com/NousResearch/hermes-agent
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/NousResearch/hermes-agent "$T" && mkdir -p ~/.claude/skills && cp -r "$T/optional-skills/research/duckduckgo-search" ~/.claude/skills/nousresearch-hermes-agent-duckduckgo-search-0e79b7 && rm -rf "$T"
manifest: optional-skills/research/duckduckgo-search/SKILL.md
source content

DuckDuckGo Search

Free web search using DuckDuckGo. No API key required.

Preferred when

web_search
is unavailable or unsuitable (for example when
FIRECRAWL_API_KEY
is not set). Can also be used as a standalone search path when DuckDuckGo results are specifically desired.

Detection Flow

Check what is actually available before choosing an approach:

# Check CLI availability
command -v ddgs >/dev/null && echo "DDGS_CLI=installed" || echo "DDGS_CLI=missing"

Decision tree:

  1. If
    ddgs
    CLI is installed, prefer
    terminal
    +
    ddgs
  2. If
    ddgs
    CLI is missing, do not assume
    execute_code
    can import
    ddgs
  3. If the user wants DuckDuckGo specifically, install
    ddgs
    first in the relevant environment
  4. Otherwise fall back to built-in web/browser tools

Important runtime note:

  • Terminal and
    execute_code
    are separate runtimes
  • A successful shell install does not guarantee
    execute_code
    can import
    ddgs
  • Never assume third-party Python packages are preinstalled inside
    execute_code

Installation

Install

ddgs
only when DuckDuckGo search is specifically needed and the runtime does not already provide it.

# Python package + CLI entrypoint
pip install ddgs

# Verify CLI
ddgs --help

If a workflow depends on Python imports, verify that same runtime can import

ddgs
before using
from ddgs import DDGS
.

Method 1: CLI Search (Preferred)

Use the

ddgs
command via
terminal
when it exists. This is the preferred path because it avoids assuming the
execute_code
sandbox has the
ddgs
Python package installed.

# Text search
ddgs text -q "python async programming" -m 5

# News search
ddgs news -q "artificial intelligence" -m 5

# Image search
ddgs images -q "landscape photography" -m 10

# Video search
ddgs videos -q "python tutorial" -m 5

# With region filter
ddgs text -q "best restaurants" -m 5 -r us-en

# Recent results only (d=day, w=week, m=month, y=year)
ddgs text -q "latest AI news" -m 5 -t w

# JSON output for parsing
ddgs text -q "fastapi tutorial" -m 5 -o json

CLI Flags

FlagDescriptionExample
-q
Query — required
-q "search terms"
-m
Max results
-m 5
-r
Region
-r us-en
-t
Time limit
-t w
(week)
-s
Safe search
-s off
-o
Output format
-o json

Method 2: Python API (Only After Verification)

Use the

DDGS
class in
execute_code
or another Python runtime only after verifying that
ddgs
is installed there. Do not assume
execute_code
includes third-party packages by default.

Safe wording:

  • "Use
    execute_code
    with
    ddgs
    after installing or verifying the package if needed"

Avoid saying:

  • "
    execute_code
    includes
    ddgs
    "
  • "DuckDuckGo search works by default in
    execute_code
    "

Important:

max_results
must always be passed as a keyword argument — positional usage raises an error on all methods.

Text Search

Best for: general research, companies, documentation.

from ddgs import DDGS

with DDGS() as ddgs:
    for r in ddgs.text("python async programming", max_results=5):
        print(r["title"])
        print(r["href"])
        print(r.get("body", "")[:200])
        print()

Returns:

title
,
href
,
body

News Search

Best for: current events, breaking news, latest updates.

from ddgs import DDGS

with DDGS() as ddgs:
    for r in ddgs.news("AI regulation 2026", max_results=5):
        print(r["date"], "-", r["title"])
        print(r.get("source", ""), "|", r["url"])
        print(r.get("body", "")[:200])
        print()

Returns:

date
,
title
,
body
,
url
,
image
,
source

Image Search

Best for: visual references, product images, diagrams.

from ddgs import DDGS

with DDGS() as ddgs:
    for r in ddgs.images("semiconductor chip", max_results=5):
        print(r["title"])
        print(r["image"])
        print(r.get("thumbnail", ""))
        print(r.get("source", ""))
        print()

Returns:

title
,
image
,
thumbnail
,
url
,
height
,
width
,
source

Video Search

Best for: tutorials, demos, explainers.

from ddgs import DDGS

with DDGS() as ddgs:
    for r in ddgs.videos("FastAPI tutorial", max_results=5):
        print(r["title"])
        print(r.get("content", ""))
        print(r.get("duration", ""))
        print(r.get("provider", ""))
        print(r.get("published", ""))
        print()

Returns:

title
,
content
,
description
,
duration
,
provider
,
published
,
statistics
,
uploader

Quick Reference

MethodUse WhenKey Fields
text()
General research, companiestitle, href, body
news()
Current events, updatesdate, title, source, body, url
images()
Visuals, diagramstitle, image, thumbnail, url
videos()
Tutorials, demostitle, content, duration, provider

Workflow: Search then Extract

DuckDuckGo returns titles, URLs, and snippets — not full page content. To get full page content, search first and then extract the most relevant URL with

web_extract
, browser tools, or curl.

CLI example:

ddgs text -q "fastapi deployment guide" -m 3 -o json

Python example, only after verifying

ddgs
is installed in that runtime:

from ddgs import DDGS

with DDGS() as ddgs:
    results = list(ddgs.text("fastapi deployment guide", max_results=3))
    for r in results:
        print(r["title"], "->", r["href"])

Then extract the best URL with

web_extract
or another content-retrieval tool.

Limitations

  • Rate limiting: DuckDuckGo may throttle after many rapid requests. Add a short delay between searches if needed.
  • No content extraction:
    ddgs
    returns snippets, not full page content. Use
    web_extract
    , browser tools, or curl for the full article/page.
  • Results quality: Generally good but less configurable than Firecrawl's search.
  • Availability: DuckDuckGo may block requests from some cloud IPs. If searches return empty, try different keywords or wait a few seconds.
  • Field variability: Return fields may vary between results or
    ddgs
    versions. Use
    .get()
    for optional fields to avoid
    KeyError
    .
  • Separate runtimes: A successful
    ddgs
    install in terminal does not automatically mean
    execute_code
    can import it.

Troubleshooting

ProblemLikely CauseWhat To Do
ddgs: command not found
CLI not installed in the shell environmentInstall
ddgs
, or use built-in web/browser tools instead
ModuleNotFoundError: No module named 'ddgs'
Python runtime does not have the package installedDo not use Python DDGS there until that runtime is prepared
Search returns nothingTemporary rate limiting or poor queryWait a few seconds, retry, or adjust the query
CLI works but
execute_code
import fails
Terminal and
execute_code
are different runtimes
Keep using CLI, or separately prepare the Python runtime

Pitfalls

  • max_results
    is keyword-only
    :
    ddgs.text("query", 5)
    raises an error. Use
    ddgs.text("query", max_results=5)
    .
  • Do not assume the CLI exists: Check
    command -v ddgs
    before using it.
  • Do not assume
    execute_code
    can import
    ddgs
    :
    from ddgs import DDGS
    may fail with
    ModuleNotFoundError
    unless that runtime was prepared separately.
  • Package name: The package is
    ddgs
    (previously
    duckduckgo-search
    ). Install with
    pip install ddgs
    .
  • Don't confuse
    -q
    and
    -m
    (CLI):
    -q
    is for the query,
    -m
    is for max results count.
  • Empty results: If
    ddgs
    returns nothing, it may be rate-limited. Wait a few seconds and retry.

Validated With

Validated examples against

ddgs==9.11.2
semantics. Skill guidance now treats CLI availability and Python import availability as separate concerns so the documented workflow matches actual runtime behavior.