# Google SERP and Keyword Research API - DataForSEO (`nabeelbaghoor/google-serp-keyword-research-api`) Actor

Google SERP API and keyword research with DataForSEO: live organic rankings, Google Ads search volume, CPC and competition, keyword ideas with difficulty and intent, keywords any domain ranks for, and backlink summaries. Export to JSON, CSV or Excel. Bring your own key.

- **URL**: https://apify.com/nabeelbaghoor/google-serp-keyword-research-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** SEO tools, Marketing, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 serp result returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Google SERP and Keyword Research API - DataForSEO

Pull live Google rankings, keyword search volume, keyword ideas, the keywords any domain ranks for, and backlink summaries with your own DataForSEO API login, straight into an Apify dataset.

Works with the DataForSEO v3 API (api.dataforseo.com): the SERP API, the Keywords Data API (Google Ads), DataForSEO Labs and the Backlinks API. The actor turns a list of keywords or domains into clean, deduplicated rows you can download as JSON, CSV or Excel, schedule for rank tracking, or feed into SEO dashboards, content planning, PPC research, Looker Studio, Google Sheets and AI agents. Bring your own API key.

BYOK, not live-tested: every route, field and enum comes from DataForSEO's published API reference (docs.dataforseo.com), and each route was confirmed to exist with a deliberately invalid login, but the actor has not been run against a funded DataForSEO account.

### What it does

- **Google organic SERP (rank tracking)**: a live Google search for each keyword, by location, language, device and operating system, up to 200 results deep. Each result is a row with its position (rank group and absolute rank), domain, URL, title and snippet. Untick organic only to also keep ads, featured snippets, people also ask, local packs, AI overviews and other SERP features.
- **Google Ads search volume**: monthly search volume, CPC, competition level and index, top of page bids and up to four years of monthly searches for up to 1000 keywords per call.
- **Keyword ideas (DataForSEO Labs)**: related keywords for up to 200 seed keywords, with search volume, CPC, competition, keyword difficulty, search intent and search volume trend, filtered by minimum volume and sorted by relevance, volume, CPC or competition.
- **Ranked keywords (DataForSEO Labs)**: every keyword a domain, subdomain or page ranks for in Google organic and paid results, with its position, ranking URL, estimated traffic (ETV), search volume, CPC, keyword difficulty and intent. Filter by maximum position and minimum volume; read current or lost rankings.
- **Backlinks summary**: backlink rank, backlinks, referring domains, main domains, IPs and subnets, spam score, broken backlinks and pages, and link type, attribute, TLD and country breakdowns for each domain or page.
- **Cost aware**: the actor stops calling DataForSEO once your maximum results is reached, paces Google Ads calls to the 12 a minute the API allows, and logs the cost DataForSEO reports for the run.
- **Pay only for results**: refused and empty requests are recorded as a free row that says why, never charged.

### How to get an API key

Create a DataForSEO account at app.dataforseo.com and open the API Access page (app.dataforseo.com/api-access). It shows your API login (your email) and an API password that DataForSEO generates, which is not your account password. Paste them into the API login and API password fields, or set the `DATA_API_KEY` environment secret to `login:password` (or `DATA_API_KEY` and `DATA_API_SECRET` separately). The Backlinks API needs its own subscription with a minimum monthly commitment; the other modes run on the pay-as-you-go balance. This actor never ships a shared key.

### Input

| Field | Used by | What it does |
| --- | --- | --- |
| `mode` | all | `serpOrganic`, `searchVolume`, `keywordIdeas`, `rankedKeywords` or `backlinksSummary` |
| `keywords` | SERP, search volume, keyword ideas | One keyword per line |
| `targets` | ranked keywords, backlinks | Domains (example.com) or full page URLs, one per line |
| `locationCode`, `locationName` | all but backlinks | DataForSEO location, for example 2840 for the United States (required for SERP and keyword ideas) |
| `languageCode` | all but backlinks | Language code such as en, de or fr |
| `device`, `os`, `depth`, `seDomain` | SERP | Desktop or mobile, operating system, results per keyword (up to 200), Google domain |
| `organicOnly` | SERP | Keep only organic results (default) or every SERP element |
| `searchPartners`, `dateFrom`, `dateTo`, `volumeSortBy` | search volume | Search partner network, monthly history range, sort order |
| `closelyVariants`, `includeSerpInfo`, `ideaSortBy` | keyword ideas | Phrase match, SERP data per idea, sort order |
| `ignoreSynonyms`, `minSearchVolume` | keyword ideas, ranked keywords | Drop close variants, minimum monthly volume |
| `rankedItemTypes`, `historicalSerpMode`, `maxRank`, `rankedSortBy` | ranked keywords | Result types, current or lost rankings, best position cut-off, sort order |
| `includeSubdomains`, `includeIndirectLinks`, `excludeInternalBacklinks`, `backlinksStatusType`, `rankScale` | backlinks | Backlink counting options |
| `maxResults` | all | Row ceiling for the run, which also stops further API calls (default 100) |
| `requestsPerMinute` | all | Pacing (default 600; DataForSEO allows 2000 a minute) |
| `apiKey`, `apiSecret` | all | Your DataForSEO API login and API password, stored as secrets |

