# Google Trends Scraper - Interest, Regions, Related & Trending (`rel8ble/google-trends-scraper`) Actor

Use this to get Google Trends data for keywords. Input: search terms (up to 5 comma-separated on one line to compare), country code, time range. One result = one keyword or comparison: interest over time (0-100), interest by region, top and rising related queries and topics. $2.50 per 1,000 results.

- **URL**: https://apify.com/rel8ble/google-trends-scraper.md
- **Developed by:** [Giovanni Rich](https://apify.com/rel8ble) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.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/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: keyword trends, related queries and trending searches

This **Google Trends scraper** works as an unofficial **Google Trends API**: scrape Google Trends for any keyword and get interest over time, interest by region, related queries, related topics and today's **trending searches** as clean JSON, CSV or Excel. Track **keyword trends**, compare up to 5 terms on one scale, and spot rising and breakout searches with no API key and no browser.

For every keyword, or group of up to 5 keywords compared against each other, you get:

- **Interest over time**: the 0-100 timeline Google shows, with dates, plus the average, peak, latest value and % change for each keyword
- **Interest by region**: 0-100 by country, state/province, US metro (DMA) or city
- **Related queries**: top and rising, including "Breakout" terms
- **Related topics**: top and rising, with Knowledge Graph IDs, when Google has them
- **Trending now**: Google's current trending searches for any country, with approximate search volume and news links

It's built to run without failing. Everything goes over plain HTTP, with **no headless browser**. Each session gets a Google cookie first. When Google rate-limits a request (HTTP 429), the scraper rotates to a new session and proxy IP and backs off with jitter. A failed search is retried on its own, so it never takes down the rest of the run.

### How to use the Google Trends scraper

1. Enter your keywords in **Search terms** (one per line, or comma-separated on one line to compare them), and optionally a country, time range, or countries for **Trending now**.
2. Click **Start**. A handful of searches usually finishes in well under a minute.
3. Download the results as JSON, CSV or Excel, or call the actor through the Apify API and get the dataset in your own code.

### Why this one

Google Trends is notoriously hard to scrape: it answers `429 Too Many Requests` to anything that looks automated. Most Trends scrapers fail a large share of their runs because of it. This actor was written around that problem:

- One small HTTP flow per search: cookie warm-up, explore, then the data widgets
- A new session and IP after a 429, plus short in-session retries for widget calls that hit a transient limit
- Results are saved per search as soon as they're ready, so a slow or failing search never blocks the others
- A `RUN_SUMMARY` record lists what came back for each search and what failed and why

### Use cases

- **SEO and content planning**: find rising and breakout queries before your competitors do
- **Product and e-commerce research**: seasonality, demand by state, comparing brands (e.g. `iphone, samsung galaxy`)
- **Market and investment research**: attention indicators for tickers, crypto and brands
- **Newsrooms and social media teams**: daily trending searches with the news stories behind them
- **Dashboards**: schedule the actor and feed the output into Sheets, Looker Studio or your own database

### Input

| Field | Default | Description |
|---|---|---|
| `searchTerms` | - | One search per line. Put up to 5 comma-separated terms on a line to **compare** them on one scale: `chatgpt, gemini, claude` |
| `exploreUrls` | - | Links pasted straight from trends.google.com/trends/explore. Keywords, country, dates, category and search type are read from each URL. |
| `geo` | Worldwide | `US`, `GB`, `DE`, `US-CA`, ... |
| `timeRange` | Past 12 months | Past hour, 4 hours, day, 7 days, 30 days, 90 days, 12 months, 5 years, or 2004-present |
| `customTimeRange` | - | `2024-01-01 2024-12-31` |
| `category` | 0 (all) | Google Trends category ID, e.g. 7 Finance, 71 Food & Drink |
| `searchProperty` | web | web, images, news, youtube, shopping |
| `includeInterestOverTime` / `includeInterestByRegion` / `includeRelatedQueries` / `includeRelatedTopics` | on | Turn off what you don't need to make runs faster |
| `regionResolution` | AUTO | COUNTRY, REGION, DMA (US metros) or CITY |
| `trendingNowGeos` | - | Country codes to fetch "Trending now" searches for |
| `proxyConfiguration` | Apify Proxy | Switch to RESIDENTIAL if you see many rate-limit retries |

### Input example

```json
{
    "searchTerms": ["bitcoin", "chatgpt, gemini, claude", "air fryer"],
    "geo": "US",
    "timeRange": "today 12-m",
    "trendingNowGeos": ["US", "GB"]
}
```

### Output example

You get **one result per search** (a line in `searchTerms` or an explore URL), with every data type nested inside it, plus **one result per trending search** if you asked for trending now. This one is from a real run: US, past 12 months (arrays shortened).

```json
{
    "type": "search",
    "searchTerm": "chatgpt, gemini, claude",
    "keywords": ["chatgpt", "gemini", "claude"],
    "geo": "US",
    "geoLabel": "US",
    "timeRange": "today 12-m",
    "category": 0,
    "searchProperty": "web",
    "hasData": true,
    "keywordStats": [
        { "keyword": "chatgpt", "average": 77.6, "peakValue": 100, "peakDate": "2025-10-19T00:00:00.000Z", "latestValue": 76, "changePercent": -20.2 },
        { "keyword": "gemini", "average": 26.9, "peakValue": 35, "peakDate": "2026-04-12T00:00:00.000Z", "latestValue": 33, "changePercent": 20.9 },
        { "keyword": "claude", "average": 17.9, "peakValue": 34, "peakDate": "2026-05-24T00:00:00.000Z", "latestValue": 19, "changePercent": 263.6 }
    ],
    "averageInterest": { "chatgpt": 78, "gemini": 27, "claude": 18 },
    "interestOverTime": [
        { "date": "2026-09-13T00:00:00.000Z", "formattedTime": "Sep 13 – 19, 2026", "values": { "chatgpt": 76, "gemini": 33, "claude": 19 }, "isPartial": false },
        { "date": "2026-09-20T00:00:00.000Z", "formattedTime": "Sep 20 – 26, 2026", "values": { "chatgpt": 82, "gemini": 36, "claude": 21 }, "isPartial": true }
    ],
    "interestByRegion": [
        { "geoCode": "US-CA", "geoName": "California", "values": { "chatgpt": 57, "gemini": 26, "claude": 17 } },
        { "geoCode": "US-DC", "geoName": "District of Columbia", "values": { "chatgpt": 58, "gemini": 20, "claude": 22 } }
    ],
    "regionResolution": "REGION",
    "relatedQueriesTop": [
        { "query": "what is chatgpt", "keyword": "chatgpt", "value": 100, "formattedValue": "100", "isBreakout": false, "link": "https://trends.google.com/trends/explore?q=what+is+chatgpt&date=today+12-m&geo=US" }
    ],
    "relatedQueriesRising": [
        { "query": "how to use chatgpt effectively", "keyword": "chatgpt", "value": 2050, "formattedValue": "+2,050%", "isBreakout": false, "link": "https://trends.google.com/trends/explore?q=how+to+use+chatgpt+effectively&date=today+12-m&geo=US" }
    ],
    "relatedTopicsTop": [],
    "relatedTopicsRising": [],
    "exploreUrl": "https://trends.google.com/trends/explore?q=chatgpt%2Cgemini%2Cclaude&geo=US&date=today+12-m&hl=en-US",
    "scrapedAt": "2026-09-24T05:14:08.994Z"
}
```

A trending-now result:

```json
{
    "type": "trending",
    "geo": "US",
    "rank": 1,
    "title": "dodgers schedule",
    "approxTraffic": "1000+",
    "approxTrafficNumber": 1000,
    "publishedAt": "2026-09-24T04:40:00.000Z",
    "picture": "https://encrypted-tbn2.gstatic.com/images?q=tbn:...",
    "pictureSource": "MLB.com",
    "news": [
        { "title": "The teams no one wants to play in October", "url": "https://www.mlb.com/news/scariest-mlb-teams-to-play-in-october-2026", "source": "MLB.com", "picture": "https://encrypted-tbn2.gstatic.com/images?q=tbn:..." }
    ],
    "scrapedAt": "2026-09-24T05:14:09.089Z"
}
```

`keywordStats.changePercent` compares the average of the last quarter of the period with the average of the first quarter. Partial (still-running) periods are left out of the stats.

The dataset has three views: **Overview**, **Interest over time** and **Trending now**. The run's key-value store also holds a `RUN_SUMMARY` with per-search counts, retries and any failures.

### Pricing

**Pay per result: $2.50 per 1,000 results.** One result = one search, or one trending search. A comparison of up to 5 keywords on one line counts as **one** result, and it includes the timeline, regions, related queries and related topics. Searches that fail after all retries are not charged.

- 100 results = $0.25
- 1,000 results = $2.50
- 10,000 results = $25

The Apify free plan includes $5 of monthly credit, enough for about 2,000 results.

### Integrations

- **Make, Zapier and n8n**: start runs and pass the Google Trends data into any workflow
- **Google Sheets**: export the dataset straight into a spreadsheet, or refresh it on a schedule
- **Apify API**: REST API plus official JavaScript and Python clients; run the actor and fetch results from your own code
- **Webhooks**: get notified when a run finishes and pull the results automatically
- **Schedules**: run daily or hourly to track keyword trends over time
- **MCP for AI agents**: through the Apify MCP server (https://mcp.apify.com), Claude, ChatGPT, Cursor and other agents can call this actor as a tool and read Google Trends data directly

### FAQ

**Is it legal to scrape Google Trends?**
The actor only collects publicly available, aggregated data that anyone can see on trends.google.com, and it contains no personal data. You are still responsible for how you use the results: follow Google's terms of service and the laws that apply to you (such as GDPR). This is not legal advice; ask a lawyer if you're unsure.

**How does it avoid blocks?**
It uses Apify Proxy by default and a session pool: each session first gets its own Google cookie. When Google answers with a rate limit (HTTP 429/403), that session is retired and the search is retried on a fresh session and proxy IP with exponential backoff and jitter (up to 8 retries by default, adjustable to 20). Widget calls that hit a short, transient limit get two quick in-session retries first. Concurrency defaults to 3 parallel searches to stay under Google's limits.

**What are the limits?**
Up to 5 keywords per comparison (Google's own limit; extra terms on a line are dropped). Values are Google's relative 0-100 index, not absolute search volumes. Trending now returns what Google's trending feed lists for each country, typically about 10 searches per country. Related topics and related queries only appear when Google has enough volume. Concurrency is capped at 10.

**Why are the numbers 0-100 rather than search volumes?**
That's how Google Trends reports interest. 100 is the peak for the chosen terms, place and time. Values are only comparable within a single search, so put terms on one line (comma-separated) to compare them on the same scale.

**Why do I get slightly different numbers from the website?**
Google Trends works from a sample of searches. Numbers can move by a few points between requests, even in the browser.

**Some searches have empty related queries or topics. Is that a bug?**
No. Google only shows related queries and topics when there is enough search volume. Related topics have become rare in Google's own responses lately. When Google returns none, you get an empty array rather than an error. `hasData: false` means Google had too little volume for the term.

**I see "rate-limited ... rotating session" warnings in the log.**
That's normal and handled. Google Trends throttles aggressively, and the actor retries on a fresh IP. If a search still fails after all its retries, it appears in `RUN_SUMMARY.failures` and no result is charged for it. Many failures usually mean the proxy pool is exhausted. Switch the proxy to the RESIDENTIAL group, or lower `maxConcurrency`.

**Can I get city- or metro-level data?**
Yes. Set `geo` to a country and `regionResolution` to `CITY`, or to `DMA` for US metros.

**Can I track a topic instead of a search term?**
Yes. Put a Knowledge Graph ID like `/m/0vpj4_b` in `searchTerms`, or paste an explore URL that uses a topic.

**How fast is it?**
In our tests, 9 searches plus 2 trending countries (29 results) took about 20 seconds.

# Actor input Schema

## `searchTerms` (type: `array`):

List of Google Trends searches; each string = one result. Single keyword: "bitcoin". Compare up to 5 terms on one 0-100 scale: comma-separate them in one string, e.g. "iphone, samsung galaxy". Topic IDs like "/m/05p0rrx" work. Give searchTerms, exploreUrls or trendingNowGeos.

## `exploreUrls` (type: `array`):

Optional. List of trends.google.com/trends/explore URLs, e.g. \["https://trends.google.com/trends/explore?q=bitcoin\&geo=US"]. Keywords, country, time range, category and search type are read from each URL.

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

Optional. Where to measure interest: "" = Worldwide (default), a 2-letter uppercase country code ("US", "GB", "DE", "IN") or a sub-region code ("US-CA", "GB-ENG").

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

Optional. Period to measure. One of: "now 1-H" (past hour), "now 4-H", "now 1-d", "now 7-d", "today 1-m" (30 days), "today 3-m", "today 12-m" (default), "today 5-y", "all" (2004-present). Ignored when customTimeRange is set.

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

Optional. Exact date range that overrides timeRange, format "YYYY-MM-DD YYYY-MM-DD" (start, space, end), e.g. "2024-01-01 2024-12-31".

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

Optional. Google Trends category ID, integer >= 0. Default 0 = all categories. Examples: 7 Finance, 5 Computers & Electronics, 71 Food & Drink, 47 Autos & Vehicles, 18 Shopping.

## `searchProperty` (type: `string`):

Optional. Which Google search to measure: "web" (default), "images", "news", "youtube" or "shopping".

## `includeInterestOverTime` (type: `boolean`):

Optional boolean. true = include the 0-100 interest timeline plus average, peak and change per keyword. Default true.

## `includeInterestByRegion` (type: `boolean`):

Optional boolean. true = include 0-100 interest per country (Worldwide) or per region/city (inside a country). Default true.

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

Optional. Level for interest by region: "AUTO" (default: countries for Worldwide, sub-regions inside a country), "COUNTRY", "REGION" (state/province), "DMA" (US metro) or "CITY". DMA and CITY need geo set to a country.

## `includeLowSearchVolumeRegions` (type: `boolean`):

Optional boolean. true = also return regions Google marks as low search volume. Default false.

## `includeRelatedQueries` (type: `boolean`):

Optional boolean. true = include top and rising related searches (rising includes "Breakout" terms). Default true.

## `includeRelatedTopics` (type: `boolean`):

Optional boolean. true = include top and rising related topics with Knowledge Graph IDs. Default true.

## `trendingNowGeos` (type: `array`):

Optional. List of 2-letter uppercase country codes, e.g. \["US", "GB"]. Adds Google's current "Trending now" searches for each country (about 10 each) with approximate volume and news links; one result per trending search.

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

Optional. Google interface language code, e.g. "en-US", "de", "fr". Affects region and topic names. Default "en-US".

## `timezoneOffset` (type: `integer`):

Optional. Minutes behind UTC using Google's sign convention, integer: 300 = UTC-5 (New York winter), -60 = UTC+1. Affects hourly and daily buckets. Default 0 (UTC).

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

Optional, advanced. Searches processed in parallel, integer 1-10. Default 3 (Google Trends rate-limits hard). Leave unset.

## `maxRequestRetries` (type: `integer`):

Optional, advanced. Retries per failed or blocked request, integer 0-20; each retry uses a new proxy session. Default 8. Leave unset.

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

Optional, advanced. Apify Proxy settings object, e.g. {"useApifyProxy": true}. Default: Apify Proxy on (datacenter). Leave unset; switch to {"useApifyProxy": true, "apifyProxyGroups": \["RESIDENTIAL"]} only if the run log shows repeated blocks.

## Actor input object example

```json
{
  "searchTerms": [
    "bitcoin",
    "iphone, samsung galaxy"
  ],
  "geo": "",
  "timeRange": "today 12-m",
  "category": 0,
  "searchProperty": "web",
  "includeInterestOverTime": true,
  "includeInterestByRegion": true,
  "regionResolution": "AUTO",
  "includeLowSearchVolumeRegions": false,
  "includeRelatedQueries": true,
  "includeRelatedTopics": true,
  "language": "en-US",
  "timezoneOffset": 0,
  "maxConcurrency": 3,
  "maxRequestRetries": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One item per search term (interest over time, by region, related queries and topics) plus one item per trending search.

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

Per-search counts, retries and any failures.

# 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 = {
    "searchTerms": [
        "bitcoin",
        "iphone, samsung galaxy"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rel8ble/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 = {
    "searchTerms": [
        "bitcoin",
        "iphone, samsung galaxy",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("rel8ble/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 '{
  "searchTerms": [
    "bitcoin",
    "iphone, samsung galaxy"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call rel8ble/google-trends-scraper --silent --output-dataset

```

## MCP server setup

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