# Keyword Difficulty Checker (`groupoject/keyword-difficulty-checker`) Actor

Estimate SEO keyword difficulty in bulk from live Google SERP signals. Find low-competition keywords, easy-win topics, and SERP risks before writing.

- **URL**: https://apify.com/groupoject/keyword-difficulty-checker.md
- **Developed by:** [Group Oject](https://apify.com/groupoject) (community)
- **Categories:** SEO tools, E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 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.

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 Difficulty Checker

**Estimate SEO keyword difficulty in bulk from live Google SERP signals — and surface your easiest ranking opportunities first.**

Drop in a list of keywords and get back a 0–100 difficulty score for each, based on what's *actually* ranking on Google right now: how many high-authority sites hold the top 10, how optimized their titles are, how many ads and SERP features crowd the page, and how concentrated the domains are.

> 🔑 **Setup in 60 seconds:** get a free [SerpApi key](https://serpapi.com/users/sign_up) (100 SERP lookups/month free), paste it into `serpApiKey`, add keywords, and run.

***

### What it does

For each keyword, the Actor pulls the live Google SERP (via SerpApi) and computes a transparent difficulty estimate from observable signals:

| Signal | What it measures |
|---|---|
| **Authority** | Share of the top 10 held by high-authority domains (Wikipedia, Amazon, Forbes, `.gov`/`.edu`, …) |
| **Title optimization** | Share of top-10 titles containing your exact keyword |
| **SERP features** | Featured snippet + People-Also-Ask boxes that push organic results down |
| **Ads** | Number of paid results (commercial competition) |
| **Domain concentration** | How few unique domains control the top 10 |

These combine into a **0–100 difficulty score** and a plain-English rating (`very easy` → `very hard`) with a recommended action.

***

### Why it's honest

This is a **SERP-based estimate**, not a backlink-based metric like Ahrefs/SEMrush KD. It answers *"how contested and well-optimized is this SERP?"* — which is exactly what you can observe without proprietary link data. Every weight is in plain code in [`src/difficulty.ts`](src/difficulty.ts):

```
difficulty = authority*0.35 + titleOptimization*0.25 + serpFeatures*0.15
           + ads*0.15 + domainConcentration*0.10   (clamped 0–100)
```

No black box. Tune the weights to your niche if you want.

***

### Who it's for

- **Content & SEO teams** — prioritize the keywords you can actually rank for.
- **Bloggers & affiliates** — find low-competition "easy win" topics.
- **Agencies** — bulk-qualify a client's keyword list before committing hours.
- **PPC marketers** — gauge commercial competition (ad density) per term.

***

### Popular SEO use cases

- **Easy-win keyword finder** - sort large keyword lists by low difficulty and clear recommended action.
- **Affiliate keyword qualification** - check buyer-intent keywords before writing reviews or comparison pages.
- **SaaS content prioritization** - compare solution, alternative, and "best software" SERPs.
- **Local SEO difficulty checks** - estimate competition for city + service keywords.
- **eCommerce category planning** - score product, category, and modifier keywords before building pages.
- **Agency keyword audits** - turn client keyword exports into a transparent opportunity report.

***

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `keywords` | string\[] | — | Keywords to check |
| `keywordsText` | string | — | Keywords as text (one per line / comma-separated) |
| `serpApiKey` | string (secret) | — | **Required.** Free key from [serpapi.com](https://serpapi.com) |
| `geo` | string | `"US"` | Google country code |
| `language` | string | `"en"` | Language code |
| `maxKeywords` | integer | `100` | Max keywords to process |
| `requestDelayMs` | integer | `500` | Delay between lookups |
| `maxConcurrency` | integer | `3` | Parallel lookups |

One SERP lookup is consumed per keyword.

#### Example input

```json
{
  "keywords": ["best coffee maker", "ai seo tools", "how to start a blog"],
  "geo": "US",
  "language": "en",
  "serpApiKey": "@SERPAPI_KEY"
}
```

More in [`examples/`](examples/).

***

### Output

One dataset row per keyword:

```json
{
  "keyword": "ai seo tools",
  "difficultyScore": 64,
  "difficultyLabel": "hard",
  "authorityScore": 70,
  "titleOptimizationScore": 80,
  "serpFeatureScore": 50,
  "adsScore": 100,
  "domainConcentrationScore": 10,
  "highAuthorityCount": 7,
  "exactTitleMatches": 8,
  "uniqueDomains": 9,
  "adsCount": 4,
  "hasFeaturedSnippet": true,
  "peopleAlsoAskCount": 4,
  "topDomains": ["hubspot.com", "semrush.com", "..."],
  "recommendedAction": "Hard — only with strong domain authority and link building.",
  "source": "serpapi-google",
  "error": null
}
```

#### Key-value store outputs

- `EASY_WINS` — your lowest-difficulty keywords (the money output)
- `SUMMARY` — counts by rating, average difficulty, easiest + hardest
- `ERRORS` — any failed lookups

***

### Limitations & honesty

- This is a **SERP-signal estimate**, not a backlink-authority score. Treat it as directional.
- Results vary by `geo` and `language` — a keyword can be easy in one market, hard in another.
- The authority-domain list is curated + TLD heuristics (`.gov`/`.edu`); it won't recognize every strong niche site.
- One SerpApi lookup per keyword — mind your monthly quota on big lists.

***

### Related tools

- [Google Autocomplete Keyword Scraper](https://apify.com/groupoject/google-autocomplete-scraper) — discover the keywords to check here.
- [Google Trends Keyword Monitor](https://apify.com/groupoject/trendpulse-keyword-monitor) — see which of them are rising.
- [Google Trends Content Calendar Generator](https://apify.com/groupoject/trendpulse-content-calendar) — schedule the winners.

A natural workflow: **discover (Autocomplete) → qualify (this) → prioritize (Trends) → schedule (Calendar).**

***

### Changelog

See [CHANGELOG.md](CHANGELOG.md).

# Actor input Schema

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

Keywords to check difficulty for. You can also paste them as text below.

## `keywordsText` (type: `string`):

Paste one keyword per line or comma-separated.

## `geo` (type: `string`):

Google country code, e.g. US, GB, CA, FR, DE.

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

Language code, e.g. en, fr, es, de.

## `serpApiKey` (type: `string`):

Required. One SERP lookup per keyword. Get a free key (100/month) at https://serpapi.com. Never logged.

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

Maximum number of keywords to process.

## `requestDelayMs` (type: `integer`):

Delay between SERP lookups.

## `maxConcurrency` (type: `integer`):

Parallel SERP lookups. Keep modest to respect your SerpApi rate limit.

## `fetchMode` (type: `string`):

Data source for SERPs. SerpApi (BYO key) is the reliable path.

## `proxyConfiguration` (type: `object`):

Optional. Not required in SerpApi mode.

## `debugMode` (type: `boolean`):

Verbose logging.

## Actor input object example

```json
{
  "keywords": [
    "best coffee maker",
    "ai seo tools",
    "how to start a blog"
  ],
  "geo": "US",
  "language": "en",
  "maxKeywords": 100,
  "requestDelayMs": 500,
  "maxConcurrency": 3,
  "fetchMode": "serpapi",
  "debugMode": false
}
```

# Actor output Schema

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

One row per keyword: difficulty score, rating, SERP signals, recommendation.

## `easyWins` (type: `string`):

Lowest-difficulty keywords — best ranking opportunities.

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

Counts by rating, average difficulty, easiest + hardest keywords.

## `errors` (type: `string`):

Keywords that failed to fetch.

# 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 coffee maker",
        "ai seo tools",
        "how to start a blog"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("groupoject/keyword-difficulty-checker").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 coffee maker",
        "ai seo tools",
        "how to start a blog",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("groupoject/keyword-difficulty-checker").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 '{
  "keywords": [
    "best coffee maker",
    "ai seo tools",
    "how to start a blog"
  ]
}' |
apify call groupoject/keyword-difficulty-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=groupoject/keyword-difficulty-checker",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/6b8WU2YkVywM1Sz7b/builds/fczw1KxfqtEpxUZyz/openapi.json
