# Google Trends Scraper & API - Compare up to 500 Keywords (`michael_b/google-trends-scraper`) Actor

Google Trends scraper and API for up to 500 keywords on one 0-100 scale, past Google's limit of 5. Interest over time, interest by region, top and rising related queries, change % and busiest month. Web, YouTube, News, Images or Shopping. For SEO and product research; no-data keywords are free.

- **URL**: https://apify.com/michael_b/google-trends-scraper.md
- **Developed by:** [Michal Búci](https://apify.com/michael_b) (community)
- **Categories:** SEO tools, Marketing, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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 & API - Compare up to 500 Keywords

Get Google Trends data for up to 500 keywords in one run: interest over time, interest by region, top and rising related queries, and a plain summary per keyword (change, trend, average, peak, busiest month). Compare is on by default, so every keyword shares one 0-100 scale, even past Google's limit of 5. The actor works from your own keywords; it doesn't list Google's daily "Trending now" searches.

### Google Trends data you get for each keyword

One row per keyword. With the default settings (Compare on, United States, past 5 years) the first columns look like this:

| keyword | trend | changePct | average | latest | seasonalPeakMonth | peakDate |
|---|---|---|---|---|---|---|
| air fryer | rising | 13.4 | 57.4 | 48 | January | 2022-01-02 |
| slow cooker | rising | 11.1 | 11.4 | 12 | December | 2022-11-20 |
| rice cooker | rising | 39 | 6 | 7 | | 2026-06-21 |

*(Run on 2026-10-05. Your numbers come from Google on the day you run it.)*

- **What compares between rows:** average, latest, peak and the timeline are on the shared scale. trend, changePct, peakDate and seasonalPeakMonth come from each keyword's own scale. Regions and related queries are each keyword's own list (its top = 100), so they don't compare between rows.
- **trend** and **changePct**: rising, falling or stable, and by how much. **changeBasis** sits right next to them and says what is compared: the last 12 months vs the previous 12 for ranges of 2 years or more (including custom dates), otherwise the second half of the range vs the first half.
- **average**, **latest**, **peak**: interest on the 0-100 scale. With Compare on these compare between rows: the busiest keyword's top point is 100.
- **seasonalPeakMonth**: the keyword's seasonality, the month that was busiest in the most full years, or two months when they tie (November/December). Useful for planning stock, content and ads. Needs 3 full years, so use Past 5 years or Since 2004. Blank when there's no clear yearly peak (like rice cooker above).
- **timeline**: every point in the range, oldest first. The newest point has `partial: true` because that week (or day, or hour) isn't over yet, so don't read a dip into it. With Compare on, a small keyword's line can look flat; run it with Compare off to see its shape. Turn **Include the timeline** off to get the summary only. In CSV and Excel downloads the timeline is spread over columns (timeline/0/date, timeline/0/value, ...); JSON keeps it as one list per keyword.
- **regions**: interest by region, where the keyword makes up the biggest share of searches: states, US metro areas, countries or cities.
- **risingSearches** and **topSearches**: Google Trends' rising and top related queries, with a **breakout** flag (growth over 5,000%).
- **trendsUrl**: the same view on trends.google.com, to check the numbers by eye. For linked keywords it opens that keyword's group, which Google scales to its own top, so compare the shape of the line there, not the numbers.

### Compare more than 5 keywords in Google Trends

Google Trends compares at most 5 keywords, and each comparison is scaled to its own top, so two comparisons don't fit together. This actor fixes that. Your first 5 keywords go to Google together. Every later group is sent with the busiest of those 5, and that shared keyword lines the groups up. At the end, the highest point across all keywords is set to 100. In our check against the website, keywords linked this way matched Google's own direct comparison: 58 / 20 / 12 / 2 / 2 on trends.google.com, 57.4 / 20.4 / 11.6 / 2.2 / 1.9 from the actor.

Change %, trend, peak date and busiest month are always worked out from each keyword's own scale. On the shared scale a small keyword is only a row of 0s and 1s, and those numbers would be wrong.

Each row's **compareQuality** says how it got onto the scale:

- **direct**: in the same Google request as the busiest of your first 5 keywords.
- **linked**: brought onto the scale through the shared keyword. Reliable.
- **rough**: the shared keyword was tiny next to a much bigger keyword in that group, so average, latest and peak can be off by more than 10%. Put very different keywords in separate runs.
- **own scale**: Compare was off. Each keyword then has its own 0-100 scale and the numbers don't compare between rows.

### Estimate monthly search volume from Google Trends

Google Trends only gives 0-100. If you know the monthly searches of your **first** keyword in the same country (for example from Google Keyword Planner), enter it in **Monthly searches of your first keyword**. Every keyword then gets **estimatedMonthlySearches**, scaled from that number by its last 12 months. It needs Compare on (the default); with Compare off only the first keyword gets one. It's an estimate for comparing keywords, not a Google count.

### Google Trends by country, time range and search type

| Field | What it does | Default |
|---|---|---|
| Keywords | Search terms, up to 500 per run, 100 characters each | air fryer, slow cooker, rice cooker |
| Compare keywords on one scale | One shared 0-100 scale for all keywords | on |
| Country or region | US, GB, US-CA, US-CA-807 (San Francisco Bay Area), or a name like Germany or Texas. Empty = worldwide | US |
| Time range | Past 24 hours, 7 days, 30 days, 90 days, 12 months, 5 years, since 2004, or custom dates | Past 5 years |
| Search type | Web, YouTube, News, Images or Google Shopping | Web |
| Category | A Google Trends category name or number, for words with two meanings | all |

Under **Advanced**: custom start and end dates, the timeline on or off, regions on or off, region level, regions per keyword (20), related queries on or off and how many (25), the monthly searches number, and the proxy.

Google gives a point every 8 minutes for Past 24 hours, every hour for 7 days, every day up to 90 days, every week up to 5 years and every month since 2004.

### Use Google Trends as an API (JSON input)

Call it from Python, JavaScript or any HTTP client through the Apify API. No pytrends setup and no Google API key. Input like this:

```json
{
  "keywords": ["iphone", "samsung galaxy", "google pixel"],
  "country": "GB",
  "timeRange": "past12Months",
  "includeTimeline": false
}
```

With `includeTimeline: false` each row carries the summary, regions and related queries without the 260-point series, which keeps AI agents' context small.

### Pricing: pay only for keywords with data

$0.003 per keyword that comes back with data, so $1.50 for a full 500-keyword run. Keywords Google has too little data for (`status: no_data`), keywords Google refused (`status: blocked`) and invalid keywords are free. They still get a row that says why, so nothing goes missing silently. If Google refuses every keyword, the run ends as failed instead of looking like an empty success.

### Google Trends for AI agents (Claude, ChatGPT, MCP)

The actor works as a tool in Claude, ChatGPT and other agents through the Apify MCP server. Questions it answers well:

- "Which of these 30 product ideas is growing fastest in the US?"
- "When in the year do people search for patio heaters?"
- "Compare interest in Notion, Obsidian and Evernote over 5 years."
- "What related queries are breaking out for 'electric bike'?"

Tip for agents: send `includeTimeline: false`, and also `includeRegions: false` and `maxRelatedSearches: 10` unless the question is about places or related queries. A row is then about 500-700 tokens instead of about 7,000. Read `trend`, `changePct` and `changeBasis` first.

### FAQ

**Is this the official Google Trends API?** No. It is not made by or affiliated with Google. It reads the same public data you see on trends.google.com, and trendsUrl opens that exact view.

**Why 0-100 and not search counts?** That's what Google Trends publishes: interest relative to the busiest point. Use the monthly searches option for rough counts.

**Why do my numbers differ a little from the website?** Google computes Trends from a sample of searches and redraws that sample now and then, so the same view can move by a few points between visits. In our side-by-side check the trend line matched the website within 1-2 points.

**Why can regions and related queries differ more?** For these two lists, Google gives tools a different slice of its data than it shows in the browser. The busiest region usually matches, but the order further down and the exact rising queries can differ. Use them for direction (which places, which new searches), not as an exact copy of the website.

**Why is Wyoming at the top for "air fryer"?** The regions value is the keyword's share of all searches in that place, not the number of searches. A small state where people search it a lot relative to everything else ranks high.

**What if a keyword has very few searches?** Google returns no data or just a few scattered points for it. You get `status: no_data`, and the keyword is not charged.

**Why does Google Shopping show huge changes?** Google's Shopping search data has gaps and jumps. In the US it is close to zero for most products from late 2024 to mid 2025, then about 10 times higher from March to June 2026, and daily points are often 0 (the website shows the same). So change % for Shopping can read +100% or more. Use Shopping to compare products against each other on one scale rather than to read change %.

**Why are city lists often empty?** Google shares city-level numbers with automated requests only in some places, so city lists often come back empty even when the website shows cities (we checked "pizza" in Scotland: 50 cities on the website, none for tools). States and US metro areas are reliable. A US metro code (US-CA-807) or a region like GB-SCT defaults to cities, so pick the bigger area (US-CA or GB) to get a list.

**Does it need a proxy?** Google limits Trends lookups per IP address. With the default proxy setting the actor starts on Apify's datacenter IPs, retries refused lookups on a new IP, and switches to residential IPs by itself if Google blocks the datacenter ones. Keep the default.

**How fast is it?** Google slows down anyone who asks too fast, so the actor paces itself. A few keywords usually take under a minute, sometimes up to two when Google is slow. In our tests 40 keywords on one scale took about 2 minutes. When Google pushes back it can take around 10 seconds per keyword, so allow an hour or more for 500.

# Actor input Schema

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

What people search on Google, one per line. Up to 500 per run, 100 characters each. A keyword repeated in any letter case is looked up once and returns one row, under the spelling you typed first.

## `compare` (type: `boolean`):

On: all keywords share one 0-100 scale like on Google Trends, so average, latest and peak compare directly between rows (100 = the busiest point of the busiest keyword). Works for any number of keywords, not just Google's 5. Off: each keyword gets its own 0-100 scale and the numbers don't compare between rows. Change %, trend, peak date and busiest month always come from each keyword's own scale, so they are right either way.

## `country` (type: `string`):

One place per run: a two-letter country code (US, GB, DE), a region code (US-CA, GB-SCT), a US metro area code (US-CA-807 = San Francisco Bay Area) or a plain name (Germany, Texas). Leave empty for worldwide. An unknown place gives an invalid_input row that says what to type.

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

How far back to look. Google gives a point every 8 minutes for 24 hours, every hour for 7 days, every day up to 90 days, every week up to 5 years and every month since 2004. changePct compares the last 12 months with the 12 before for ranges of 2 years or more (custom dates too), and the second half of the range with the first half otherwise.

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

Which Google search to measure.

## `category` (type: `string`):

Narrow a word with two meanings, e.g. "jaguar" in Autos & Vehicles. A Google Trends category name (Shopping, Health, Food & Drink, Finance, Autos & Vehicles, Travel) or its number. Leave empty for all categories. An unknown name gives an invalid_input row.

## `startDate` (type: `string`):

Only used when Time range is Custom dates (ignored otherwise). First day, YYYY-MM-DD, 2004-01-01 or later.

## `endDate` (type: `string`):

Only used when Time range is Custom dates. Last day, YYYY-MM-DD. Empty means today.

## `includeTimeline` (type: `boolean`):

Add every point of the interest-over-time series (the timeline field). Off keeps the summary numbers, regions and related queries only. A 5-year timeline is about 260 points per keyword, so turning it off makes rows much smaller, useful for AI agents and big keyword lists.

## `includeRegions` (type: `boolean`):

Add the places where each keyword makes up the biggest share of searches (the regions field).

## `regionLevel` (type: `string`):

Automatic: the level Google shows on its own site. That's countries when worldwide, states or provinces inside a country, and metro areas inside a US state. Metro areas exist for the US only; elsewhere you get states or provinces. City lists are often empty for automated requests, even when the website shows cities. Rows report the level as country, state/province, metro or city.

## `maxRegions` (type: `integer`):

How many of the top places to return for each keyword, 1 to 300.

## `includeRelatedSearches` (type: `boolean`):

Add the searches people make alongside each keyword: the most common (topSearches) and the fastest growing (risingSearches, with a Breakout flag for growth over 5,000%).

## `maxRelatedSearches` (type: `integer`):

How many top and rising related queries to keep per keyword, 1 to 25 (Google gives at most 25).

## `knownMonthlySearches` (type: `integer`):

Google Trends gives 0-100, not search counts. If you know the monthly searches of your FIRST keyword in the same country (e.g. from Google Keyword Planner), enter it and every keyword gets estimatedMonthlySearches scaled from it. With Compare off, only the first keyword gets an estimate.

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

Google limits Trends lookups per IP. Keep the default: the actor starts on Apify's datacenter IPs and switches to residential IPs by itself if Google blocks them. Choose a proxy group here only if you want to force one.

## Actor input object example

```json
{
  "keywords": [
    "air fryer",
    "slow cooker",
    "rice cooker"
  ],
  "compare": true,
  "country": "US",
  "timeRange": "past5Years",
  "searchType": "web",
  "category": "",
  "includeTimeline": true,
  "includeRegions": true,
  "regionLevel": "auto",
  "maxRegions": 20,
  "includeRelatedSearches": true,
  "maxRelatedSearches": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Dataset with one row per keyword, in the order you entered them.

# 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": [
        "air fryer",
        "slow cooker",
        "rice cooker"
    ],
    "compare": true,
    "country": "US",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("michael_b/google-trends-scraper").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": [
        "air fryer",
        "slow cooker",
        "rice cooker",
    ],
    "compare": True,
    "country": "US",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("michael_b/google-trends-scraper").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": [
    "air fryer",
    "slow cooker",
    "rice cooker"
  ],
  "compare": true,
  "country": "US",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call michael_b/google-trends-scraper --silent --output-dataset

```

## MCP server setup

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

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/80NewDNF4rEnO8Tfb/builds/EMjcWWwfdsRK13m58/openapi.json
