# Keyword Research API — Ahrefs / SEMRush / Moz Alternative (`khadinakbar/dataforseo-keyword-research`) Actor

Discover keyword ideas or Google Ads search-volume metrics from bounded seed keywords. Returns normalized, source-provenanced rows with explicit cost and terminal outcomes.

- **URL**: https://apify.com/khadinakbar/dataforseo-keyword-research.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** SEO tools, Automation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 keyword research results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Keyword Research Tool — DataForSEO API

Discover Google keyword ideas or retrieve Google Ads search-volume metrics from a bounded seed list. This private Actor uses the documented DataForSEO API, returns one normalized dataset row per delivered keyword, and records the request endpoint, provider task ID, and collection time on every row.

### Best fit

Use this for SEO teams that need a reproducible keyword-research export inside an Apify workflow. Choose `keyword_ideas` to expand a topic into related phrases, or `search_volume` to evaluate a known shortlist with Google Ads volume, CPC, and competition data.

**Use when** you have one to ten seed phrases and need a bounded, provider-provenanced keyword dataset for planning or automation. **Avoid when** you need observed SERP positions, a domain's organic-keyword inventory, live Google result scraping, or a ranking guarantee; this Actor is keyword research, not rank tracking or site auditing.

For observed Google SERP positions, pair the selected research keywords with the [Keyword Rank Tracker](https://apify.com/khadinakbar/keyword-rank-tracker). Treat modeled search volume, CPC, difficulty, and intent as planning context alongside first-party analytics.

### Inputs

| Input | Use |
|---|---|
| `mode` | `keyword_ideas` for related terms, `search_volume` for supplied keywords. |
| `seedKeywords` | One to ten seed phrases; duplicates and blanks are removed. |
| `locationCode` / `languageCode` | DataForSEO market context; default is US English (`2840`, `en`). |
| `maxResults` | Bounded output cap from 1–50; default 25. |
| `minSearchVolume` | Optional post-response filter; it does not change provider coverage. |
| `includeSerpInfo` | Adds available SERP features for keyword ideas; default false. |

### Quick start

#### Discover keyword ideas

```json
{
  "mode": "keyword_ideas",
  "seedKeywords": ["keyword research"],
  "locationCode": 2840,
  "languageCode": "en",
  "maxResults": 25,
  "minSearchVolume": 100,
  "includeSerpInfo": false
}
```

#### Example: evaluate a known shortlist

```json
{
  "mode": "search_volume",
  "seedKeywords": ["keyword research", "keyword research tool"],
  "locationCode": 2840,
  "languageCode": "en",
  "maxResults": 10
}
```

### Output

Each dataset row has a stable, agent-readable shape: `keyword`, `searchVolume`, `monthlySearches`, `cpcUsd`, `competition`, `competitionLevel`, `keywordDifficulty`, `searchIntent`, `serpFeatures`, market context, and `provenance`.

```json
{
  "mode": "keyword_ideas",
  "keyword": "keyword research tools",
  "seedKeywords": ["keyword research"],
  "searchVolume": 1200,
  "keywordDifficulty": 32,
  "searchIntent": "commercial",
  "locationCode": 2840,
  "languageCode": "en",
  "provenance": {
    "source": "DataForSEO API v3",
    "endpoint": "dataforseo_labs/google/keyword_ideas/live"
  }
}
```

Read `OUTPUT` for the compact terminal outcome and `RUN_SUMMARY` for provider attempts, provider cost, request context, and warnings. `COMPLETE` means all normalized rows persisted; `PARTIAL` preserves useful rows; `VALID_EMPTY` means a valid provider response had no matching rows; `INVALID_INPUT`, `CONFIG_ERROR`, and `UPSTREAM_FAILED` explain non-success states honestly.

### Verification and freshness

The DataForSEO request/response contract, row schema, and billed-event parity were last verified against private Apify build `1.0.4` on 2026-08-10 using 20 distinct cloud runs, including both supported endpoints and terminal-record readback.

### Pricing and cost boundary

This Actor uses **Pay per event + platform usage**. Apify charges $0.01 per validated `keyword-research-result` persisted, plus a $0.00005 Actor-start event; check the live **Pricing tab** for the effective current prices and usage terms. DataForSEO charges the provider account separately per request; each run reports the provider-reported cost in `RUN_SUMMARY.providerCostUsd`.

Start with one seed and `maxResults: 10` when validating an account. The Actor never sends an unbounded query and caps dataset output at 50 rows. DataForSEO’s Google Ads search-volume API accepts up to 1,000 keywords per request, while this Actor deliberately uses a smaller cap for predictable evidence and billing. [DataForSEO Google Ads Search Volume](https://docs.dataforseo.com/v3/keywords_data-google_ads-search_volume-live/)

### API and agent workflow

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~dataforseo-keyword-research/runs" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode":"keyword_ideas","seedKeywords":["keyword research"],"locationCode":2840,"languageCode":"en","maxResults":25}'
```

#### MCP prompt

> Run `khadinakbar/dataforseo-keyword-research` to find US-English keyword ideas for `keyword research`. Return the top 25 rows with keyword, searchVolume, keywordDifficulty, cpcUsd, searchIntent, provenance, and the `OUTPUT` outcome. Read the `keyword_research` dataset view, use `RUN_SUMMARY` for provider cost, and tighten `maxResults` when a smaller response is useful.

### Limits and responsible use

DataForSEO metrics are provider estimates whose scope depends on the selected location, language, endpoint, and provider freshness. Keep credentials in Actor secrets or private input; they are used only for the provider authorization header and are never written to output. Use only a DataForSEO account you are authorized to access and follow its terms and your organization’s data-retention requirements.

### Builder's note

I built this around DataForSEO's separate keyword-ideas and Google Ads search-volume endpoints because they have different data semantics and billing surfaces. Each row carries the endpoint and provider task ID, while the output cap ties useful persisted data to a predictable Apify event. The terminal contract keeps completed research, valid empty responses, configuration setup, and provider availability visible to users and agents.

# Actor input Schema

## `mode` (type: `string`):

Choose the DataForSEO keyword job. keyword\_ideas discovers related phrases; search\_volume measures the supplied phrases. Use keyword\_ideas for research expansion and search\_volume for a known shortlist. This is not a rank-tracking or domain-keyword tool.

## `seedKeywords` (type: `array`):

Provide 1-10 seed phrases, for example \["keyword research"]. Keyword ideas uses them to discover related terms; search volume measures those exact phrases. Blank and duplicate entries are removed. This is not a target domain or Google search operator field.

## `locationCode` (type: `integer`):

DataForSEO Google location code, such as 2840 for the United States. It scopes the returned keyword database metrics. Defaults to 2840 and must be a positive integer. This is not an ISO country string.

## `languageCode` (type: `string`):

DataForSEO language code for the selected location, such as en. It scopes the language of keyword metrics and ideas. Defaults to en. This is not a natural-language name such as English.

## `maxResults` (type: `integer`):

Maximum normalized keyword rows to persist. The Actor caps this at 50 to keep DataForSEO and Apify costs predictable. Defaults to 25. This is not an unbounded provider pagination setting.

## `minSearchVolume` (type: `integer`):

Keep only rows whose provider-reported search volume meets this minimum. Defaults to zero, so rows with a valid zero estimate remain visible. Use it to reduce a keyword-ideas export. This is not a claim of traffic or conversion potential.

## `includeSerpInfo` (type: `boolean`):

Request available SERP feature information for keyword-ideas rows. It defaults to false to keep provider work bounded. It has no effect on search\_volume mode. This is not a live rank-check request.

## `dataforSeoLogin` (type: `string`):

Optional DataForSEO API login used only when the owner secret is unavailable. It is sent only in the HTTP authorization header. Keep it private and never use it in tasks. This is not an Apify token.

## `dataforSeoPassword` (type: `string`):

Optional DataForSEO API password used only when the owner secret is unavailable. It is sent only in the HTTP authorization header. Keep it private and never use it in tasks. This is not your DataForSEO dashboard password.

## Actor input object example

```json
{
  "mode": "keyword_ideas",
  "seedKeywords": [
    "keyword research",
    "content strategy"
  ],
  "locationCode": 2840,
  "languageCode": "en",
  "maxResults": 25,
  "minSearchVolume": 100,
  "includeSerpInfo": false,
  "dataforSeoLogin": "your-private-dataforseo-login",
  "dataforSeoPassword": "your-private-dataforseo-password"
}
```

# Actor output Schema

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

Normalized DataForSEO keyword research rows.

## `output` (type: `string`):

Compact terminal outcome and billing diagnostics.

## `runSummary` (type: `string`):

Detailed provider cost and terminal diagnostics.

# 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 = {
    "seedKeywords": [
        "keyword research"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/dataforseo-keyword-research").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 = { "seedKeywords": ["keyword research"] }

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/dataforseo-keyword-research").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 '{
  "seedKeywords": [
    "keyword research"
  ]
}' |
apify call khadinakbar/dataforseo-keyword-research --silent --output-dataset

```

## MCP server setup

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

```

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/8RW7Ow9S3hRAnX1ye/builds/PP6ZKnxQ7Ag0dUVzk/openapi.json
