DuckDuckGo MCP: Rank Checking and SERP Research
Point an agent at a live DuckDuckGo SERP and answer the questions people actually ask about it. Where does my domain rank for this term? Who sits above me? Does that change in the UK, or in Germany, or if I only count results from the past month?
DuckDuckGo pulls from a different index than Google, so a site that ranks well on one often does not on the other. This skill turns that gap into something you can measure.
When to use this skill
- The user asks about "DuckDuckGo MCP" or wants a DuckDuckGo tool their agent can call.
- They want to check where a domain ranks on DuckDuckGo for a keyword.
- They want to see which competitors outrank them on DuckDuckGo, and with what page titles.
- They want to compare the same query across regions, or before and after a content change.
- They want an agent to ground an answer in live search results rather than in what it remembers.
Not for: bulk SERP exports and pipeline work (use the companion DuckDuckGo scraper skill), or Google, Yandex, and Baidu rankings (see references/actor-index.md).
Prerequisites
The Actor
Connect it as an MCP tool
The Actor is MCP-ready. Add the hosted server URL to Claude, Cursor, or any MCP client:
https://mcp.apify.com/?tools=actors,docs,johnvc/DuckDuckGo-Scraper-for-serp-rankings
MCP setup docs: https://docs.apify.com/platform/integrations/mcp
Once connected, prompts like these work directly:
- "Where does example.com rank on DuckDuckGo for 'privacy focused search engine'?"
- "Show me the top ten DuckDuckGo results for 'open source CRM' in the UK and flag anyone I compete with."
- "Run that same query restricted to the past month and tell me what changed."
Workflow
- Fix the query and the market. One keyword per run. Set
localization to the region and language you care about, us-en by default, uk-en, de-de, fr-fr and 38 more available.
- Decide the depth.
max_pages 1 is enough for a top-of-page check. Use 2 for a top-50-ish read. Deeper only if the domain is genuinely buried.
- Run the Actor and take the single page item back.
- Find the position. Walk
organic_results and match the target domain against each row's link. The row's position is the rank on that page. If you paginated, keep page_number so you can report the page as well as the position.
- Read the neighbourhood. The rows above the target, with their
title and snippet, are the pages you are actually losing to. Their title text is usually the fastest signal for what the engine thinks the query means.
- Repeat to compare. Same query, different
localization, gives a regional read. Same query with date_filter set to m or an explicit range gives a freshness read. Same query re-run later gives movement.
Rank check with the Apify CLI
Top page of results for a keyword, US English:
apify actors call "johnvc/DuckDuckGo-Scraper-for-serp-rankings" -i '{"query":"privacy focused search engine","max_pages":1}' \
--json \
--user-agent apify-awesome-skills/apify-duckduckgo-mcp-serp-research \
2>/dev/null
Same keyword in the UK, two pages deep, for a wider rank check:
apify actors call "johnvc/DuckDuckGo-Scraper-for-serp-rankings" -i '{"query":"privacy focused search engine","localization":"uk-en","max_pages":2}' \
--json \
--user-agent apify-awesome-skills/apify-duckduckgo-mcp-serp-research \
2>/dev/null
Fresh results only, past month, to see what recently published pages are winning:
apify actors call "johnvc/DuckDuckGo-Scraper-for-serp-rankings" -i '{"query":"best password manager","date_filter":"m","max_pages":1}' \
--json \
--user-agent apify-awesome-skills/apify-duckduckgo-mcp-serp-research \
2>/dev/null
Every call carries the three flags this repo expects: --json, --user-agent apify-awesome-skills/apify-duckduckgo-mcp-serp-research, and 2>/dev/null.
What comes back (one item per page)
Confirmed on a live run. Each dataset item is a whole page, and the ranked rows live in a nested array on it.
organic_results array. Every row has position, title, link, snippet, favicon. Rows carry date and date_raw when DuckDuckGo shows a published date (9 of 11 rows on the test query).
- Run echo:
query, localization, safe_search, max_pages, search_timestamp.
- Counters:
total_results_found, pages_processed, page_number.
search_metadata: localization, localization_name, safe_search, safe_search_description, max_pages, pagination_limit_reached.
pagination_info: total_pages, max_pages_set, pagination_stopped_by_limit, and results_per_page with first_page and subsequent_pages.
ads, knowledge_graph, news_results, inline_images, inline_videos, related_searches come back as arrays on every item and fill in only when DuckDuckGo renders those blocks. All six were empty for the informational test query.
search_timestamp is what makes a series comparable. Store it with every reading.
Reading a rank honestly
- A position is a snapshot for one query, one region, one moment. Two readings do not make a trend.
- Page size is not uniform. The live run reported 11 results on the first page and 50 on subsequent pages, so never compute a global rank by multiplying
page_number by a fixed page size. Use results_per_page or just concatenate the arrays in order.
- If the domain does not appear at all, say "not found in the first N results", not "not ranking". Absence within
max_pages is not absence from the index.
- DuckDuckGo rankings are not Google rankings. Do not present one as a proxy for the other.
- A missing
date on a row means DuckDuckGo did not show one, not that the page is old.
Cost
Pay per event: a fractions-of-a-cent setup fee per run plus a per-page fee. A one-page rank check costs about a penny, so daily tracking of a small keyword set is cheap. The arithmetic and confirmation thresholds are in references/gotchas.md.
Troubleshooting
- Domain not in
organic_results: raise max_pages to 2, then stop. Deeper pages rarely change a decision.
- Positions shifted with no content change: normal SERP movement. Re-read before reporting a drop.
- Wrong-country results:
localization is a combined region and language code, so setting de-de also switches the language to German.
- Rejected
date_filter: use d, w, m, y, or exactly YYYY-MM-DD..YYYY-MM-DD.
See references/gotchas.md for cost guardrails and error recovery, and references/actor-index.md for the Actor routing table.
Related search Actors
1---2name: apify-duckduckgo-mcp-serp-research3description: Check where a site ranks on DuckDuckGo and research a live SERP from an AI agent, using the Apify DuckDuckGo Scraper Actor (johnvc/DuckDuckGo-Scraper-for-serp-rankings) as a hosted duckduckgo mcp tool. Run a query, read the ranked organic_results rows (position, title, link, snippet, favicon), find a domain's position, list the competitors above it, and repeat the query across regions or date windows to see how a privacy-first engine ranks differently from Google. Use when the user asks about duckduckgo mcp, wants to check a DuckDuckGo ranking, see where a site sits on DuckDuckGo, compare competitor visibility on DuckDuckGo, watch a position over time, or ground an agent's answer in live DuckDuckGo results instead of training data. Pay-per-page billing, MCP-ready for Claude and other AI agents.4license: MIT5---67# DuckDuckGo MCP: Rank Checking and SERP Research89Point an agent at a live DuckDuckGo SERP and answer the questions people actually ask about it. Where does my domain rank for this term? Who sits above me? Does that change in the UK, or in Germany, or if I only count results from the past month?1011DuckDuckGo pulls from a different index than Google, so a site that ranks well on one often does not on the other. This skill turns that gap into something you can measure.1213## When to use this skill1415- The user asks about "DuckDuckGo MCP" or wants a DuckDuckGo tool their agent can call.16- They want to check where a domain ranks on DuckDuckGo for a keyword.17- They want to see which competitors outrank them on DuckDuckGo, and with what page titles.18- They want to compare the same query across regions, or before and after a content change.19- They want an agent to ground an answer in live search results rather than in what it remembers.2021Not for: bulk SERP exports and pipeline work (use the companion DuckDuckGo scraper skill), or Google, Yandex, and Baidu rankings (see `references/actor-index.md`).2223## Prerequisites2425- Apify account (sign up at https://apify.com?fpr=9n7kx3&fp_sid=skillrepo).26- Authentication via `apify login`, or an `APIFY_TOKEN` environment variable (Apify Console, Settings, Integrations).2728## The Actor2930- Store page: https://apify.com/johnvc/DuckDuckGo-Scraper-for-serp-rankings?fpr=9n7kx3&fp_sid=skillrepo31- Actor ID: `johnvc/DuckDuckGo-Scraper-for-serp-rankings`32- Pricing: a tiny per-run setup fee plus a per-page fee (see `references/gotchas.md`).3334## Connect it as an MCP tool3536The Actor is MCP-ready. Add the hosted server URL to Claude, Cursor, or any MCP client:3738`https://mcp.apify.com/?tools=actors,docs,johnvc/DuckDuckGo-Scraper-for-serp-rankings`3940MCP setup docs: https://docs.apify.com/platform/integrations/mcp4142Once connected, prompts like these work directly:4344- "Where does example.com rank on DuckDuckGo for 'privacy focused search engine'?"45- "Show me the top ten DuckDuckGo results for 'open source CRM' in the UK and flag anyone I compete with."46- "Run that same query restricted to the past month and tell me what changed."4748## Workflow49501. Fix the query and the market. One keyword per run. Set `localization` to the region and language you care about, `us-en` by default, `uk-en`, `de-de`, `fr-fr` and 38 more available.512. Decide the depth. `max_pages` 1 is enough for a top-of-page check. Use 2 for a top-50-ish read. Deeper only if the domain is genuinely buried.523. Run the Actor and take the single page item back.534. Find the position. Walk `organic_results` and match the target domain against each row's `link`. The row's `position` is the rank on that page. If you paginated, keep `page_number` so you can report the page as well as the position.545. Read the neighbourhood. The rows above the target, with their `title` and `snippet`, are the pages you are actually losing to. Their `title` text is usually the fastest signal for what the engine thinks the query means.556. Repeat to compare. Same query, different `localization`, gives a regional read. Same query with `date_filter` set to `m` or an explicit range gives a freshness read. Same query re-run later gives movement.5657## Rank check with the Apify CLI5859Top page of results for a keyword, US English:6061```bash62apify actors call "johnvc/DuckDuckGo-Scraper-for-serp-rankings" -i '{"query":"privacy focused search engine","max_pages":1}' \63 --json \64 --user-agent apify-awesome-skills/apify-duckduckgo-mcp-serp-research \65 2>/dev/null66```6768Same keyword in the UK, two pages deep, for a wider rank check:6970```bash71apify actors call "johnvc/DuckDuckGo-Scraper-for-serp-rankings" -i '{"query":"privacy focused search engine","localization":"uk-en","max_pages":2}' \72 --json \73 --user-agent apify-awesome-skills/apify-duckduckgo-mcp-serp-research \74 2>/dev/null75```7677Fresh results only, past month, to see what recently published pages are winning:7879```bash80apify actors call "johnvc/DuckDuckGo-Scraper-for-serp-rankings" -i '{"query":"best password manager","date_filter":"m","max_pages":1}' \81 --json \82 --user-agent apify-awesome-skills/apify-duckduckgo-mcp-serp-research \83 2>/dev/null84```8586Every call carries the three flags this repo expects: `--json`, `--user-agent apify-awesome-skills/apify-duckduckgo-mcp-serp-research`, and `2>/dev/null`.8788## What comes back (one item per page)8990Confirmed on a live run. Each dataset item is a whole page, and the ranked rows live in a nested array on it.9192- `organic_results` array. Every row has `position`, `title`, `link`, `snippet`, `favicon`. Rows carry `date` and `date_raw` when DuckDuckGo shows a published date (9 of 11 rows on the test query).93- Run echo: `query`, `localization`, `safe_search`, `max_pages`, `search_timestamp`.94- Counters: `total_results_found`, `pages_processed`, `page_number`.95- `search_metadata`: `localization`, `localization_name`, `safe_search`, `safe_search_description`, `max_pages`, `pagination_limit_reached`.96- `pagination_info`: `total_pages`, `max_pages_set`, `pagination_stopped_by_limit`, and `results_per_page` with `first_page` and `subsequent_pages`.97- `ads`, `knowledge_graph`, `news_results`, `inline_images`, `inline_videos`, `related_searches` come back as arrays on every item and fill in only when DuckDuckGo renders those blocks. All six were empty for the informational test query.9899`search_timestamp` is what makes a series comparable. Store it with every reading.100101## Reading a rank honestly102103- A position is a snapshot for one query, one region, one moment. Two readings do not make a trend.104- Page size is not uniform. The live run reported 11 results on the first page and 50 on subsequent pages, so never compute a global rank by multiplying `page_number` by a fixed page size. Use `results_per_page` or just concatenate the arrays in order.105- If the domain does not appear at all, say "not found in the first N results", not "not ranking". Absence within `max_pages` is not absence from the index.106- DuckDuckGo rankings are not Google rankings. Do not present one as a proxy for the other.107- A missing `date` on a row means DuckDuckGo did not show one, not that the page is old.108109## Cost110111Pay per event: a fractions-of-a-cent setup fee per run plus a per-page fee. A one-page rank check costs about a penny, so daily tracking of a small keyword set is cheap. The arithmetic and confirmation thresholds are in `references/gotchas.md`.112113## Troubleshooting114115- Domain not in `organic_results`: raise `max_pages` to 2, then stop. Deeper pages rarely change a decision.116- Positions shifted with no content change: normal SERP movement. Re-read before reporting a drop.117- Wrong-country results: `localization` is a combined region and language code, so setting `de-de` also switches the language to German.118- Rejected `date_filter`: use `d`, `w`, `m`, `y`, or exactly `YYYY-MM-DD..YYYY-MM-DD`.119120See `references/gotchas.md` for cost guardrails and error recovery, and `references/actor-index.md` for the Actor routing table.121122## Related search Actors123124- DuckDuckGo scraper (bulk SERP export, the companion skill for this Actor)125- Yandex Search Scraper: https://apify.com/johnvc/Scrape-Yandex?fpr=9n7kx3&fp_sid=skillrepo126- Baidu Search Scraper: https://apify.com/johnvc/Baidu-Search-Scraper?fpr=9n7kx3&fp_sid=skillrepo127- Naver Search API (Korea): https://apify.com/johnvc/naver-search-api?fpr=9n7kx3&fp_sid=skillrepo