Each route only receives the fields its documentation lists; an input that belongs to another mode is left off with a warning.

Example input, the top 20 US desktop results for two keywords:

```json
{
    "mode": "serpOrganic",
    "keywords": ["best running shoes", "running shoes for flat feet"],
    "locationCode": 2840,
    "languageCode": "en",
    "device": "desktop",
    "depth": 20,
    "maxResults": 40
}
```

Example input, the page-one keywords a competitor ranks for in the UK:

```json
{
    "mode": "rankedKeywords",
    "targets": ["example.com"],
    "locationCode": 2826,
    "languageCode": "en",
    "maxRank": 10,
    "rankedSortBy": "keyword_data.keyword_info.search_volume,desc",
    "maxResults": 200
}
```

### Example output

A SERP row, abridged. The common columns come first; every field DataForSEO returns for the element follows unchanged.

```json
{
    "mode": "serpOrganic",
    "recordType": "serpItem",
    "identifier": "best running shoes",
    "found": true,
    "keyword": "best running shoes",
    "itemType": "organic",
    "rank": 1,
    "rankAbsolute": 2,
    "domain": "www.example.com",
    "url": "https://www.example.com/best-running-shoes",
    "title": "The Best Running Shoes of 2026, Tested",
    "description": "We ran hundreds of miles to find the best running shoes for every runner...",
    "seResultsCount": 512000000,
    "checkUrl": "https://www.google.com/search?q=best%20running%20shoes&hl=en&gl=US",
    "checkedAt": "2026-10-13 09:12:44 +00:00",
    "locationCode": 2840,
    "languageCode": "en",
    "note": null,
    "type": "organic",
    "rank_group": 1,
    "rank_absolute": 2,
    "position": "left",
    "breadcrumb": "https://www.example.com > reviews",
    "is_featured_snippet": false
}
```

A keyword idea row carries `keyword`, `searchVolume`, `cpc`, `competition`, `keywordDifficulty` and `searchIntent`, followed by the full `keyword_info` (with `monthly_searches` and `search_volume_trend`), `keyword_properties`, `search_intent_info` and `avg_backlinks_info`. A ranked keyword row adds `rank`, `url`, `title` and `etv` from the ranking element, with `keyword_data` and `ranked_serp_element` kept whole. A backlinks row carries `backlinkRank`, `backlinks`, `referringDomains`, `referringMainDomains`, `spamScore`, `brokenBacklinks` and `firstSeen`, then every summary field.

### FAQ

#### What is DataForSEO?

DataForSEO is an SEO data provider whose APIs power many rank trackers and keyword tools. Its v3 API offers live Google SERP data, Google Ads keyword data, the DataForSEO Labs keyword and ranking database, and a backlink index, all paid per request from a prepaid balance.

#### Do I need my own DataForSEO account?

Yes. The actor calls DataForSEO with your own API login and API password, and DataForSEO charges those calls to your balance. A run without credentials ends straight away with a message that says where to find them, and nothing is charged.

#### How do I track Google rankings for my keywords?

Use the Google organic SERP mode with your keywords, a location code and a language code, and schedule the actor daily or weekly. Each organic result is a row with its position, URL and domain, so you can filter for your own domain or compare competitors.

#### How do I get Google search volume for a keyword list?

Use the Google Ads search volume mode and paste up to 1000 keywords per call (the actor batches longer lists). Each keyword comes back with monthly search volume, CPC, competition and monthly history.

#### How do I find which keywords a competitor ranks for?

Use the ranked keywords mode with the competitor's domain. Set a maximum position of 10 for page one only, and sort by search volume to see their most valuable rankings with estimated traffic.

#### How much does DataForSEO charge per call?

