# Google Trends Scraper – Compare 100+ Keywords (`quinic_resin/google-trends-scraper`) Actor

Google Trends data for any number of keywords: interest over time, interest by region, related and rising queries, plus Trending Now by country. Compare 100+ keywords on one scale, get spike and breakout alerts on a schedule. Pay only per result.

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

## Pricing

from $0.01 / 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 – Compare 100+ Keywords

Get Google Trends data for **any number of keywords** in one run: interest over time, interest by region, related and rising queries, and **Trending Now** searches by country. Put 100+ keywords on **one comparable scale** (Google stops at 5), and schedule runs that flag **spikes and new breakout queries**.

No browser, no login, no Google account. Residential proxies are included in the price, and you pay only for rows that contain data.

### What you can do with it

- **Keyword research and content planning.** Check hundreds of topic ideas at once and sort by average interest, recent change or year-over-year growth. Then mine the rising queries for the next article.
- **Market and product research.** Compare brands, product names or features on one 0–100 scale, and see where each is most popular.
- **Brand and competitor monitoring.** Schedule a daily run with a monitor name. Each row tells you whether the keyword is spiking and which rising queries appeared since yesterday.
- **News and social teams.** Pull what's trending right now in the US, UK, India, Germany and more, with search volume, growth, start time, category and news links.
- **Data science and AI agents.** Clean JSON with summary numbers (average, peak, latest, change %, trend, spike), so a dashboard or an LLM agent can answer "is this growing?" without reading 260 data points. Agents can call it through the Apify API or MCP server.

### Why this one

| | This Actor | Typical Google Trends scrapers |
|---|---|---|
| Keywords per run | Unlimited, in parallel | Often 1 per run, or a slow browser |
| Compare more than 5 keywords on one scale | ✅ up to 300 (fitted across overlapping requests, see below) | ❌ |
| Summary numbers per keyword (trend, change %, spike, YoY) | ✅ | Raw points only |
| Monitoring: only new trends, new breakout queries | ✅ | ❌ |
| Rate limits | Fresh residential sessions, retries only the failed part | Run fails or returns empty |
| Price | $3 per 1,000 keyword reports, all sections included. Trending: $0.50 per 1,000 | Per data point, start fees, or platform usage on top |

### Input examples

**Several keywords, each on its own scale (the default):**

```json
{
  "searchTerms": ["standing desk", "walking pad", "ergonomic chair"],
  "geo": "US",
  "timeRange": "today 12-m"
}
```

**Compare 30 brands on one scale:**

```json
{
  "searchTerms": ["notion", "obsidian", "evernote", "onenote", "..."],
  "compareKeywords": true,
  "timeRange": "today 5-y"
}
```

**Paste links from trends.google.com.** The link's terms, location, dates, category and search type are used:

```json
{ "startUrls": [{ "url": "https://trends.google.com/trends/explore?date=now%207-d&geo=GB&q=tea,coffee" }] }
```

**What's trending right now in four countries, sports only:**

```json
{ "mode": "trending", "trendingGeos": ["US", "GB", "IN", "DE"], "trendingHours": "24", "trendingCategories": ["17"] }
```

**Daily alerts.** Add a monitor name and create a Schedule in Apify Console:

```json
{ "searchTerms": ["my brand", "competitor one", "competitor two"], "monitorId": "brand-watch" }
```

### Output

One row per keyword. Example values:

