# DuckDuckGo Search Scraper - Organic SERP Data (`igolaizola/duckduckgo-search-scraper`) Actor

Scrape organic duckduckgo.com SERPs with positions, titles, URLs, domains, and snippets. Localize by country, apply Safe Search and time filters, and export structured data for SEO rank tracking, competitor research, and lead discovery

- **URL**: https://apify.com/igolaizola/duckduckgo-search-scraper.md
- **Developed by:** [Iñigo Garcia Olaizola](https://apify.com/igolaizola) (community)
- **Categories:** SEO tools, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.30 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## DuckDuckGo Search Scraper — Organic SERP Data by Country & Time

Scrape organic DuckDuckGo search results and download structured ranking data
for SEO research, competitor monitoring, content discovery, and lead generation.
Use it as a privacy-focused Google Search alternative with country, Safe Search,
and publication-time filters.

### 🤖 What does DuckDuckGo Search Scraper do?

DuckDuckGo Search Scraper collects organic web results for one or more search
queries and saves them to an Apify dataset.

- **Organic rankings** — collect result positions without ads or interface widgets
- **Search result details** — extract titles, destination URLs, domains, and snippets
- **Multiple queries** — research several keywords in one run
- **Country targeting** — compare results across supported countries
- **Safe Search controls** — choose strict, moderate, or disabled filtering
- **Time filters** — focus on results from the past day, week, month, or year
- **Flexible exports** — download JSON, CSV, Excel, XML, or RSS

**Great for:** rank tracking, keyword research, competitor analysis, content
research, brand monitoring, link prospecting, and lead discovery.

> SEO keywords: **DuckDuckGo scraper**, **DuckDuckGo search results**, **organic
> SERP scraper**, **Google Search alternative**, **SEO rank tracker**,
> **DuckDuckGo API alternative**, **Apify Actor**.

### 💡 Why scrape DuckDuckGo search results?

- 📈 **Track organic visibility** — monitor which pages rank for important keywords
- 🕵️ **Research competitors** — discover the domains and content winning each SERP
- 🌍 **Compare countries** — identify regional differences in rankings and sources
- 📰 **Find recent content** — narrow discovery to a recent publication period
- 🔗 **Build prospect lists** — collect relevant websites for outreach or enrichment
- 🤖 **Power automated workflows** — connect structured search data to APIs, agents, and dashboards

### 🚀 Quick Start

1. **Add the Actor** — open DuckDuckGo Search Scraper in Apify Store.
2. **Enter your searches** — add one or more values to `queries`.
3. **Choose a limit** — set `maxItems` and, if needed, `maxPagesPerQuery`.
4. **Refine the search** — select `country`, `safeSearch`, or `timeRange`.
5. **Run the Actor** — click **Run** or start it through the Apify API or SDK.
6. **Download results** — open the **Dataset** tab and export your preferred format.

### 📝 Input Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `queries` | Array of strings | Yes | One or more DuckDuckGo search queries, processed in the order provided. |
| `maxItems` | Integer | Yes | Maximum results saved across all queries. Default `10`. Set `0` to use only the per-query page limit. |
| `country` | String | No | Two-letter country code for localized results, such as `us`, `gb`, `de`, `es`, or `ru`. Default `us`. |
| `proxyCountry` | String | No | Optional two-letter country code for the network location. Leave empty to use the configured proxy pool. |
| `safeSearch` | Enum | No | Explicit-content filtering: `"strict"` · `"moderate"` · `"off"`. Default `"moderate"`. |
| `timeRange` | Enum | No | Publication-time filter: `"any"` · `"day"` · `"week"` · `"month"` · `"year"`. Default `"any"`. |
| `maxPagesPerQuery` | Integer | No | Maximum result pages collected for each query, from `1` to `10`. Default `10`. |

Unsupported country codes fall back to `us`. Use `gb` for the United Kingdom;
the common `uk` alias is also accepted.

**SEO rank research across several keywords**

```json
{
  "queries": [
    "best web scraping tools",
    "browser automation platform",
    "data for AI agents"
  ],
  "maxItems": 100,
  "country": "us",
  "safeSearch": "moderate",
  "timeRange": "any",
  "maxPagesPerQuery": 10
}
```

**Recent German-language market research**

```json
{
  "queries": [
    "Datenschutz Browser",
    "Suchmaschinen Marktanteil"
  ],
  "maxItems": 40,
  "country": "de",
  "proxyCountry": "de",
  "safeSearch": "strict",
  "timeRange": "month",
  "maxPagesPerQuery": 4
}
```

### 📊 Output Results

Each dataset item contains one organic DuckDuckGo search result:

- **query** *(string)* — search query that produced the result
- **position** *(number)* — result position in the complete dataset
- **title** *(string)* — result headline
- **url** *(string)* — destination URL
- **displayUrl** *(string, optional)* — readable URL shown in search results
- **domain** *(string, optional)* — destination hostname
- **snippet** *(string, optional)* — descriptive text shown with the result

Example result:

```json
{
  "query": "best web scraping tools",
  "position": 1,
  "title": "Apify Store - 53,000+ web scraping and automation tools",
  "url": "https://apify.com/store",
  "displayUrl": "apify.com/store",
  "domain": "apify.com",
  "snippet": "Ready-to-use web scraping and automation tools for popular websites and data workflows."
}
```

Positions are contiguous across the complete run, including runs containing
multiple queries.

### 🧭 Tips & Common Recipes

- **Track one keyword deeply:** use one query with a higher `maxItems` value.
- **Compare several topics:** add multiple queries and set a shared result limit.
- **Monitor recent coverage:** set `timeRange` to `"day"`, `"week"`, or `"month"`.
- **Compare markets:** repeat the same query in separate runs with different `country` values.
- **Align regional signals:** set `country` and `proxyCountry` to the same code.
- **Control sensitive results:** choose `"strict"` or `"off"` with `safeSearch`.

### ⚙️ Best Practices

- Use focused queries to improve the relevance of collected domains and snippets.
- Keep the same country and filters when comparing rankings over time.
- Set a realistic `maxItems` limit to avoid collecting results you do not need.
- Search rankings change naturally by location, time, and DuckDuckGo index updates.

### 🌍 Proxy Usage

Residential proxies are recommended for reliable search collection at scale.
Use `proxyCountry` when the network location should match a specific market;
otherwise, leave it empty and rely on the configured proxy pool.

### ⚖️ Legal & Ethical Considerations

- Follow DuckDuckGo's terms, policies, and applicable robots instructions.
- Use reasonable collection volumes and avoid abusive traffic patterns.
- Handle personal data responsibly and comply with applicable privacy laws, including GDPR.
- Respect copyright, database rights, and attribution requirements when republishing data.
- Confirm that your intended use is lawful in the relevant jurisdiction.

This Actor is an independent tool and is **not affiliated with, endorsed by, or
sponsored by DuckDuckGo**. All trademarks are the property of their respective
owners.

### ❓ FAQ

**Can I search more than one query in a run?**

Yes. Add each search term to `queries`. Results are collected in the same order
and share the global `maxItems` limit.

**What is the difference between `country` and `proxyCountry`?**

`country` localizes the search results. `proxyCountry` selects the requested
network location. Matching them generally gives the most consistent regional
results, but they can differ when your workflow requires it.

**Does the Actor include advertisements?**

No. The output focuses on organic search results.

**Why did I receive fewer results than `maxItems`?**

`maxItems` is a maximum, not a guarantee. A query can have fewer available
results, and `maxPagesPerQuery` can stop collection before the global limit.

**Can I use the results through an API?**

Yes. Start runs and retrieve dataset items with the Apify API, JavaScript SDK,
Python SDK, webhooks, or integrations.

### 🛟 Support

Need a custom field, search option, or export workflow?

Open an issue or contact the developer at
https://igolaizola.com/#contact or https://t.me/igolaizola.

# Actor input Schema

## `queries` (type: `array`):

One or more DuckDuckGo web-search queries. Each query is paginated before the next one starts.

## `maxItems` (type: `integer`):

Maximum number of organic search results to save across all queries. Use 0 to rely only on the per-query page limit.

## `country` (type: `string`):

Two-letter ISO country code used to localize results, such as us, gb, de, es, or ru.

## `proxyCountry` (type: `string`):

Optional two-letter country code for the proxy exit location. Search localization is controlled separately by country.

## `safeSearch` (type: `string`):

Level of explicit-content filtering applied by DuckDuckGo.

## `timeRange` (type: `string`):

Only return pages published or updated within the selected period.

## `maxPagesPerQuery` (type: `integer`):

Maximum DuckDuckGo result pages collected for each query.

## Actor input object example

```json
{
  "queries": [
    "apify"
  ],
  "maxItems": 10,
  "country": "us",
  "proxyCountry": "",
  "safeSearch": "moderate",
  "timeRange": "any",
  "maxPagesPerQuery": 10
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "queries": [
        "apify"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("igolaizola/duckduckgo-search-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "queries": ["apify"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("igolaizola/duckduckgo-search-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "queries": [
    "apify"
  ],
  "maxItems": 10
}' |
apify call igolaizola/duckduckgo-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=igolaizola/duckduckgo-search-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/fU0PdxgbpTUcYSgP0/builds/nGvQv2PpTBrCCyndr/openapi.json
