# Google Trends Keyword Ranker and Compare Tool (`datagrit/google-trends-keyword-ranker`) Actor

Rank up to 100 keywords on one comparable Google Trends scale, with interest by region and related queries, for many locations in one run.

- **URL**: https://apify.com/datagrit/google-trends-keyword-ranker.md
- **Developed by:** [datagrit](https://apify.com/datagrit) (community)
- **Categories:** SEO tools, Marketing
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

### What does Google Trends Keyword Ranker and Compare Tool do?

Google Trends Keyword Ranker and Compare Tool takes a list of up to 100 keywords and ranks them against each other on one Google Trends scale, per location. Google Trends itself compares five terms at a time and rescales every chart to its own peak, so two charts cannot be compared. This Actor links the groups through a repeated anchor keyword and returns average interest, peak, trend direction, top regions and related queries as structured rows you can export as JSON, CSV or Excel, call through the Apify API, or plug into n8n, Make and AI agents through MCP. No browser and no API key are needed.

### Why use Google Trends Keyword Ranker and Compare Tool?

- **Keyword research and content planning.** Take 50 candidate topics, see which ones have real search interest and which are rising, and sort the list by one comparable number instead of eyeballing five charts at a time.
- **Market and product comparison.** Compare brands, tools, programming languages or products in several countries in one run and see where each one is strongest.
- **Seasonality and trend alerts.** Schedule the Actor weekly, store the rows and track `changePct` and `trendDirection` per keyword over time.
- **Finding what is breaking out.** The related queries output flags breakout queries, which are search terms that grew by more than 5,000 percent.
- **Regional targeting.** Rank countries, states, metro areas or cities by share of searches for a keyword to decide where to run ads or open a market.

### What data does it return?

Pick the row types in **Data to return**. Every row has a `type`, the `keyword`, the `geo` it was measured in and a `scrapedAt` timestamp.

- **keywordSummary** is one ranked row per keyword and location: `rank`, `normalizedAverage`, `peakValue`, `peakDate`, `latestValue`, `changePct`, `trendDirection` and `scaleQuality`.
- **interestOverTime** is one row per keyword and location with the whole `timeline` in one field: date, raw 0 to 100 value, value on the shared scale and a flag for the period still running.
- **interestByRegion** returns the top regions for each keyword at country, state, metro or city level.
- **relatedQuery** returns the top and rising related queries with their score and a breakout flag.

#### How the shared scale works

Keywords are read in groups of five. From the second group on, the middle keyword of the first group is repeated as an anchor, and the ratio between its two readings rescales the whole group. Each row says how reliable its placement is in `scaleQuality`: `exact` for the first group, `good` when the anchor had plenty of search volume, `coarse` when it was thin or when the keyword's own values average below 3 on Google's 0 to 100 scale (whole-number rounding then dominates), and `unlinked` when it was too thin to link at all. Unlinked keywords keep their own 0 to 100 values but get no rank. The run message lists how many keywords fell into each class, so you know how far to trust the ranking.

### Example output

A run for seven programming languages in the United States over the last 12 months returned this ranking:

| rank | keyword | normalizedAverage | trendDirection | scaleQuality |
|---|---|---|---|---|
| 1 | swift | 31.6 | steady | good |
| 2 | python | 30.5 | steady | exact |
| 3 | java | 15.1 | steady | exact |
| 4 | rust | 15 | rising | exact |
| 5 | typescript | 1.8 | rising | coarse |
| 6 | golang | 1 | falling | coarse |
| 7 | kotlin | 0.8 | rising | coarse |

Swift ranks first because Google's search interest includes the bird, the singer and the language, which is a good reason to look at related queries before drawing conclusions. A related-queries row for python looks like this:

```json
{
  "type": "relatedQuery",
  "keyword": "python",
  "geo": "US",
  "relatedKind": "rising",
  "relatedRank": 1,
  "relatedQuery": "python programming tutorial",
  "relatedValue": 4450,
  "relatedLabel": "+4,450%",
  "isBreakout": false,
  "scrapedAt": "2026-10-08T03:00:00.000Z"
}
```

### How much does it cost to scrape Google Trends?

The Actor uses pay per result pricing: you pay for each row it returns, and nothing for rows it does not return. Keywords or locations with too little search volume produce a single status row that is not charged, and so does a keyword whose interest rounds to 0 next to much stronger keywords in the same list (the run message counts these), and a run that cannot read Google Trends fails instead of billing empty rows. The **Maximum rows** input caps what a run can produce, and you can also set a maximum spend on the run in Apify. Check the pricing tab of the Actor for the current price per result.

A keyword summary run is the cheapest way to rank a long list, because it returns one row per keyword and location. A timeline is also one row per keyword, however many data points it holds.

### How to use the Actor

1. Enter your keywords in **Keywords**, one per line. Phrases work as well as single words.
2. Choose **Locations** as country codes such as `US`, `DE` or `GB`, regions such as `US-CA`, or `WORLDWIDE`. Up to 10 locations can be compared in one run.
3. Set the **Time range** from the last hour to all time, or give a **Custom date range** as two dates.
4. Select the **Data to return** and run the Actor. Open the Overview view of the dataset for the ranking, or use the Regions, Related and Series views for the other row types.

Searches can be limited to web, images, news, YouTube or shopping, and to a Google Trends **Category ID**, for example to separate the fruit from the phone brand.

#### Input example

```json
{
  "keywords": ["python", "rust", "golang"],
  "geos": ["US", "DE"],
  "timeRange": "today 12-m",
  "dataTypes": ["keywordSummary", "relatedQueries"],
  "relatedQueryKind": "rising",
  "maxRelatedPerKeyword": 5,
  "maxItems": 100
}
```

### Output fields

| Field | Meaning |
|---|---|
| `type` | keywordSummary, interestOverTime, interestByRegion, relatedQuery or status |
| `keyword`, `geo` | The keyword and the location the row was measured in |
| `rank` | Position among all keywords of the location, 1 is the most searched |
| `normalizedAverage` | Average interest on the shared scale, where the strongest keyword peaks at 100 |
| `averageValue` | Average of the raw 0 to 100 points of the keyword in its own group |
| `peakValue`, `peakDate` | Highest point on the shared scale and when it happened |
| `changePct`, `trendDirection` | Change between the first and last third of the range, and rising, falling or steady. A keyword that starts from zero has no percentage but is rising |
| `scaleQuality`, `anchorKeyword` | How the keyword was placed on the shared scale, and the anchor that linked it |
| `timeline` | Interest over time rows: date, value, normalizedValue, isPartial for every point |
| `regionName`, `regionCode`, `regionValue`, `regionRank` | Interest by region rows |
| `relatedQuery`, `relatedKind`, `relatedValue`, `relatedLabel`, `isBreakout` | Related query rows |
| `found`, `reason`, `message` | Status rows that explain why a keyword or location returned no data |

### FAQ

#### Is it legal to scrape Google Trends?

The Actor reads the aggregated, public search interest numbers that anyone can see on the Google Trends website without logging in. It collects no personal data. You are responsible for using the results in line with the terms of the services you build on them.

#### Why do some keywords have no rank?

A keyword gets no rank when Google returns too little search volume for it, or when it is too small to be linked to the others. The `scaleQuality` field says which. A keyword without data in a location, or one that rounds to 0 on every point next to much stronger keywords, produces a free status row instead of a billed result; run such a keyword on its own to see its own curve.

#### Why do values differ from the Google Trends website?

Google Trends shows values from 0 to 100 relative to the highest point in the chart. The shared scale puts all keywords of the run on one chart, so the values are comparable between keywords. The raw numbers are in `averageValue` and in the `value` field of each timeline point.

#### How many keywords and locations can I compare?

Up to 100 keywords and 10 locations per run, and the **Maximum rows** field stops a run at the row count you set.

#### How often can I run it?

As often as you like. Google Trends refreshes daily, so a daily or weekly schedule is typical. When Google slows down requests, the Actor waits and retries, and the run message reports how many retries were needed.

#### What is not included?

Related topics are not returned, only related queries. Keywords with very low search volume get no values at all, which is how Google Trends reports them.

### Related Actors

- [Google News RSS Monitor](https://apify.com/datagrit/google-news-rss-monitor) tracks what is being published about the keywords you rank here.
- [Website Tech Stack Lookup](https://apify.com/datagrit/website-tech-stack-lookup) identifies the technology behind the sites that win the searches you found.

# Changelog

This Actor's version history is a separate document: https://apify.com/datagrit/google-trends-keyword-ranker/changelog.md

# Actor input Schema

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

Keywords or topics to compare, one per line, up to 100. Lists longer than five are linked automatically so every number is on the same 0 to 100 scale. Duplicates are ignored.

## `geos` (type: `array`):

Where to measure interest: a country code such as "US" or "DE", a region such as "US-CA" or "GB-ENG", or "WORLDWIDE". Each location is a separate comparison, up to 10 per run.

## `timeRange` (type: `string`):

Period to measure. Short ranges return hourly points, long ones weekly or monthly points.

## `customTimeRange` (type: `string`):

Optional range "YYYY-MM-DD YYYY-MM-DD", start date first, for example "2024-01-01 2024-12-31". When filled it replaces the time range above.

## `searchType` (type: `string`):

Which Google property the searches come from.

## `category` (type: `integer`):

Optional Google Trends category number that narrows the searches, for example 5 for Computers and Electronics. 0 means all categories.

## `dataTypes` (type: `array`):

Row types to produce, one per line: keywordSummary (one ranked row per keyword and location), interestOverTime (one row per keyword and location with the whole timeline in one field), interestByRegion and relatedQueries (both read per keyword). Unknown values are ignored.

## `regionResolution` (type: `string`):

Granularity of the interest by region rows: automatic picks countries for worldwide runs and states or provinces for a country; cities and metro areas give finer rows inside a country, and Google reports only cities with enough search volume, so rare keywords may return few or none.

## `maxRegionsPerKeyword` (type: `integer`):

Keep this many top regions for each keyword and location.

## `relatedQueryKind` (type: `string`):

Top queries are the most searched alongside the keyword; rising queries grew fastest and include breakout flags.

## `maxRelatedPerKeyword` (type: `integer`):

Keep this many related queries of each kind for each keyword and location.

## `maxItems` (type: `integer`):

Stop after this many rows in total across all keywords and locations.

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

Google Trends rate limits shared server addresses, so Apify Proxy is on by default. Switch it off only when you run the Actor from a home connection.

## Actor input object example

```json
{
  "keywords": [
    "python",
    "java",
    "rust",
    "golang",
    "kotlin",
    "swift",
    "typescript"
  ],
  "geos": [
    "US"
  ],
  "timeRange": "today 12-m",
  "customTimeRange": "",
  "searchType": "web",
  "category": 0,
  "dataTypes": [
    "keywordSummary"
  ],
  "regionResolution": "auto",
  "maxRegionsPerKeyword": 25,
  "relatedQueryKind": "both",
  "maxRelatedPerKeyword": 25,
  "maxItems": 200,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All extracted records as a dataset.

# 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": [
        "python",
        "java",
        "rust",
        "golang",
        "kotlin",
        "swift",
        "typescript"
    ],
    "geos": [
        "US"
    ],
    "timeRange": "today 12-m",
    "customTimeRange": "",
    "searchType": "web",
    "category": 0,
    "dataTypes": [
        "keywordSummary"
    ],
    "regionResolution": "auto",
    "maxRegionsPerKeyword": 25,
    "relatedQueryKind": "both",
    "maxRelatedPerKeyword": 25,
    "maxItems": 200,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("datagrit/google-trends-keyword-ranker").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": [
        "python",
        "java",
        "rust",
        "golang",
        "kotlin",
        "swift",
        "typescript",
    ],
    "geos": ["US"],
    "timeRange": "today 12-m",
    "customTimeRange": "",
    "searchType": "web",
    "category": 0,
    "dataTypes": ["keywordSummary"],
    "regionResolution": "auto",
    "maxRegionsPerKeyword": 25,
    "relatedQueryKind": "both",
    "maxRelatedPerKeyword": 25,
    "maxItems": 200,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("datagrit/google-trends-keyword-ranker").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": [
    "python",
    "java",
    "rust",
    "golang",
    "kotlin",
    "swift",
    "typescript"
  ],
  "geos": [
    "US"
  ],
  "timeRange": "today 12-m",
  "customTimeRange": "",
  "searchType": "web",
  "category": 0,
  "dataTypes": [
    "keywordSummary"
  ],
  "regionResolution": "auto",
  "maxRegionsPerKeyword": 25,
  "relatedQueryKind": "both",
  "maxRelatedPerKeyword": 25,
  "maxItems": 200,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call datagrit/google-trends-keyword-ranker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datagrit/google-trends-keyword-ranker"
        }
    }
}
```

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/Inl8soaNTbopoARtv/builds/rOcD5ctl7W49GV5VL/openapi.json