```json
{
  "type": "keyword",
  "keyword": "standing desk",
  "geo": "US",
  "geoName": "United States",
  "timeRange": "today 12-m",
  "averageInterest": 77.2,
  "peakInterest": 100,
  "peakDate": "2026-01-04",
  "latestInterest": 91,
  "latestDate": "2026-09-27",
  "changePercent": 14.5,
  "trend": "rising",
  "trendChangePercent": 21.3,
  "isSpike": false,
  "yearOverYearChangePercent": null,
  "topRegion": "Washington",
  "topRisingQuery": "standing desk with treadmill",
  "timelineResolution": "week",
  "interestOverTime": [
    { "date": "2025-10-05", "value": 68, "isPartial": false },
    { "date": "2025-10-12", "value": 71, "isPartial": false }
  ],
  "interestByRegion": [
    { "geoCode": "US-WA", "geoName": "Washington", "value": 100 },
    { "geoCode": "US-CA", "geoName": "California", "value": 93 }
  ],
  "relatedQueries": {
    "top": [{ "query": "standing desk converter", "value": 100, "formattedValue": "100", "isBreakout": false }],
    "rising": [{ "query": "standing desk with treadmill", "value": 5000, "formattedValue": "Breakout", "isBreakout": true }]
  },
  "sectionsMissing": [],
  "trendsUrl": "https://trends.google.com/trends/explore?date=today%2012-m&geo=US&q=standing%20desk&hl=en-US",
  "scrapedAt": "2026-10-05T09:00:00.000Z"
}
```

Compared keywords also carry `comparedWith` and `comparisonMethod`. Their values share one scale: 100 is the busiest point of any keyword in the group.

With a monitor name, rows also carry `newRisingQueries`, `alert` (a spike or a new rising query) and `firstMonitorRun`.

Trending Now rows look like this:

```json
{
  "type": "trending",
  "geo": "US",
  "rank": 1,
  "keyword": "fed rate decision",
  "searchVolume": 500000,
  "searchVolumeLabel": "500K+",
  "growthPercent": 1000,
  "startedAt": "2026-10-05T06:10:00.000Z",
  "endedAt": null,
  "isActive": true,
  "hoursTrending": 3.2,
  "relatedKeywords": ["fed", "interest rates"],
  "categories": ["Business and Finance", "Politics"],
  "news": [{ "title": "…", "url": "https://…", "source": "Reuters" }],
  "isNew": true,
  "trendsUrl": "https://trends.google.com/trends/explore?date=now%207-d&geo=US&q=fed%20rate%20decision"
}
```

Each run also stores:

- **Report:** an HTML page with a chart for every keyword, comparison charts and Trending Now tables.
- **Timeline CSV:** every keyword's points in long format, ready for Excel, Sheets or Looker Studio.
- **Comparison:** the shared-scale series as JSON.
- **Run summary:** counts, charges, and any failures with the reason.

### Pricing

Pay per event. Platform usage and proxies are included.

| Event | Price |
|---|---|
| Keyword report: one keyword with timeline, regions and related searches | $0.003 ($3 per 1,000) |
| Trending search: one trending search with volume, growth and news | $0.0005 ($0.50 per 1,000) |

You are **not charged** for:

- keywords Google has no data for (the row is still delivered, with `hasData: false`)
- keyword rows whose interest over time could not be fetched (delivered with the reason in `sectionsMissing` and `note`)
- keywords that failed after all retries (listed in the run summary)
- Trending Now rows that a monitor already reported
- rows delivered before a platform restart of the same run (they are never delivered or charged twice)

Set a spending limit when you start a run, and the Actor stops cleanly at that limit.

### How comparing 100+ keywords works

Google compares at most 5 terms per request and scales each request so its busiest point is 100. Every request still says how big its terms are relative to each other, so the Actor combines many overlapping requests into one scale:

1. Every keyword is fetched next to an anchor keyword, 4 per request. Keywords that round to 0, or that are hidden next to a much bigger one, are fetched again next to keywords closer to their size.
2. All the ratios from all requests are combined in one weighted fit: precise measurements count more, rough ones less. Each keyword gets a level and an uncertainty, so no single rough request can throw the result off.
3. Where uncertainty remains, overlapping groups of similar popularity (at most about 1:10 apart) are fetched, and the fit is repeated.
4. Everything is normalized so the single busiest point is 100.

In simulations of Google's integer rounding, 50 keywords spanning 1:1,000 in popularity came out within about 1% of their true averages. Products launched partway through the period, and one keyword 50× more popular than all the others, are handled too.

Some keywords get a `note` instead:

