Web search and a page reader through DuckDuckGo, with no account or API key.
- Started in our test
- ★ 1.6K GitHub stars
- 27.7K downloads a week
- Last commit 4 Sept 2026
What is DuckDuckGo Search MCP?
DuckDuckGo Search MCP is a free community server by Nick Clyde that lets an assistant search DuckDuckGo and read web pages, with no account or API key.
Nick Clyde's server is one of the simplest ways to let an assistant search the web: there is no sign-up and no key. It sends your query to DuckDuckGo, returns a tidy list of results, and can fetch a page and turn it into plain text, the main article only, or Markdown, a chunk at a time.
Because it scrapes DuckDuckGo's HTML results rather than calling a paid API, heavy use can get blocked. The server slows itself down to stay under a request limit, and an optional extra lets it imitate a real browser when DuckDuckGo turns plain requests away. A guard stops it from fetching addresses on your own network unless you allow that.
- Made by
- Nick Clyde (nickclyde/duckduckgo-mcp-server)
- Licence
- MIT
- Latest version
- 0.7.0 (4 Sept 2026)
- PyPI package
- duckduckgo-mcp-server
- GitHub stars
- 1.6K
- Downloads
- 27.7K a week
- Last commit
- 4 Sept 2026
- Tools
- 3
- Runs on
- Your computer
- Setup checked
- 27 Oct 2026
- Page updated
- 27 Oct 2026
Our check: We ran this exact config on 27 Oct 2026: it started and answered with 3 tools.
MCP Shelf take
We started DuckDuckGo Search on our own test machine on 27 Oct 2026 and it answered with 3 tools. 2 of the 3 only read; the other 1 can change things. Every tool comes with a useful description, none says whether they change things, and the tool list costs about 800 tokens of context before you ask a thing. It sits 11th of 13 in its category on our shelf by GitHub stars (1.6K, with 27.7K downloads a week).
What can DuckDuckGo Search MCP read and change?
It can read
- DuckDuckGo search results
- Any public web page the model asks to fetch
It can change
- Nothing. It only reads.
Safer setup: It is read-only already. Leave DDG_ALLOW_PRIVATE_URLS unset so the model cannot fetch addresses on your own network.
What's in the pod
What tools does DuckDuckGo Search MCP have?
We found 3 tools when we started it on 27 Oct 2026. 2 only read. The rest can change things, so keep your app's "ask before each tool call" setting on for them.
Changes things1 tool · Can create, edit, send or delete.
| Tool | What it is for |
|---|---|
expand_link | Turns a shortened ref:// link from the results back into the full address. |
Only reads2 tools · Looks things up and changes nothing.
| Tool | What it is for |
|---|---|
fetch_content | Downloads a page and returns its text, the main article only, or Markdown, in chunks you can page through. |
search | Searches DuckDuckGo and returns titles, links and snippets. Takes an optional region and result count. |
Grouped and described by us. The README on GitHub lists the inputs each tool takes.
How clearly it describes its tools to your assistant
- Tools with a description
- 3 of 3
- Say if they change things
- 0 of 3
- Context it takes, at least
- ~800 tokens
No tool says whether it only reads or can change things, so your client treats them all alike: keep approvals on.
From the tool list it sent us. The token figure counts names, descriptions and input names; the full schemas your client loads add more.
How do I install DuckDuckGo Search MCP?
Install steps from the DuckDuckGo Search MCP README
The project's own instructions, copied from its README on GitHub on 27 Oct 2026 under its MIT licence. They are the source of truth; the ready-made configs further down are built from them. The rest of the README is in the README tab.
Quick Start
uvx duckduckgo-mcp-server
What you need first
- uv, for uvx
- Nothing else: no account or key
Add DuckDuckGo Search MCP to your app
Pick your app for a ready-to-paste snippet and where it goes, built from the steps above.
Where it goes: Your terminal, in the project folder
claude mcp add duckduckgo -- uvx --with 'duckduckgo-mcp-server[browser]' duckduckgo-mcp-serverThe README's own example is claude mcp add ddg-search uvx duckduckgo-mcp-server. The version here adds the [browser] extra so searches still work when DuckDuckGo blocks plain requests.
Where it goes: ~/.cursor/mcp.json, or .cursor/mcp.json in a project
{
"mcpServers": {
"duckduckgo": {
"command": "uvx",
"args": [
"--with",
"duckduckgo-mcp-server[browser]",
"duckduckgo-mcp-server"
]
}
}
}Where it goes: claude_desktop_config.json (Settings → Developer → Edit Config)
{
"mcpServers": {
"duckduckgo": {
"command": "uvx",
"args": [
"--with",
"duckduckgo-mcp-server[browser]",
"duckduckgo-mcp-server"
]
}
}
}Where it goes: .vscode/mcp.json in your project
{
"servers": {
"duckduckgo": {
"type": "stdio",
"command": "uvx",
"args": [
"--with",
"duckduckgo-mcp-server[browser]",
"duckduckgo-mcp-server"
]
}
}
}Where it goes: ~/.codeium/windsurf/mcp_config.json
{
"mcpServers": {
"duckduckgo": {
"command": "uvx",
"args": [
"--with",
"duckduckgo-mcp-server[browser]",
"duckduckgo-mcp-server"
]
}
}
}Where it goes: Not supported
ChatGPT only connects to remote servers by URL. This one runs on your computer, so use Claude, Cursor or VS Code.
The [browser] extra lets searches fall back to a Chrome-like client when DuckDuckGo blocks plain requests, which happens often. You can drop the first two arguments for a lighter install that may return no results while blocked. Set DDG_REGION (for example "us-en") and DDG_SAFE_SEARCH in "env" if you want defaults.
Checked against the project's own install docs on 27 Oct 2026: nickclyde/duckduckgo-mcp-server README.
New to this? See the setup guides for Claude Code, Cursor, Claude Desktop and ChatGPT.
DuckDuckGo Search MCP not working? Common fixes
- Searches come back empty
- DuckDuckGo is probably blocking plain requests. Start the server with the [browser] extra, as in the config here, so it can fall back to a Chrome-like client.
- Certificate verification errors
- You are behind a proxy that re-signs HTTPS. Set DDG_CA_CERTS to your company's CA bundle.
- 421 errors when running over HTTP in Docker
- The SDK's DNS-rebinding guard only trusts localhost. Add your host name with --allowed-hosts and --allowed-origins.
- Rate limit messages
- The server holds back to avoid getting blocked. Lower your request rate, or raise DDG_SEARCH_RPM carefully.
How do I configure DuckDuckGo Search MCP?
Names are exactly as the project spells them. Required ones are marked.
| Setting | What it does |
|---|---|
DDG_SAFE_SEARCHEnvironment variable | SafeSearch level: STRICT, MODERATE (the default) or OFF.STRICT |
DDG_REGIONEnvironment variable | Default region and language for searches.us-en |
DDG_SEARCH_BACKENDEnvironment variable | auto (the default) tries a plain request and falls back to a Chrome-like client when blocked; httpx or curl force one. curl and the fallback need the [browser] extra.auto |
DDG_SEARCH_RPMEnvironment variable | Searches allowed per minute. Default 30.30 |
DDG_FETCH_RPMEnvironment variable | Page fetches allowed per minute. Default 20.20 |
DDG_PARSE_MODEEnvironment variable | Default output of fetch_content: text, main or markdown.markdown |
DDG_CA_CERTSEnvironment variable | Path to a CA bundle, for networks that re-sign HTTPS traffic./path/to/company-ca.pem |
--fetch-backendCommand line flag | Which client fetch_content uses by default: httpx, curl or auto.--fetch-backend auto |
DuckDuckGo Search MCP FAQ
How do I add DuckDuckGo Search MCP to Claude Code?
Install uv, then run claude mcp add with uvx and duckduckgo-mcp-server. Adding the [browser] extra, as in the command on this page, keeps results coming when DuckDuckGo blocks plain requests.
How do I use DuckDuckGo search in Claude Desktop?
Add an entry to claude_desktop_config.json that runs uvx duckduckgo-mcp-server, then restart Claude. Set DDG_SAFE_SEARCH and DDG_REGION in env if you want defaults.
Does DuckDuckGo Search MCP need an API key?
No. It reads DuckDuckGo's public results pages, so there is nothing to sign up for and nothing to pay.
Is it made by DuckDuckGo?
No. It is a community project that DuckDuckGo does not support, so results can break when DuckDuckGo changes its pages or limits requests.
Why does DuckDuckGo search return nothing?
DuckDuckGo is likely blocking plain requests. Install the server with the [browser] extra so it falls back to a Chrome-like client, and keep the request rate low.
Can it read the pages it finds?
Yes. fetch_content downloads a page and returns its text, main content or Markdown, and it pages through long articles. It fetches as an anonymous visitor, so pages behind a login are out of reach.
Does it work with ChatGPT?
Not as set up here. It runs on your computer, and ChatGPT only connects to servers by public URL. It has an HTTP mode, but you would have to host it yourself.
Is DuckDuckGo Search MCP free?
Yes. It is MIT licensed and uses DuckDuckGo's free public search, so there is no bill from either side.
DuckDuckGo Search MCP README
This is the project's own README from nickclyde/duckduckgo-mcp-server, written by Nick Clyde (nickclyde/duckduckgo-mcp-server), and shared under its MIT licence. We copied it on 27 Oct 2026, so the version on GitHub may be newer.
DuckDuckGo Search MCP Server
A Model Context Protocol (MCP) server that provides web search capabilities through DuckDuckGo, with additional features for content fetching and parsing.
Quick Start
uvx duckduckgo-mcp-server
Features
- Web Search: Search DuckDuckGo with advanced rate limiting and result formatting
- Content Fetching: Retrieve and parse webpage content with intelligent text extraction
- Long URL Shortening: Over-long result URLs become short
ref://tokens thatfetch_contentaccepts directly, saving context - Rate Limiting: Built-in protection against rate limits for both search and content fetching
- Error Handling: Comprehensive error handling and logging
- LLM-Friendly Output: Results formatted specifically for large language model consumption
Installation
Install from PyPI using uv:
uv pip install duckduckgo-mcp-server
Usage
Running with Claude Desktop
- Download Claude Desktop
- Create or edit your Claude Desktop configuration:
- On macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - On Windows:
%APPDATA%\Claude\claude_desktop_config.json
- On macOS:
Add the following configuration:
Basic Configuration (No SafeSearch, No Default Region):
{
"mcpServers": {
"ddg-search": {
"command": "uvx",
"args": ["duckduckgo-mcp-server"]
}
}
}
With SafeSearch and Region Configuration:
{
"mcpServers": {
"ddg-search": {
"command": "uvx",
"args": ["duckduckgo-mcp-server"],
"env": {
"DDG_SAFE_SEARCH": "STRICT",
"DDG_REGION": "cn-zh"
}
}
}
}
Configuration Options:
DDG_SAFE_SEARCH: SafeSearch filtering level (optional)STRICT: Maximum content filtering (kp=1)MODERATE: Balanced filtering (kp=-1, default if not specified)OFF: No content filtering (kp=-2)
DDG_REGION: Default region/language code (optional, examples below)us-en: United States (English)cn-zh: China (Chinese)jp-ja: Japan (Japanese)wt-wt: No specific region- Leave empty for DuckDuckGo's default behavior
DDG_CA_CERTS: Path to a PEM CA bundle used to verify TLS certificates on outbound requests (optional). Needed behind TLS-intercepting proxies — see Running behind a TLS-intercepting proxy.DDG_RATE_LIMIT_STRATEGY:sliding(default, historical 60s window) ortoken_bucket(burst, then smooth).DDG_SEARCH_RPM: Search requests per minute (default:30).DDG_FETCH_RPM: Globalfetch_contentrequests per minute (default:20).DDG_FETCH_HOST_RPM: Optional per-host fetch cap (default:0, off). Set a positive number to enable.DDG_CACHE_TTL: Seconds to keep a parsed page in the in-memoryfetch_contentcache (default:300). Paginated reads of the same URL reuse one download. Set0to disable.DDG_CACHE_MAX_ENTRIES: Maximum pages kept in that cache (default:64). Least-recently-used eviction. Set0to disable.DDG_PARSE_MODE: Defaultfetch_contentextractor (text,main, ormarkdown). Default istext(historical flattened page). Per-callparse_modeoverrides this.DDG_REF_URL_THRESHOLD: Search-result URLs longer than this many characters are replaced with shortref://<id>tokens (default:120). Set0to always show full URLs. Also--ref-url-threshold.
- Restart Claude Desktop
Running with Claude Code
- Download Claude Code
- Ensure
uvenvis installed and theuvxcommand is available - Add the MCP server:
claude mcp add ddg-search uvx duckduckgo-mcp-server
Running with SSE or Streamable HTTP
The server supports alternative transports for use with other MCP clients:
# SSE transport
uvx duckduckgo-mcp-server --transport sse
# Streamable HTTP transport
uvx duckduckgo-mcp-server --transport streamable-http
The default transport is stdio, which is used by Claude Desktop and Claude Code.
When running with sse or streamable-http, override the default bind address (127.0.0.1:8000) with the --host and --port flags:
uvx duckduckgo-mcp-server --transport streamable-http --host 0.0.0.0 --port 7070
Running behind a reverse proxy or in Docker
The MCP SDK enables DNS-rebinding protection for the HTTP transports and, by default, only accepts Host/Origin headers for localhost. Behind a reverse proxy or in a container the client's Host header won't match, so requests fail with 421 Misdirected Request.
Fix it by allow-listing the host(s) and origin(s) clients actually use (preferred over disabling protection). Values support host, host:port, and wildcard-port host:*:
uvx duckduckgo-mcp-server --transport streamable-http --host 0.0.0.0 --port 7070 \
--allowed-hosts ddg-mcp.example.com "ddg-mcp.example.com:*" \
--allowed-origins "https://ddg-mcp.example.com"
Equivalent environment variables (comma-separated) are also available: DDG_ALLOWED_HOSTS, DDG_ALLOWED_ORIGINS.
As a last resort you can turn the check off entirely with --disable-dns-rebinding-protection (or DDG_DISABLE_DNS_REBINDING_PROTECTION=1). Prefer an allow-list — disabling protection removes a defense against DNS-rebinding attacks. When nothing is configured, the secure localhost-only default is preserved.
Running behind a TLS-intercepting proxy
Corporate proxies that re-sign HTTPS traffic with their own CA (via HTTPS_PROXY) cause outbound requests to fail with certificate verification errors, because the HTTP clients don't trust the proxy's self-signed CA (and httpx no longer reads the SSL_CERT_FILE environment variable). Point the server at your proxy's CA bundle:
uvx duckduckgo-mcp-server --ca-certs /path/to/proxy-ca.pem
Or set DDG_CA_CERTS=/path/to/proxy-ca.pem. The bundle is used by both the search and fetch_content tools, on the httpx and curl backends alike.
As a last resort, --no-ssl-verify (or DDG_SSL_VERIFY=0) disables certificate verification entirely. This exposes traffic to interception by anyone on the network path — prefer --ca-certs.
Backends (bypassing bot detection)
Some sites — and, as of recently, DuckDuckGo's own search endpoint (html.duckduckgo.com) — block the default httpx client because of its distinctive TLS fingerprint, regardless of User-Agent. Cloudflare Bot Management and similar filters key on the JA3/TLS handshake, not on headers, so html.duckduckgo.com may answer httpx with an empty HTTP 202 page (silently yielding "no results"). An opt-in backend, curl (implemented via curl_cffi), impersonates a real Chrome browser's TLS handshake and passes through those checks.
Both the search tool and the fetch_content tool support these backends.
Installation:
# Default install (httpx only)
uv pip install duckduckgo-mcp-server
# With the optional browser backend
uv pip install "duckduckgo-mcp-server[browser]"
Backend options:
| Value | Behavior | Needs [browser] |
|---|---|---|
httpx |
Lightweight async HTTP. Default. Works on most sites. | no |
curl |
Uses curl_cffi with Chrome 131 TLS impersonation. Passes TLS-fingerprint-based filters. |
yes |
auto |
Tries httpx first; on 403 or a Cloudflare challenge response, retries with curl. |
yes |
Two ways to configure the backend:
Server-wide default via the
--fetch-backendCLI flag (applies to everyfetch_contentcall):# Default behavior — uses httpx uvx duckduckgo-mcp-server # Force curl for every fetch (requires the [browser] extra) uvx --with "duckduckgo-mcp-server[browser]" duckduckgo-mcp-server --fetch-backend curl # Try httpx first, fall back to curl on 403 / Cloudflare challenge uvx --with "duckduckgo-mcp-server[browser]" duckduckgo-mcp-server --fetch-backend autoPer-call override via the
backendargument on thefetch_contenttool (overrides the CLI default for that single call). The tool exposesbackendin its input schema, so an MCP client can choose"httpx","curl", or"auto"on a fetch-by-fetch basis.
For fetch_content, the default stays httpx so users who don't need the impersonation don't pay for the extra dependency.
Search backend
Because DuckDuckGo's search endpoint now fingerprint-blocks plain httpx, the search tool defaults to auto: it tries httpx first and falls back to curl when it detects a block (HTTP 202/403). The fallback only works if the [browser] extra is installed; otherwise search returns a message telling you to install it.
Configure the search backend with the --search-backend CLI flag or the DDG_SEARCH_BACKEND environment variable (auto (default) / httpx / curl):
# Recommended: install the browser extra so the auto fallback can impersonate Chrome
uvx --with "duckduckgo-mcp-server[browser]" duckduckgo-mcp-server
# Force curl for every search
uvx --with "duckduckgo-mcp-server[browser]" duckduckgo-mcp-server --search-backend curl
# Opt out of the fallback (legacy behavior — may return no results while blocked)
uvx duckduckgo-mcp-server --search-backend httpx
Development
For local development:
# Install dependencies
uv sync
# Run with the MCP Inspector
mcp dev src/duckduckgo_mcp_server/server.py
# Install locally for testing with Claude Desktop
mcp install src/duckduckgo_mcp_server/server.py
# Run all tests
uv run python -m pytest src/duckduckgo_mcp_server/ -v
# Run only unit tests
uv run python -m pytest src/duckduckgo_mcp_server/test_server.py -v
# Run only e2e tests
uv run python -m pytest src/duckduckgo_mcp_server/test_e2e.py -v
Available Tools
1. Search Tool
async def search(query: str, max_results: int = 10, region: str = "") -> str
Performs a web search on DuckDuckGo and returns formatted results.
Parameters:
query: Search query stringmax_results: Maximum number of results to return (default: 10)region: (Optional) Region/language code to override the default. Leave empty to use the configured default region.
Region Code Examples:
us-en: United States (English)cn-zh: China (Chinese)jp-ja: Japan (Japanese)de-de: Germany (German)fr-fr: France (French)wt-wt: No specific region
Returns: Formatted string containing search results with titles, URLs, and snippets.
Example Usage:
- Search with default settings:
search("python tutorial") - Search with specific region:
search("latest news", region="jp-ja")for Japanese news
2. Content Fetching Tool
async def fetch_content(
url: str,
start_index: int = 0,
max_length: int = 8000,
backend: Optional[str] = None,
parse_mode: Optional[str] = None,
) -> str
Fetches and parses content from a webpage.
Parameters:
url: The webpage URL to fetch content from, or aref://<id>token from search resultsstart_index: Character offset to start reading from (for pagination)max_length: Maximum number of characters to returnbackend: Optional per-call override of the default fetch backend ("httpx","curl", or"auto"). When omitted, uses whatever was set via--fetch-backendat server startup.parse_mode: Optional per-call extractor ("text","main", or"markdown"). When omitted, usesDDG_PARSE_MODE/--parse-mode(defaulttext).
Returns:
Cleaned and formatted text content from the webpage. The parsed full page is cached in memory (default 5 minutes) so later pages via start_index do not re-download. Metadata includes cache=hit or cache=miss when the cache is enabled.
SSRF protection: By default
fetch_contentrefuses URLs that resolve to loopback, private (RFC1918), link-local (including the169.254.169.254cloud metadata endpoint), reserved, multicast, or unspecified addresses, and it re-validates every redirect hop. Onlyhttp/httpsURLs are allowed. For trusted local deployments that need to fetch internal hosts, disable the guard withDDG_ALLOW_PRIVATE_URLS=1or--allow-private-urls. See SECURITY.md for details.
3. Link Expansion Tool
async def expand_link(token: str) -> str
Search results replace URLs longer than DDG_REF_URL_THRESHOLD characters (default 120) with short, stable ref://<id> tokens so long tracking-laden links do not eat context. fetch_content accepts a token in place of a URL, so the model only needs this tool when it has to show or cite the real link.
Parameters:
token: Aref://<id>token exactly as it appeared in search results (the bare id also works)
Returns: The full original URL, or an error if the token is unknown. Tokens live in memory for the lifetime of the server process (bounded by an LRU cap), so they are forgotten on restart.
Features in Detail
Rate Limiting
- Search: 30 requests per minute by default (
DDG_SEARCH_RPM/--search-rpm) - Content fetching: 20 requests per minute globally (
DDG_FETCH_RPM/--fetch-rpm) - Optional per-host fetch cap, off by default (
DDG_FETCH_HOST_RPM/--fetch-host-rpm) - Strategies:
sliding(default) ortoken_bucketviaDDG_RATE_LIMIT_STRATEGY/--rate-limit-strategy - HTTP 429 responses honor
Retry-After(capped at 30s) and retry once - Cache hits on
fetch_contentskip both the download and the fetch rate limiter
Content cache
- In-memory TTL cache of the fully parsed page (before pagination)
- Default TTL 300 seconds, 64 entries, least-recently-used eviction
- Errors are never cached
- Configure with
DDG_CACHE_TTL/DDG_CACHE_MAX_ENTRIESor--cache-ttl/--cache-max-entries - Set either value to
0to disable
Result Processing
- Removes ads and irrelevant content
- Cleans up DuckDuckGo redirect URLs
- Formats results for optimal LLM consumption
- Truncates long content appropriately
Content parsing modes
fetch_content accepts parse_mode:
| Mode | Behavior |
|---|---|
text |
Historical default. Strip chrome, return flattened page text. |
main |
Keep the primary article / main / content container only. |
markdown |
Same primary content, rendered as lightweight markdown (headings, lists, links, code). |
Content Safety
SafeSearch Filtering: Configured at server startup via
DDG_SAFE_SEARCHenvironment variable- Controlled by administrators, not modifiable by AI assistants
- Filters inappropriate content based on the selected level
- Uses DuckDuckGo's official
kpparameter
Region Localization:
- Default region set via
DDG_REGIONenvironment variable - Can be overridden per search request by AI assistants
- Improves result relevance for specific geographic regions
- Default region set via
Error Handling
- Comprehensive error catching and reporting
- Detailed logging through MCP context
- Graceful degradation on rate limits or timeouts
Contributing
Issues and pull requests are welcome!
License
This project is licensed under the MIT License.
Star History
Two peas, one chat
Chat with AI about DuckDuckGo Search
Opens a chat primed with DuckDuckGo Search’s README and setup docs from this page, or add it in Cursor to use its tools.
The Cursor button opens Cursor and asks before it adds the server. Fill in any keys it needs in Cursor’s MCP settings.
Peas in a pod
What are the alternatives to DuckDuckGo Search MCP?
How DuckDuckGo Search MCP lines up against its neighbours on the shelf. See every browser and web data server.

DuckDuckGo Search MCPThis pea
Web search and a page reader through DuckDuckGo, with no account or API key.
- Tools
- 3
- Runs on
- Your computer
- Licence
- MIT
- Stars
- 1.6K

Web, news, image, video and place search from Brave's own index.
- Tools
- 8
- Runs on
- Your computer
- Licence
- MIT
- Stars
- 1.5K
Microsoft's browser automation server: navigate, click, type, read.
- Tools
- 25
- Runs on
- Your computer
- Licence
- Apache-2.0
- Stars
- 38.7K

Scrape pages, crawl sites and search, returned as clean Markdown.
- Tools
- 28
- Runs on
- Your computer or hosted
- Licence
- MIT
- Stars
- 7.7K
Search built for AI: web results, page contents and code examples.
- Tools
- 2
- Runs on
- Hosted or your computer
- Licence
- MIT
- Stars
- 5.2K

Search and scraping through Bright Data, for sites that block ordinary requests.
- Tools
- 32
- Runs on
- Hosted or your computer
- Licence
- MIT
- Stars
- 2.7K
Something wrong on this page? Tell us.