# Google Trends Scraper: Compare 100 Keywords on One Scale (`alhadikhan/google-trends-compare`) Actor

Google Trends compares only 5 keywords at a time. This Actor puts up to 100 keywords or topics on one shared 0-100 scale, keeps small keywords from rounding to 0, and labels the precision of every number. Tested against a known true answer. JSON plus a ready CSV table.

- **URL**: https://apify.com/alhadikhan/google-trends-compare.md
- **Developed by:** [MD. AL-HADI KHAN](https://apify.com/alhadikhan) (community)
- **Categories:** SEO tools, Marketing
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 keyword results

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

## Google Trends Scraper: compare 100 keywords on one scale

Google Trends compares **only 5 keywords at a time**. Each comparison is scaled so its own highest point is 100 and rounded to whole numbers. Two separate comparisons can't be put side by side, and small keywords next to big ones show up as "0" or "<1".

This Actor compares **up to 100 keywords or topics on one shared 0–100 scale**, keeps small keywords measurable, and tells you how precise each number is.

### What you get

For every keyword:

- its **rank**, **average interest** and **peak interest**, all on one scale;
- the full **timeline** (one value per day, week or month, depending on the time range);
- a **precision label** (`high`, `medium`, `low`), so you know which numbers to trust;
- how it was measured (`matchedAs`: `words`, `topic` or `topic ID`), the **topic** used, and a note if a requested topic couldn't be found.

#### Words with several meanings

A plain word counts every search for it: "jaguar" includes both the car and the animal. To measure one meaning, add it in brackets: `Jaguar (car make)`. The Actor then uses the Google topic of that type, and only if its name matches. If Google has no such topic, the plain word is measured and `matchNote` says so. It never guesses. You can also give a topic ID directly, with your own label if you like: `Python language=/m/05z1_`.

You also get a **wide table (CSV)** with dates in rows and keywords in columns, ready for Excel, Google Sheets or pandas. It's saved in the key-value store record `TABLE`.

#### Example: 12 keywords, 5,500x apart (real run, worldwide, last 12 months)

| Rank | Keyword | Average interest | Precision |
|---|---|---|---|
| 1 | weather | 77.566 | high |
| 2 | python | 4.811 | high |
| 3 | bitcoin | 4.192 | high |
| 4 | rust | 1.543 | high |
| … | … | … | … |
| 12 | ocaml | 0.014 | medium |

On Google Trends itself, "ocaml" next to "weather" is just "<1". Here it has a real value and its own shape over the year.

### How it works

1. **Size check.** Every keyword is compared against an anchor to estimate how big it is. Keywords the anchor drowns out are measured again against a smaller anchor.
2. **Ladder.** Keywords are sorted by size and grouped with neighbours of similar size. Neighbouring groups share one "link" keyword, and a group ends early when sizes jump, so nobody gets rounded to 0.
3. **Stitch.** The groups are chained through their links, each keyword is taken from the comparison where it was measured best, and the result is rescaled to a maximum of 100.

#### Why not just repeat one anchor keyword in every batch?

That simple method breaks as soon as your keywords differ a lot in size: small keywords round to 0, and if the anchor is small, every batch breaks.

We tested both methods on simulated Google data where the true answer is known. That's 40 keywords per test, 6 tests per size range, with the same rounding Google does:

| Keyword sizes span | Ladder: keywords lost | Ladder: worst error | One anchor: keywords lost |
|---|---|---|---|
| 100x | 0 | under 1% | 0 (worst error up to 17%) |
| 1,000x | 0 | under 1% | 57 of 240 |
| 10,000x | 0 | under 1% in 5 of 6 tests\* | 117 of 240 |

\*In the hardest test the small keywords were off by about 12%, and the Actor labelled every one of them `low`. Keywords labelled `high` were within 1% in every test.

#### Tested on real Google data, too

We compared this Actor's output with **Google's own direct comparisons** of every neighbouring pair, for the 12 keywords in the example above (5,500x apart):

- **no keyword lost**;
- neighbouring keywords within **0.5% (median), 2.2% (worst)** of Google's direct ratios;
- "weather" vs "ocaml" within **2%** of the ratio chained from Google's pairs;
- the same input run twice differed by at most **1.1%**.

Values keep 4 decimals. Tools that round to whole numbers after rescaling turn every keyword below 0.5 into 0. In the same 12-keyword test, that approach lost 6 of the 12 keywords.

**The raw data is genuine.** Google sends automated tools decoy data in some panels (related queries), but not in the timeline. We checked the timeline Google sends us against the Google Trends website, value by value: 53 of 53 weeks identical (python, United States, past 12 months, 7 Nov 2026). This Actor uses only that timeline, and we repeat the check every month.

### Input

| Field | Example | Notes |
|---|---|---|
| Keywords or topics | `python`, `Jaguar (car make)`, `Python language=/m/05z1_` | Up to 100. Duplicates are removed. See "Words with several meanings" below. |
| Location | `US`, `GB`, `US-CA` | Empty means worldwide. |
| Time range | `today 12-m` | Same format as Google Trends: `now 7-d`, `today 3-m`, `today 5-y`, `all`, or `2024-01-01 2024-12-31`. |
| Search type | Web, YouTube, News, Images, Shopping | |
| Category ID | `0` | Google Trends category number. |
| Proxy | Residential (default) | Google blocks data-centre IPs quickly. |

```json
{
  "keywords": ["python", "javascript", "java", "rust", "kotlin", "typescript", "golang", "haskell"],
  "geo": "US",
  "timeframe": "today 12-m"
}
```

### Output example (one dataset item, shortened)

```json
{
  "rank": 2,
  "keyword": "python",
  "query": "python",
  "topic": null,
  "matchedAs": "words",
  "matchNote": null,
  "averageInterest": 4.811,
  "peakInterest": 7.545,
  "precision": "high",
  "geo": "worldwide",
  "timeframe": "today 12-m",
  "property": "web",
  "category": 0,
  "timeline": [
    { "date": "2025-11-02", "value": 4.996, "isPartial": false },
    { "date": "2025-11-09", "value": 5.098, "isPartial": false }
  ]
}
```

### FAQ

**How do I compare more than 5 keywords in Google Trends?**
Put them all in the Keywords field (up to 100). The Actor runs the batches of 5, links them, and returns one scale. You don't need to pick an anchor keyword yourself.

**Is this a pytrends alternative?**
Yes. pytrends was archived in April 2025. This Actor returns the same interest-over-time data as JSON or CSV, handles Google's rate limits for you, and can be called from Python with the `apify-client` package.

**Why do my numbers differ from what I see on Google Trends?**
Google scales every comparison so its own top point is 100. Here the top point of *all* your keywords is 100, so each keyword is shown relative to the biggest one in your list. Ratios between keywords are what matter, and those are kept.

**Can I measure my brand against competitors?**
Yes. For brand tracking in percent, see our **Share of Search Tracker**, which uses the same engine and reports each brand's share of all brand searches per month, quarter or year.

**Do I pay for failed runs?**
You're charged per keyword in the results. If a run fails (for example, because of an invalid location code), no results are written and no keyword charges apply.

### Tips

- **Check `matchedAs` and `matchNote`** when you use brackets. To find a topic ID yourself, search the term on Google Trends, pick the topic from the dropdown, and copy the `/m/...` or `/g/...` part from the address bar.
- **Keep the same location and time range** when you compare runs. Values are only comparable within one run.
- **Very short time ranges** (`now 1-H`, `now 4-H`) change minute by minute. A run can fail if a new interval starts midway. Just run it again.

### Limits

- Values are relative interest, not search volume. That's what Google Trends provides.
- Up to 100 keywords per run. Larger runs take longer, because Google is asked politely, with pauses.
- The last point of a timeline is often `isPartial: true` (the current week or day isn't over yet).

# Actor input Schema

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

Up to 100 search terms or Google Trends topics. Words with several meanings: add the meaning in brackets, for example 'Jaguar (car make)' or 'Python (programming language)', and the matching Google topic is used. Or give a topic ID, optionally with your own label: 'Python language=/m/05z1\_'. Everything ends up on one shared 0-100 scale.

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

Two-letter country code (US, GB, DE, BD) or region code (US-CA). Leave empty for worldwide.

## `timeframe` (type: `string`):

Same format as Google Trends: 'now 7-d', 'today 1-m', 'today 3-m', 'today 12-m', 'today 5-y', 'all', or a date range such as '2024-01-01 2024-12-31'.

## `property` (type: `string`):

Which Google search to measure: web (the normal Google Trends view), images, news, YouTube or Shopping.

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

Google Trends category number, to limit searches to one topic area. Examples: 5 Computers & Electronics, 31 Programming, 47 Autos & Vehicles, 390 Mobile Phones, 37 Banking. 0 means all categories.

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

Google rate-limits data-centre IPs hard. Residential proxies are strongly recommended.

## Actor input object example

```json
{
  "keywords": [
    "python",
    "javascript",
    "java",
    "rust",
    "kotlin",
    "typescript",
    "golang",
    "haskell"
  ],
  "geo": "",
  "timeframe": "today 12-m",
  "property": "",
  "category": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

No description

## `table` (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": [
        "python",
        "javascript",
        "java",
        "rust",
        "kotlin",
        "typescript",
        "golang",
        "haskell"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("alhadikhan/google-trends-compare").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",
        "javascript",
        "java",
        "rust",
        "kotlin",
        "typescript",
        "golang",
        "haskell",
    ],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("alhadikhan/google-trends-compare").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",
    "javascript",
    "java",
    "rust",
    "kotlin",
    "typescript",
    "golang",
    "haskell"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call alhadikhan/google-trends-compare --silent --output-dataset

```

## MCP server setup

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

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/IzuMV2IXpD2U5fDOc/builds/s8Pw2frdaxrLM9gca/openapi.json