DataForSEO bills your balance per request at the rates on its pricing pages (dataforseo.com/pricing): a SERP is billed per 10 results of depth, a Google Ads search volume call costs the same for 1 or 1000 keywords, and DataForSEO Labs calls are billed per request plus per returned item. The actor logs the exact cost DataForSEO reports for each run, and the maximum results cap stops further calls once reached.

#### What do I pay for this actor?

Pay per result: 0.005 USD per SERP result row, 0.01 USD per keyword row (search volume, keyword idea or ranked keyword), and 0.02 USD per backlink summary. Refused and empty requests are never charged. Your DataForSEO usage is billed separately by DataForSEO.

#### What happens if my login is wrong or my balance runs out?

A rejected login or password (HTTP 401), an empty balance (status 40200 or 40210), a reached daily cost limit (40203), an API not on your subscription (40204, typical for Backlinks), an unverified or paused account, or an IP whitelist ends the run cleanly with a status message that says what to change. Rate limits are waited out and retried. A keyword or target DataForSEO refuses becomes a free row with the API's own words, and the run moves on.

### Pricing

| Event | Price | Charged for |
| --- | --- | --- |
| `serp-result` | 0.005 USD | Each Google SERP result row |
| `keyword-record` | 0.01 USD | Each search volume, keyword idea or ranked keyword row |
| `backlink-summary` | 0.02 USD | Each domain or page backlink summary |

### Keyword map

Google SERP API, rank tracker API, keyword research API, Google search volume API, keyword search volume, CPC and competition, Google Ads keyword planner data, keyword ideas, keyword difficulty, search intent, competitor keywords, ranked keywords, domain organic keywords, estimated traffic, backlink checker API, referring domains, domain rank, SEO API, DataForSEO API, DataForSEO Labs.

### Terms and data use

Use of the DataForSEO API is governed by your DataForSEO account and its terms of service. The data-use restriction they state is on SERP data: data obtained from Google and other search engines must not be used to compete with or adversely affect the business interests of those search engines, and you indemnify DataForSEO for any such use. The Backlinks API is sold separately with a minimum commitment. Run this actor with your own login and keep within those terms. This actor is not affiliated with or endorsed by DataForSEO.

# Actor input Schema

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

Google organic SERP runs a live Google search for each keyword and returns every ranking result. Google Ads search volume returns monthly search volume, CPC, competition and 12 months of history for up to 1000 keywords per call. Keyword ideas suggests related keywords with volume, CPC, difficulty and intent from the DataForSEO Labs database. Ranked keywords lists the keywords a domain or page ranks for in Google, with position and estimated traffic. Backlinks summary returns backlink and referring domain counts for each domain or page.

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

SERP, search volume and keyword ideas modes. One keyword per line. SERP: each keyword is one live search (up to 700 characters). Search volume: up to 1000 keywords per call, each up to 80 characters and 10 words. Keyword ideas: up to 200 seed keywords in one request.

## `targets` (type: `array`):