- **Values only estimated roughly** (±10% or more): the note says the values are approximate.
- **Too small to show next to the top keyword** (below about 0.5%, as on Google's own chart): reported as 0 and not charged.

Comparing adds about one to one and a half Google requests per keyword. The price per keyword is the same.

### FAQ

**What do the numbers mean?**
Google Trends values are relative, not search counts. 100 is the peak for the chosen keyword (or group), place and time range; 50 is half as popular. Trending Now volumes (`searchVolume`) are Google's own estimates of searches.

**Why does a keyword show `hasData: false`?**
Google has too little search volume for it in that location and period. Try a wider time range or Worldwide. You are not charged for these rows.

**What if one keyword is hugely more popular than the rest?**
On one shared scale, a keyword below about 0.5% of the top one shows as 0. Google's own chart shows it the same way. Those rows are free and say so in `note`. Compare the smaller keywords in a separate run without the giant to see them in detail.

**Why are related topics empty?**
Google often withholds related topics from automated sessions, and never offers them in comparisons. Related queries are not affected. The option is off by default, and leaving it on costs nothing extra.

**Will Google block it?**
Google rate-limits Trends hard per IP, and that is the main reason Trends scrapers fail. This Actor uses fresh residential sessions, warms up cookies, paces requests, and retries only the failed section on a new session. A keyword that still fails is listed in the run summary and costs nothing.

**Which countries and languages?**
Every location Google Trends supports: country codes (`US`, `GB`, `DE`, `IN`, …) and regions (`US-CA`, `GB-ENG`). Trending Now works per country. `language` changes the names of regions and categories; search terms are never translated.

**Can I use it from code or an AI agent?**
Yes, through the Apify API, the JavaScript and Python clients, webhooks, and Apify's MCP server. Input and output are plain JSON, and every row carries its own summary numbers.

**Is scraping Google Trends allowed?**
The Actor reads publicly available, aggregated, anonymous data that Google shows on trends.google.com without a login. It collects no personal data. Check that your use complies with Google's terms and your local laws.

### Support

Open an issue on the Actor's **Issues** tab and include the run link. Feature requests are welcome.

# Changelog

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

# Actor input Schema

## `mode` (type: `string`):

<b>Keyword trends</b>: interest over time, interest by region and related searches for your search terms (one row per keyword).<br><b>Trending now</b>: what is spiking in Google Search right now in one or more countries (one row per trending search).

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

Keywords to look up, one per line. Each keyword gets its own row with Google's 0–100 interest scale. Google Trends syntax works: <code>tea + coffee</code> (either), <code>"green tea"</code> (exact), <code>tea -green</code> (exclude), or a topic id like <code>/m/07c1v</code>.

## `compareKeywords` (type: `boolean`):

Put all search terms on one shared 0–100 scale, like Google's comparison chart – but for up to 300 keywords (Google allows 5). Overlapping requests are combined into one consistent scale. Leave off to get each keyword on its own scale.

## `startUrls` (type: `array`):

Paste explore links from trends.google.com (e.g. <code>https://trends.google.com/trends/explore?q=tea,coffee\&geo=GB</code>). The link's terms, location, time range, category and search type are used. A link with several terms is a comparison.

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

Country code like <code>US</code>, <code>GB</code>, <code>DE</code>, or a region like <code>US-CA</code>. Leave empty for Worldwide.

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

Period to analyse. Shorter periods give finer data: minutes or hours for the past day/week, days up to 9 months, weeks up to 5 years, months for 2004–present.

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

Overrides the time range above. Format <code>YYYY-MM-DD YYYY-MM-DD</code>, e.g. <code>2025-01-01 2025-06-30</code>. For hourly data use <code>YYYY-MM-DDTHH YYYY-MM-DDTHH</code> (max 7 days).

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

Narrow results to a topic area (e.g. <i>python</i> in Computers & Electronics vs. Pets & Animals). Deeper categories work through a Google Trends link.

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

Which Google search to measure.

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

The timeline (0–100) plus summary numbers: average, peak, latest, recent change, rising/falling, spike flag, year-over-year change.

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

Where the keyword is most popular (countries for Worldwide, states/regions for a country).

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

<b>Auto</b> follows Google: countries for Worldwide, subregions for a country. Cities work for most countries; metro areas (DMA) only for the US.

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

Top regions to keep, sorted by interest. 0 = all.

## `includeLowVolumeRegions` (type: `boolean`):

Also list regions where Google has little data (shown as 0).

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

Top and rising searches people also make, including 'Breakout' queries (growth over 5,000%).

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

Top and rising topics (entities). Google often returns this list empty for automated access and never offers it in comparisons; you are not charged extra either way.

## `trendingGeos` (type: `array`):

Country codes for Trending now, e.g. <code>US</code>, <code>GB</code>, <code>IN</code>, <code>DE</code>. One run can cover many countries.

## `trendingHours` (type: `string`):

Time window for trending searches.

## `trendingCategories` (type: `array`):

Only keep trends in these categories. Empty = all.

## `trendingOnlyActive` (type: `boolean`):

Skip trends that have already ended.

## `maxTrendingPerGeo` (type: `integer`):

Google lists up to a few hundred trends per country and time window.

## `includeTrendingNews` (type: `boolean`):

Adds the news stories Google links to the top trends (one extra request per country).

## `monitorId` (type: `string`):

Give a name (e.g. <code>daily-us-trends</code> or <code>my-brands</code>) and schedule the Actor. <b>Trending now</b>: later runs return only trends that are new since the previous run. <b>Keyword trends</b>: each row lists rising queries that are new since the previous run and an <code>alert</code> flag (new breakout or spike). Runs with the same name share this memory.

## `onlyNew` (type: `boolean`):

With a monitor name, Trending now returns only trends not reported before.

## `firstRunBaseline` (type: `boolean`):

With a monitor name, the first Trending now run returns nothing (and costs nothing) and just remembers what is trending; alerts start with the next run.

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

Stop after this many rows. 0 = no limit. You can also set a spending limit when you start the run.

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

How many proxy sessions query Google at once. Higher is faster; Google rate-limits aggressive clients, and the Actor backs off and rotates sessions automatically.

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

Language for region names and labels, e.g. <code>en-US</code>, <code>de</code>, <code>es-MX</code>. Search terms are never translated.

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

Google Trends rate-limits datacenter IPs within a few requests, so residential proxies are used by default. Proxy traffic is included in the price.

## Actor input object example

```json
{
  "mode": "keywords",
  "searchTerms": [
    "chatgpt",
    "claude"
  ],
  "compareKeywords": false,
  "geo": "US",
  "timeRange": "today 12-m",
  "category": "0",
  "property": "",
  "includeInterestOverTime": true,
  "includeInterestByRegion": true,
  "regionResolution": "auto",
  "maxRegions": 50,
  "includeLowVolumeRegions": false,
  "includeRelatedQueries": true,
  "includeRelatedTopics": false,
  "trendingGeos": [
    "US"
  ],
  "trendingHours": "24",
  "trendingOnlyActive": false,
  "maxTrendingPerGeo": 100,
  "includeTrendingNews": false,
  "onlyNew": true,
  "firstRunBaseline": false,
  "maxItems": 0,
  "maxConcurrency": 5,
  "language": "en-US",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

One row per keyword (timeline, summary, regions, related searches) or per trending search.

## `report` (type: `string`):

HTML report with a chart per keyword, comparison charts and Trending Now tables.

## `timelineCsv` (type: `string`):

Every keyword's interest over time in long format (keyword, date, value) – ready for Excel, Sheets or a BI tool.

## `comparison` (type: `string`):

For compared keywords: dates and every keyword's series on the shared scale, plus the method used.

## `runSummary` (type: `string`):

Counts, charged rows, failures with reasons, and request statistics.

# 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": [
        "chatgpt",
        "claude"
    ],
    "geo": "US",
    "trendingGeos": [
        "US"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("quinic_resin/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": [
        "chatgpt",
        "claude",
    ],
    "geo": "US",
    "trendingGeos": ["US"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("quinic_resin/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": [
    "chatgpt",
    "claude"
  ],
  "geo": "US",
  "trendingGeos": [
    "US"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call quinic_resin/google-trends-scraper --silent --output-dataset

```

## MCP server setup

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