# Keyword Research & SERP Data (`datascraperes/keyword-research-serp`) Actor

Research keywords, search-result data, related terms, and keyword clusters from publicly accessible search intelligence pages.

- **URL**: https://apify.com/datascraperes/keyword-research-serp.md
- **Developed by:** [DataScraperES](https://apify.com/datascraperes) (community)
- **Categories:** SEO tools, Automation, Developer tools
- **Stats:** 4 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.75 / 1,000 keyword analyzeds

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/actors/running/actors-in-store.md#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

Research seed keywords and receive market-specific search volume, ranking difficulty, SERP competitors, related opportunities, and topic clusters in export-ready datasets. Start with one keyword and a two-letter market code, then select only the report sections your workflow needs.

### What this Actor does

Keyword Research & SERP Data turns up to 25 unique seed terms into structured keyword and search-results intelligence. The default Dataset gives one summary per keyword, while separate datasets hold organic rankings, keyword ideas, clusters, and paid SERP history for detailed analysis.

### Use cases

- Build and prioritize SEO content plans with volume and difficulty signals.
- Discover related keywords and high-priority opportunities around seed topics.
- Review organic competitors, top-ranking domains, and SERP features.
- Group keyword ideas into topics for briefs, site architecture, or campaigns.

### How to use

1. Open the Actor in Apify Console.
2. Add one or more seed keywords, choose the market, and select report sections.
3. Click **Start** and open the Dataset when the run finishes.

### Input

`keywords` is required and accepts up to 25 unique terms; blanks and duplicates are removed. `countryCode` defaults to `ES` and expects a two-letter market code such as `ES`, `US`, or `UK`. `sections` defaults to `serp`, `stats`, `suggestions`, `related`, and `clusters`. `relatedLimit` defaults to 5 and allows 1–100 rows per related source; `serpRows` defaults to 30 and allows 1–100 organic rows. `topDomain` is used only with `top_url`. `delaySeconds` ranges from 0 to 30, and `continueOnError` defaults to `true`.

```json
{
  "keywords": [
    "seo"
  ],
  "countryCode": "ES",
  "sections": [
    "serp",
    "stats",
    "suggestions",
    "related",
    "clusters"
  ],
  "relatedLimit": 5,
  "serpRows": 10,
  "delaySeconds": 0,
  "continueOnError": true
}
```

### Output

The default Dataset contains one keyword-level report. Additional named datasets provide row-level organic SERP results, keyword opportunities, clusters, and paid history when those sections return data. The `sectionsWithData` array shows exactly which sources produced usable information.

This is the complete default Dataset item from a real successful run:

```json
{
  "keyword": "seo",
  "countryCode": "ES",
  "ok": true,
  "sectionsRequested": [
    "serp",
    "stats",
    "suggestions",
    "related",
    "clusters"
  ],
  "sectionsWithData": [
    "organic_serp",
    "paid_serp_history",
    "keyword_stats",
    "suggestions",
    "related_keywords",
    "keyword_clusters",
    "keyword_group_stats"
  ],
  "liveSearchVolume": 39700,
  "rankingDifficulty": 17,
  "paidCompetitors": 99,
  "serpFeatures": "Knowledge Panel,People Also Ask,Videos",
  "topOrganicResult": "seo.org",
  "organicResultCount": 10,
  "keywordIdeaCount": 25,
  "highPriorityOpportunityCount": 13,
  "clusterCount": 5,
  "paidHistoryCount": 4,
  "errorCode": null,
  "errorMessage": null
}
```

### Pricing

Each successful keyword analysis written to the Dataset triggers one `keyword-analyzed` event. Apify selects the tier from your account plan automatically.

| Apify plan tier | Price per keyword | Equivalent per 1,000 keywords |
|---|---:|---:|
| Free | $0.001 | $1.00 |
| Bronze | $0.0009 | $0.90 |
| Silver | $0.0008 | $0.80 |
| Gold | $0.00075 | $0.75 |
| Platinum | $0.00075 | $0.75 |
| Diamond | $0.00075 | $0.75 |

There is no separate Actor-start charge. Failed keyword rows and requested sections that return no usable data do not trigger the event. You can set a maximum total charge in Apify before starting a run.

### Related Actors

| Actor | Best for |
|---|---|
| [Google SERP Scraper API – Search Results Scraper](https://apify.com/datascraperes/google-serp-scraper) | Collecting ranked Google organic results for a focused list of queries. |
| [Bing Search Scraper – SERP Results](https://apify.com/datascraperes/bing-search-scraper) | Comparing keyword visibility and competitors in Bing across supported markets. |
| [Yahoo Search Results Scraper](https://apify.com/datascraperes/yahoo-search-scraper) | Exporting paginated Yahoo organic results for keyword monitoring. |
| [DuckDuckGo Search Scraper — Organic SERP API](https://apify.com/datascraperes/duckduckgo-search-results-scraper) | Measuring privacy-focused organic results across DuckDuckGo regions. |

### Limits and data quality

Each run accepts at most 25 unique seed keywords. Search volume, difficulty, competitors, paid history, and SERP composition are market-specific snapshots and can change between runs. A requested section can legitimately return no rows; use `sectionsWithData` and the count fields instead of assuming every section is populated. The upstream source may return fewer organic or related rows than requested. For temporary rate limits or incomplete large batches, retry affected keywords with a small `delaySeconds` value.

### Frequently asked questions

#### Which country code should I use for the United Kingdom?

Use `UK`, not `GB`, as specified by the Actor's market input.

#### Why are some counts zero even though the run succeeded?

Success means the keyword report completed. Individual sections can still have no available data for that keyword and market.

#### When should I use `topDomain`?

Use it only when `top_url` is included in `sections`; enter a bare domain without protocol, path, or spaces.

### Responsible use

Use search intelligence responsibly and comply with applicable laws, contractual requirements, and third-party rights. Metrics are estimates and snapshots; validate important business decisions with additional evidence.

### Support

Open the Actor's **Issues** tab with the run ID, exact input, affected keyword and market, requested sections, and the expected versus actual result.

# Actor input Schema

## `keywords` (type: `array`):

Required. Add one seed keyword per item, exactly as people search for it. You may enter up to 25 unique terms; blanks and duplicates are removed. Example: seo, abogados madrid, email marketing software.

## `countryCode` (type: `string`):

Required market for every keyword. Use a two-letter code: ES for Spain, US for United States, UK for United Kingdom (not GB). The same keyword can produce different volume, difficulty and SERP data in each market.

## `sections` (type: `array`):

Choose one or more values: stats for volume/difficulty; related for scored keyword opportunities; serp for organic and paid results; suggestions for extra unscored query ideas; clusters for top topics; top\_url only when topDomain is filled. More sections return more datasets and can take longer.

## `relatedLimit` (type: `integer`):

Maximum requested rows for each related-keyword and cluster source. Start with 5. Raise it only when you need a broader idea list; the upstream service may still return fewer items.

## `serpRows` (type: `integer`):

Maximum organic ranking URLs to return per keyword when serp is selected. Use 10 for a quick competitor review or 30 for deeper analysis. The upstream service may return fewer rows.

## `topDomain` (type: `string`):

Optional. Use only together with top\_url. Enter a bare domain without http://, https://, paths or spaces, for example example.com. The Actor returns the URL from that domain which ranks best for each seed keyword. Leave empty when you do not need this comparison.

## `delaySeconds` (type: `number`):

Optional wait between upstream requests. Zero is the fastest tested sequential mode. If a large run returns rate-limit errors or incomplete data, retry affected keywords with 1–3 seconds. Higher values increase runtime.

## `continueOnError` (type: `boolean`):

Recommended. When enabled, a failure for one keyword creates an uncharged error row and the Actor continues with the rest. Disable only when you need the run to stop at the first keyword failure.

## Actor input object example

```json
{
  "keywords": [
    "seo",
    "abogados madrid"
  ],
  "countryCode": "ES",
  "sections": [
    "serp",
    "stats",
    "suggestions",
    "related",
    "clusters"
  ],
  "relatedLimit": 5,
  "serpRows": 30,
  "topDomain": "semrush.com",
  "delaySeconds": 0,
  "continueOnError": true
}
```

# Actor output Schema

## `keywordIdeas` (type: `string`):

Prioritized keyword opportunities with metrics, intent, score, and recommendation.

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

One decision-ready summary per processed keyword.

## `organicSerp` (type: `string`):

One row per organic result, ready to filter or export.

## `keywordClusters` (type: `string`):

Flattened topic clusters with hierarchy, size, and score.

## `paidSerpHistory` (type: `string`):

Historical paid results, one row per ad observation.

## `summary` (type: `string`):

Summary of input, processed reports, failures, and charge-limit status.

# 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 = {
    "keywords": [
        "seo"
    ],
    "countryCode": "ES",
    "sections": [
        "serp",
        "stats",
        "suggestions",
        "related",
        "clusters"
    ],
    "relatedLimit": 5,
    "serpRows": 30,
    "topDomain": "semrush.com",
    "delaySeconds": 0,
    "continueOnError": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascraperes/keyword-research-serp").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 = {
    "keywords": ["seo"],
    "countryCode": "ES",
    "sections": [
        "serp",
        "stats",
        "suggestions",
        "related",
        "clusters",
    ],
    "relatedLimit": 5,
    "serpRows": 30,
    "topDomain": "semrush.com",
    "delaySeconds": 0,
    "continueOnError": True,
}

# Run the Actor and wait for it to finish
run = client.actor("datascraperes/keyword-research-serp").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "keywords": [
    "seo"
  ],
  "countryCode": "ES",
  "sections": [
    "serp",
    "stats",
    "suggestions",
    "related",
    "clusters"
  ],
  "relatedLimit": 5,
  "serpRows": 30,
  "topDomain": "semrush.com",
  "delaySeconds": 0,
  "continueOnError": true
}' |
apify call datascraperes/keyword-research-serp --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datascraperes/keyword-research-serp"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/9A45DJWtf0eW4o3pQ/builds/Fhnf6NkAxHnsuBueg/openapi.json
