# Keyword Research API: Search Volume, CPC, Difficulty, Intent (`gaelasao/keyword-research-api`) Actor

Keyword search volume (Google, plus Bing on 300+ keywords), AI search volume, CPC, difficulty, intent and SERP features in bulk, plus long-tail ideas and keywords of up to 10 competitors. Keyword Planner alternative. $2 per 1,000.

- **URL**: https://apify.com/gaelasao/keyword-research-api.md
- **Developed by:** [Gaël GERARD](https://apify.com/gaelasao) (community)
- **Categories:** SEO tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 1,000 keyword with data

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

Get **keyword search volume** in bulk, with the rest of Google's keyword data in the same row: cost per click (CPC), competition, top-of-page bids, **keyword difficulty**, **search intent**, a **12-month trend**, **AI search volume** and the **SERP features** on Google's first page, plus **Bing search volume** on runs of 300 keywords or more. Paste up to **10,000 keywords per run**, grow a few seeds into up to 5,000 **keyword ideas**, **long-tail suggestions** or **related searches**, or enter up to 10 competitor websites and see **every keyword they rank for**. Works in **every country** Google Ads serves.

A **Google Keyword Planner alternative** built for SEO teams, agencies and AI agents: no Google Ads account, no data-provider account, one flat typed row per keyword and a price you can compute in advance. **$2 per 1,000 keywords with data**, plus $0.01 per run that returns data. Keywords without data are free.

### What does Keyword Research API do?

You send keywords and a country. For each keyword you get:

| Field | What it tells you |
| --- | --- |
| `search_volume` | Average monthly Google searches over the last 12 months |
| `monthly_searches` | Searches for each of the last 12 months, newest first |
| `cpc` | Average cost per click in USD (Google Ads) |
| `competition`, `competition_level` | Paid search competition, from 0 to 1 and as LOW, MEDIUM or HIGH |
| `low_top_of_page_bid`, `high_top_of_page_bid` | Bid range for the top of the results page, in USD |
| `keyword_difficulty` | How hard it is to rank in the organic top 10, from 0 to 100 |
| `search_intent`, `secondary_intents` | Informational, navigational, commercial or transactional |
| `trend` | Change in search volume over the last month, quarter and year, in % |
| `serp_features` | Result types on Google's first page: AI Overview, featured snippet, People Also Ask, local pack, video, shopping and more |
| `serp_url` | The Google search DataForSEO checked, to see the results yourself |
| `core_keyword` | The main form of a group of close variants (plurals, word order), to cluster keywords that share one volume |
| `bing_search_volume`, `bing_cpc`, `bing_competition`, `bing_monthly_searches` | Bing Ads volume, CPC and competition next to Google's, on runs of 300 keywords or more. Included at no extra cost |
| `ai_search_volume`, `ai_monthly_searches` | How often the keyword comes up in AI assistants such as ChatGPT, estimated by DataForSEO from People Also Ask questions: last month, and each of the 12 months before. Included at no extra cost |
| `data_status` | `ok` (every metric the source has), `partial` (Google Ads metrics only) or `no_data` (free row) |

The data comes from [DataForSEO](https://dataforseo.com/): Google Ads keyword data plus the DataForSEO Labs keyword database, which adds difficulty, intent and trend, and DataForSEO's AI keyword data for the AI search volume. A value the source does not have is `null`. It is never replaced by 0.

### Three modes

- **Metrics** (default): one row per keyword you send. Up to 10,000 keywords per run. Duplicates, extra spaces and capital letters are cleaned up first, so the same keyword is never looked up or charged twice.
- **Ideas**: send 1 to 20 seed keywords and get up to 5,000 keywords with the same metrics, with three methods (`ideasMethod`):
  - `ideas` (default): broad ideas from the same topics;
  - `suggestions`: **long-tail phrases that contain your seed**, such as "best running shoes for flat feet";
  - `related`: Google's **related searches**, up to four levels deep.
    Suggestions and related searches run once per seed and say which seed each row came from (`seed_keyword`).
- **Domain (competitor keywords)**: enter one website, or **up to 10** to compare competitors in one run. You get the keywords each ranks for on Google, best traffic first, with its position (`rank_position`), the ranking page (`ranking_url`) and an estimate of the monthly visits each keyword brings (`estimated_traffic`), plus the usual metrics. Keep only positions 4 to 20 to find **striking-distance keywords**. Up to 5,000 keywords per website, same price per row.

In ideas and domain modes, `includeTerms` keeps only keywords that contain a word ("best", "near me"), `excludeTerms` leaves out brand names or "free" before anything is charged, and `sortBy` fetches the highest volume, the highest CPC or the easiest keywords first.

### What can you use it for?

- **Bulk search volume checker**: average monthly Google searches and the last 12 months, for up to 10,000 keywords per run.
- **Keyword difficulty checker**: how hard each keyword is to rank for in the organic top 10, from 0 to 100.
- **Search intent checker**: informational, navigational, commercial or transactional.
- **CPC checker**: cost per click, paid competition and the top-of-page bid range from Google Ads.
- **Keyword ideas and long-tail keywords**: up to 5,000 related keywords from 1 to 20 seeds, filtered by minimum volume.
- **Competitor keyword research**: the keywords any website or page ranks for, with position, ranking URL and estimated traffic.
- **AI search volume checker**: how often each keyword comes up in AI assistants, with its 12-month history.
- **Google vs Bing**: Bing searches and CPC next to Google's, on runs of 300 keywords or more.
- **SERP features checker**: which keywords show an AI Overview, a featured snippet, People Also Ask or a local pack.
- **Long-tail keyword suggestions**: phrases that contain your seed, with volume, CPC and difficulty, easiest first if you like.
- **Striking distance keywords**: the keywords your site ranks for in positions 4 to 20, the quickest wins.
- **Competitor comparison**: the keywords of up to 10 websites in one run, each row tagged with its website.
- **Keyword data for AI agents**: call it as an MCP tool or through the API and get the same typed rows.

### How to use it

1. Paste your keywords, one per line. Google Ads match-type notation such as `"phrase"` or `[exact]` is removed.
2. Pick a country. The language defaults to the country's main language, for example German for Switzerland; change it if you need French or Italian.
3. Optional: set a minimum search volume or a maximum number of keywords.
4. Set a **maximum cost per run** that covers your list (see the price table below), then start.
5. Open the **Output** tab: the *Keyword metrics* view, a *Google Ads bids and competition* view and a *12-month history* view. Export JSON, CSV or Excel, or use the *Main columns for spreadsheets (CSV)* link, which leaves out the monthly columns.

### Input examples

Metrics for your own list:

```json
{
  "keywords": ["running shoes", "trail running shoes", "best running shoes for flat feet"],
  "location": "US"
}
```

Keyword ideas from a seed, only ideas with at least 100 searches a month:

```json
{
  "mode": "ideas",
  "keywords": ["running shoes"],
  "location": "GB",
  "maxIdeas": 500,
  "minSearchVolume": 100
}
```

Keywords a competitor ranks for in the US, best traffic first:

```json
{
  "mode": "domain",
  "domain": "competitor.com",
  "location": "US",
  "maxIdeas": 1000
}
```

Long-tail suggestions that contain the seed, without brand names, easiest first:

```json
{
  "mode": "ideas",
  "ideasMethod": "suggestions",
  "keywords": ["coffee grinder"],
  "excludeTerms": ["baratza", "breville"],
  "sortBy": "difficulty",
  "maxIdeas": 200
}
```

Striking-distance keywords of two competitors (positions 4 to 20):

```json
{
  "mode": "domain",
  "domains": ["competitor.com", "other-competitor.com"],
  "minPosition": 4,
  "maxPosition": 20,
  "maxIdeas": 500
}
```

Another language in the same country:

```json
{
  "keywords": ["chaussures de course", "logiciel de facturation"],
  "location": "CA",
  "language": "fr"
}
```

`location` accepts an ISO country code (`US`, `GB`), a country name in English or French (`United Kingdom`, `Royaume-Uni`) or a numeric DataForSEO `location_code` (`2840`). **Every country works.** The 94 countries in the drop-down list get every metric and all three modes. The other countries, and location codes such as a city, return Google Ads metrics: search volume, CPC, competition and bids, without difficulty, intent or trend, in metrics mode.

### Output example

What a row looks like, with illustrative values (the 12 monthly values are shortened here):

```json
{
  "keyword": "running shoes",
  "location_code": 2840,
  "language_code": "en",
  "search_volume": 246000,
  "monthly_searches": [
    { "year": 2026, "month": 9, "search_volume": 201000 },
    { "year": 2026, "month": 8, "search_volume": 246000 }
  ],
  "cpc": 1.12,
  "competition": 1,
  "competition_level": "HIGH",
  "low_top_of_page_bid": 0.58,
  "high_top_of_page_bid": 1.71,
  "keyword_difficulty": 79,
  "search_intent": "commercial",
  "secondary_intents": ["transactional"],
  "trend": { "monthly": -18, "quarterly": -18, "yearly": 0 },
  "data_status": "ok",
  "source_endpoint": "dataforseo_labs/google/keyword_overview/live",
  "retrieved_at": "2026-10-18T09:00:00.000Z"
}
```

Every run also writes a `SUMMARY` record (linked in the Output tab). It shows how many keywords were received, cleaned up, looked up and delivered, each batch with its attempts, any limit that stopped the run, and what was charged.

### How much does it cost?

This Actor uses pay-per-event pricing. Platform usage is included.

| Event | Price |
| --- | --- |
| Keyword with data (`keyword-result`) | $0.002 per keyword |
| Run start (`run-start`), charged only when the run returns at least one keyword with data | $0.01 per run |

| Keywords with data | Total price |
| --- | --- |
| 100 | $0.21 |
| 1,000 | $2.01 |
| 10,000 | $20.01 |

You are **never charged** for:

- keywords the source has no data for (rows with `data_status: "no_data"`);
- keywords left out by `minSearchVolume` or `maxKeywords`, or listed as duplicates;
- keywords in a batch that failed;
- a run that returns nothing.

**Maximum cost per run.** Set it in the run options (or with `maxTotalChargeUsd` in the API). The Actor only requests data it can bill within that limit, and keywords that turn out to have no data free their share of the budget for the rest of your list. When the limit is reached, it stops cleanly, keeps every row already delivered and tells you how many keywords are left, for example: *"Stopped at your $1.00 maximum cost per run: 495 keywords with data. Raise it to $2.01 to get the other 505."* For 1,000 keywords, a limit of $2.01 is enough.

**Apify free plan.** Runs started from a free Apify account are limited to 20 keywords (or 20 ideas), enough to try the Actor. Paid Apify plans process up to 10,000 keywords per run.

### How does it compare?

Popular keyword Actors in Apify Store charge up to $12 per 1,000 keywords, and many leave out keyword difficulty or search intent. This one:

- costs $2 per 1,000 keywords with data, and keywords without data are free;
- takes up to 10,000 keywords in one run;
- puts volume, CPC, bids, difficulty, intent and the 12-month trend in the same row, for every keyword in the 94 countries with full data;
- adds keyword ideas, long-tail suggestions, related searches and the keywords of up to 10 competitor websites at the same price per row;
- includes AI search volume and SERP features at no extra cost, and Bing search volume on runs of 300+ keywords;
- filters by words, position and minimum volume at the source, so keywords left out are never charged.

What it does not do: SERP results, backlinks or clickstream-adjusted volumes. It is also new, so its public track record is short. The `SUMMARY` record shows exactly what happened in each run.

### Reliable by design

- Keywords are sent in batches of up to 700, three batches at a time.
- Each request is retried up to 3 times, with growing waits, on rate limits, timeouts and server errors.
- If the DataForSEO Labs request fails for a batch, the Actor asks Google Ads for the same keywords. You still get volume, CPC, competition and bids; difficulty, intent and trend stay `null` and the row says `data_status: "partial"`.
- A failed batch does not stop the others, and results already delivered are kept. The run is marked as failed only if nothing could be delivered, and then nothing is charged.
- The Actor stops starting new batches shortly before the run timeout, leaving time to write the summary and a clear status message.
- If the platform restarts the run, keywords already delivered are skipped and not charged again.

### Use it from your code

Run it and get the rows in one request with the [run-sync-get-dataset-items](https://docs.apify.com/api/v2/actor-run-sync-get-dataset-items-post) endpoint:

```bash
curl -X POST "https://api.apify.com/v2/acts/gaelasao~keyword-research-api/run-sync-get-dataset-items?maxTotalChargeUsd=2.01" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords": ["running shoes", "trail running shoes"], "location": "US"}'
```

With the JavaScript client:

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('gaelasao/keyword-research-api').call(
  { keywords: ['running shoes', 'trail running shoes'], location: 'GB' },
  { maxTotalChargeUsd: 2.01 },
);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

For long lists, start the run asynchronously and read the dataset when it finishes; the synchronous endpoint waits up to 5 minutes.

### Use it from an AI agent (MCP)

Apify hosts this Actor as a tool on its [MCP server](https://docs.apify.com/mcp). In an MCP client such as Claude, Cursor or VS Code, add:

```text
https://mcp.apify.com?tools=actors,docs,gaelasao/keyword-research-api
```

Then ask, for example: *"Get search volume, CPC, difficulty and intent for these 40 keywords in Germany and sort them by volume."* or *"Which keywords bring competitor.com the most traffic in the UK? Show the top 50 with their ranking pages."* The agent sends the same JSON input as above. The output is the same flat rows, and the price per keyword is fixed, so an agent can estimate the cost before it runs.

### FAQ

#### Where does the data come from?

From DataForSEO, a licensed SEO data provider. Search volume, CPC, competition and bids are Google Ads keyword data. Keyword difficulty, search intent and trend come from the DataForSEO Labs database, and AI search volume from DataForSEO's AI keyword data. `source_endpoint` on each row says which one answered.

#### How fresh is it?

Google publishes keyword volumes as monthly averages, and DataForSEO refreshes its database every month. The newest month appears a few days after it ends; the current month is never included. `retrieved_at` shows when the Actor fetched the data, not when Google updated it.

#### Why is there no data for some keywords?

Very rare or very new keywords are often missing from the Google Ads and DataForSEO databases. Those keywords come back with `data_status: "no_data"` and `null` metrics, and they are free.

#### Why do similar keywords have the same volume?

Google Ads groups close variants, such as plurals or reordered words, and reports the same volume for the group. This is how Google provides the data.

#### Which countries and languages are supported?

Every country Google Ads serves: use a two-letter code (`US`, `GB`, `DE`) or the country name in English or French. 94 countries get every metric and all three modes, each in its supported languages (for example English and Spanish for the US, Dutch, French and German for Belgium). The other countries get Google Ads metrics (volume, CPC, competition and bids) in metrics mode. Regions and cities work with a numeric DataForSEO `location_code`. DataForSEO does not serve Russia or Belarus.

#### What are the limits?

- Metrics mode: 1 to 10,000 keywords per run. Ideas mode: 1 to 20 seeds and up to 5,000 ideas. Domain mode: one website or page and up to 5,000 ranked keywords.
- Each keyword can have up to 80 characters and 10 words. Longer ones are listed in `SUMMARY` and skipped.
- Google Ads rejects some characters (`, ! @ % ^ * ( ) = { } ; ~ < > ? \ |` and emojis). Keywords containing them can still get full metrics from DataForSEO Labs, but they are left out of the Google Ads fallback and listed in `SUMMARY`.

#### When do I get Bing search volume?

On runs of **300 keywords or more** (in ideas and domain modes, when you ask for 300 rows or more), in English, French or German, in the countries Bing Ads covers. It costs nothing extra: Bing charges per request whatever the size, so it is added where the run is large enough to pay for it. Batches with fewer than 50 keywords with data, such as a small leftover batch, skip it. Rows then get `null`, and runs below 300 keywords have no Bing columns. Turn it off with `"includeBing": false`.

#### What are SERP features?

The kinds of results Google shows on the first page for a keyword: classic organic links, but also an AI Overview, a featured snippet, People Also Ask questions, a local pack, videos, images or shopping results. They tell you what it takes to be seen: a keyword with an AI Overview and a featured snippet leaves fewer clicks to the organic results. `serp_features` lists them for each keyword with full metrics, at no extra cost. Turn it off with `"includeSerpInfo": false`.

#### What is AI search volume?

An estimate, by DataForSEO, of how often a keyword comes up in AI assistants such as ChatGPT, built from the questions in Google's People Also Ask boxes. You get last month's value in `ai_search_volume` and the 12 months before in `ai_monthly_searches` (when `includeTrend` is on). It is on by default, costs nothing extra, and is `null` where DataForSEO has no AI data, for example for some countries or languages. Turn it off with `"includeAiVolume": false`.

#### Is it a Google Keyword Planner alternative?

Yes. You get the same Google Ads keyword metrics (search volume, CPC, competition and bid range) without a Google Ads account or ad spend, plus keyword difficulty, search intent and trend from DataForSEO Labs, for thousands of keywords at once.

#### Do I need a DataForSEO or Google Ads account?

No. You only need an Apify account. Charges come out of your Apify balance.

#### Can I track the same keywords every month?

Yes. Save your input as a task and add an Apify schedule. Each run is charged like any other run.

# Changelog

This Actor's version history is a separate document: https://apify.com/gaelasao/keyword-research-api/changelog.md

# Actor input Schema

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

Metrics mode: 1 to 10,000 keywords, one per line. Duplicates and extra spaces are removed and keywords are lowercased. Each keyword can have up to 80 characters and 10 words. Ideas mode: 1 to 20 seed keywords. Domain mode: not used.

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

Metrics returns one row per keyword you provide. Ideas returns related keywords for your seed keywords. Domain returns the keywords a website ranks for on Google, with its position, ranking URL and estimated traffic.

## `ideasMethod` (type: `string`):

Ideas: broad keyword ideas from the same topics. Suggestions: long-tail phrases that contain your seed. Related: Google's related searches, up to 4 levels deep. Suggestions and related run once per seed.

## `domain` (type: `string`):

Domain mode only: a website such as "example.com", or one page URL. Returns the keywords it ranks for in the chosen country, best traffic first.

## `domains` (type: `array`):

Domain mode only: up to 10 websites in total with "domain", to compare competitors in one run. Maximum rows applies to each website.

## `location` (type: `string`):

Pick a country, or type an ISO code (US), a country name (United Kingdom) or a DataForSEO location_code (2840). The 94 listed countries have every metric. Other location codes, such as cities, return Google Ads metrics only (no difficulty, intent or trend) and do not support ideas mode.

## `language` (type: `string`):

Leave empty to use the main language of the country (for example English for the US, German for Switzerland). A language the country does not support in DataForSEO Labs returns Google Ads metrics only.

## `includeTrend` (type: `boolean`):

Adds monthly search volumes for the last 12 months and the monthly, quarterly and yearly trend (%) to each row. Turn off for smaller exports. The price is the same.

## `includeAiVolume` (type: `boolean`):

Adds ai_search_volume to each row with data: an estimate of how often the keyword comes up in AI assistants such as ChatGPT (DataForSEO AI keyword data), with its 12-month history when the history option is on. Included at no extra cost. Null where DataForSEO has no AI data.

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

Adds serp_features (AI Overview, featured snippet, People Also Ask, local pack, video, shopping and more) and serp_url to each row with full metrics. Included at no extra cost.

## `includeBing` (type: `boolean`):

On runs of 300 keywords or more, adds bing_search_volume, bing_cpc and bing_competition from Bing Ads to each row with data, at no extra cost. English, French and German, in the countries Bing covers. Smaller runs skip it.

## `maxIdeas` (type: `integer`):

Ideas mode: rows to return, up to 5,000 (per seed with the suggestions and related methods). Domain mode: rows per website. You pay only for the rows delivered.

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

Only return keywords with at least this average monthly search volume. Keywords below it, or without volume data, are left out and not charged. 0 keeps everything.

## `maxKeywords` (type: `integer`):

Optional cap on billed rows. Metrics mode looks up only the first N unique keywords; the rest are listed in SUMMARY. Your maximum cost per run still applies.

## `includeTerms` (type: `array`):

Up to 3 words or phrases. Only keywords that contain at least one of them are returned, for example "best" or "near me".

## `excludeTerms` (type: `array`):

Up to 3 words or phrases, such as brand names or "free". Keywords that contain any of them are left out and not charged.

## `minPosition` (type: `integer`):

Domain mode: only keywords where the website ranks at this position or lower. Use 4 with a maximum of 20 for striking-distance keywords.

## `maxPosition` (type: `integer`):

Domain mode: only keywords where the website ranks at this position or better, for example 10 for its page-1 keywords.

## `sortBy` (type: `string`):

Order in which ideas and domain rows are fetched. Default: search volume for ideas, estimated traffic for domain mode. Easiest first sorts by keyword difficulty, lowest first. Traffic and position work in domain mode only.

## Actor input object example

```json
{
  "keywords": [
    "keyword research",
    "seo tools",
    "running shoes",
    "project management software",
    "coffee grinder"
  ],
  "mode": "metrics",
  "ideasMethod": "ideas",
  "location": "US",
  "includeTrend": true,
  "includeAiVolume": true,
  "includeSerpInfo": true,
  "includeBing": true,
  "maxIdeas": 100,
  "minSearchVolume": 0
}
```

# Actor output Schema

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

No description

## `csv` (type: `string`):

No description

## `summary` (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 = {
    "keywords": [
        "keyword research",
        "seo tools",
        "running shoes",
        "project management software",
        "coffee grinder"
    ],
    "mode": "metrics",
    "location": "US"
};

// Run the Actor and wait for it to finish
const run = await client.actor("gaelasao/keyword-research-api").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": [
        "keyword research",
        "seo tools",
        "running shoes",
        "project management software",
        "coffee grinder",
    ],
    "mode": "metrics",
    "location": "US",
}

# Run the Actor and wait for it to finish
run = client.actor("gaelasao/keyword-research-api").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": [
    "keyword research",
    "seo tools",
    "running shoes",
    "project management software",
    "coffee grinder"
  ],
  "mode": "metrics",
  "location": "US"
}' |
apify call gaelasao/keyword-research-api --silent --output-dataset

```

## MCP server setup

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

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/nrNuSpDN2FYCovuBS/builds/RycyvR7qYcuUAtQPy/openapi.json