Ranked keywords and backlinks summary modes. One per line: a domain such as example.com (without https:// or www.), a subdomain, or a full page URL such as https://example.com/blog/post. Each target is one request.

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

DataForSEO location code, for example 2840 United States, 2826 United Kingdom, 2276 Germany, 2124 Canada, 2036 Australia, 2356 India. Required for SERP and keyword ideas (or give a location name); optional for search volume and ranked keywords. Not used by backlinks summary.

## `locationName` (type: `string`):

Used only when the location code is empty. A DataForSEO location name such as United States or London,England,United Kingdom.

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

Search engine language code such as en, de, fr, es or zh-TW. Optional; leave empty to let DataForSEO pick the main language of the location.

## `device` (type: `string`):

SERP mode only. Desktop or mobile Google results.

## `os` (type: `string`):

SERP mode only. Windows or macOS for desktop, Android or iOS for mobile.

## `depth` (type: `integer`):

SERP mode only. How many results to read for each keyword, up to 200. DataForSEO bills each 10 results as one SERP page, so 100 costs about ten times as much as 10.

## `seDomain` (type: `string`):

SERP mode only. Optional Google domain such as google.co.uk or google.de. DataForSEO picks one from the location when empty.

## `organicOnly` (type: `boolean`):

SERP mode only. Keep only organic results. Untick to also get ads, featured snippets, people also ask, local packs, AI overviews and every other SERP element as rows.

## `searchPartners` (type: `boolean`):

Search volume mode only. Include Google search partner sites in the volume.

## `dateFrom` (type: `string`):

Search volume mode only. Start of the monthly history (YYYY-MM-DD, up to 4 years back). Default is the past 12 months.

## `dateTo` (type: `string`):

Search volume mode only. End of the monthly history (YYYY-MM-DD). Google Ads has no data for the current month.

## `volumeSortBy` (type: `string`):

Search volume mode only. Sort order of the results, descending.

## `closelyVariants` (type: `boolean`):

Keyword ideas only. Phrase-match search instead of broad match.

## `ignoreSynonyms` (type: `boolean`):

Keyword ideas and ranked keywords. Return only core keywords and drop highly similar variants.

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

Keyword ideas only. Add SERP data (result count, SERP features, check URL) to each keyword idea.

## `ideaSortBy` (type: `string`):

Keyword ideas only. How ideas are sorted before the result limit applies.

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

Keyword ideas and ranked keywords. Only keywords with at least this monthly search volume.

## `rankedItemTypes` (type: `array`):

Ranked keywords only. Which SERP result types to include. Empty means organic and paid, the provider default.

## `historicalSerpMode` (type: `string`):

Ranked keywords only. Current rankings, rankings lost since the last check, or both.

## `maxRank` (type: `integer`):

Ranked keywords only. Only keywords where the target ranks at this position or better, for example 10 for page one.

## `rankedSortBy` (type: `string`):

Ranked keywords only. How keywords are sorted before the result limit applies.

## `includeSubdomains` (type: `boolean`):

Backlinks summary only. Count backlinks to subdomains of the target too.

## `includeIndirectLinks` (type: `boolean`):

Backlinks summary only. Count links to pages that redirect to the target or name it as canonical.

## `excludeInternalBacklinks` (type: `boolean`):

Backlinks summary only. Leave out links from other subdomains of the same domain.

## `backlinksStatusType` (type: `string`):

Backlinks summary only. Count live backlinks, lost backlinks, or all.

## `rankScale` (type: `string`):

Backlinks summary only. Scale of the backlink rank value.

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

The most rows this run returns and charges for. It also stops further DataForSEO calls once reached, which keeps your DataForSEO spend in check.

## `requestsPerMinute` (type: `integer`):

Pacing. DataForSEO allows 2000 calls a minute and 30 at once; Google Ads search volume is limited to 12 a minute and is always paced to that.

## `apiKey` (type: `string`):

Your DataForSEO API login (the email shown on app.dataforseo.com/api-access). Stored as a secret and sent only in the HTTP Basic Authorization header. You can instead set the DATA_API_KEY environment secret to login:password.

## `apiSecret` (type: `string`):

Your DataForSEO API password from app.dataforseo.com/api-access. It is generated by DataForSEO and is not your account password. You can instead set the DATA_API_SECRET environment secret.

## Actor input object example

```json
{
  "mode": "serpOrganic",
  "keywords": [
    "best running shoes",
    "running shoes for flat feet"
  ],
  "locationCode": 2840,
  "languageCode": "en",
  "device": "desktop",
  "os": "default",
  "depth": 10,
  "organicOnly": true,
  "searchPartners": false,
  "volumeSortBy": "relevance",
  "closelyVariants": false,
  "ignoreSynonyms": false,
  "includeSerpInfo": false,
  "ideaSortBy": "relevance,desc",
  "historicalSerpMode": "live",
  "rankedSortBy": "ranked_serp_element.serp_item.rank_group,asc",
  "includeSubdomains": true,
  "includeIndirectLinks": true,
  "excludeInternalBacklinks": true,
  "backlinksStatusType": "live",
  "rankScale": "one_thousand",
  "maxResults": 100,
  "requestsPerMinute": 600
}
```

# Actor output Schema

## `records` (type: `string`):

One row per SERP element, keyword or backlink summary.

# 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": [
        "best running shoes",
        "running shoes for flat feet"
    ],
    "locationCode": 2840,
    "languageCode": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/google-serp-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": [
        "best running shoes",
        "running shoes for flat feet",
    ],
    "locationCode": 2840,
    "languageCode": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/google-serp-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": [
    "best running shoes",
    "running shoes for flat feet"
  ],
  "locationCode": 2840,
  "languageCode": "en"
}' |
apify call nabeelbaghoor/google-serp-keyword-research-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/google-serp-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/G1eFB7CGuG9Nvo8PV/builds/sh8Q24L7of46iZnH9/openapi.json
