# Google Trends Scraper & API (`suslabs/google-trends-scraper`) Actor

Google Trends scraper and API in bulk: interest over time, compare up to 5 keywords, daily trending searches, states, metros and cities, rising and Breakout queries. A pytrends alternative that handles 429 errors for you. You pay only for complete results, plus a tiny start fee.

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

## Pricing

from $1.70 / 1,000 keyword reports

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** gets Google Trends data for **any number of keywords in one run**: interest over time, interest by state, metro area or city, related and rising queries, **keyword comparisons on one shared scale**, and **daily trending searches by country**. No browser, no Google account, no code: it works like a Google Trends API you can use today.

**Why people choose it:**

- ✅ **Result charges require complete data.** Blocked keywords, no-data keywords and reports missing requested base panels have no result event charge. The platform startup fee still applies; daily estimates charge per complete baseline/window.
- ⚡ **Automatic connection fallback.** Requests try direct connections first and switch to rotating residential proxies when needed. Runtime varies with refusals and panels: a saved full-panel three-term comparison on 21 Oct 2026 took about 21 seconds; a 20-keyword run took about two minutes.
- 🛡️ **Built for Google's rate limits.** A refused panel is retried on its own over a fresh connection. In our stress tests (100 keywords, 20 at a time) 200 of 200 reports came back complete.
- 🔁 **Monitoring that doesn't charge you for noise.** Scheduled runs mark keywords UNCHANGED (free) unless something really changed, such as a newly completed week or a new Breakout query.
- 🐍 **A pytrends replacement** that handles the `429 Too Many Requests` errors for you. Most pytrends methods have a direct equivalent (see below).
- 🤖 **Ready for AI agents:** compact output, an MCP setup, and a clear output schema.

Export to JSON, CSV or Excel, call it from the API, or connect it to Make, Zapier, n8n, Google Sheets or an AI agent.

### What you get in the example comparison

The default input compares **ChatGPT vs Gemini vs Claude** in the US over the past 12 months. A real run on 20 Oct 2026 returned:

| Keyword | Share within this comparison | Average interest | First vs last quarter | Strongest state |
| --- | --- | --- | --- | --- |
| ChatGPT | 62% | 75 / 100 | stable (−10%) | Mississippi |
| Gemini | 22% | 27 / 100 | rising (+31%) | California |
| Claude | 16% | 19 / 100 | **rising (+207%)** | District of Columbia |

Shares use the sum of Google's average indices for these selected terms, not AI usage or market share. Change percentages compare the first and last quarters of complete observations in the range, not year-over-year growth.

Top rising searches for Claude included the **Breakout** queries "claude cowork" and "claude opus 5.5".

The prefilled demo compares ChatGPT, Gemini and Claude in the US with weekly timelines, regional interest and related queries. Click **Start** to try it.

### What can this Google Trends scraper do?

- 📈 **Interest over time:** the same 0–100 timeline you see on trends.google.com, from the past hour to 2004–present, or any custom date range.
- 🆚 **Compare keywords on one scale:** up to 5 keywords per group, like the Trends compare view. Longer lists are split into groups of 5 automatically. You get the winner, share of search and ranking.
- 🗺️ **Google Trends by region:** countries, US states, **metro areas (DMA)** or **cities with coordinates**, optionally including low-volume regions.
- 🔍 **Related and rising queries:** top and rising searches, with **Breakout** queries flagged.
- 🔥 **Daily trending searches** for any country, with approximate traffic ("200K+"), news articles and images.
- 🌍 **Many countries in one run:** every keyword in US, GB, IN and more.
- 🧭 **Compare one keyword across countries or periods**, e.g. 2025 vs 2026.
- 📺 **YouTube, Google Shopping, News and Image search trends**, plus 25 categories.
- 🧮 **Ready-made insights** for every keyword: average, peak and peak date, trend direction, change %, year-over-year change, volatility, spikes, top regions and a one-sentence summary.
- 🔗 **Paste Google Trends URLs** or import keywords from a Google Sheet or CSV.
- 📄 **Nested or flat output:** flat gives one row per data point, perfect for Excel and BI tools. Compact output is available for AI agents.

### How it compares

| | This Actor | Typical Google Trends scrapers |
| --- | --- | --- |
| Keywords per run | Any number, in parallel | Varies; some take one keyword per run |
| Charging | Complete reports or daily baseline/windows; startup fee also applies | Varies by Actor |
| Compare on one scale | Up to 5 per group, automatic grouping, optional chaining for more | Often up to 5, grouped by hand |
| Regions | Countries, states, metros, cities with coordinates | Often one level |
| Trending searches | Daily RSS with news, plus the full Trending Now feed | Often one of the two |
| Monitoring | Built in; unchanged keywords have no result event charge | Implementation dependent |
| Insights | Average, peak, direction, change %, YoY, spikes, breakouts, summary sentence | Raw numbers |
| Related topics | Not offered: Google returns them empty to automated clients | Often listed; frequently empty in practice |

### How to scrape Google Trends

1. Choose **What to scrape**: keyword trends, compare keywords, daily trending searches, or topic suggestions.
2. Add your **keywords** (one per line). Topic IDs like `/m/0k8z` work too.
3. Optionally set a **country or region**, a **time range** and which **data** to collect.
4. Click **Start**, then download the results as JSON, CSV or Excel, or fetch them through the API.

Leave the advanced settings alone unless you need them. The defaults (residential proxies, a fresh IP for every request, automatic retries) are tuned for reliability.

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

You pay per result, and **only for complete results**: every panel you asked for has to be there. Platform usage and residential proxies are included in the price. There is also an **Actor start fee of $0.00005 per GB, with a one-event minimum**: $0.00005 per run at 512 MB, including runs with no charged result. The table lists Free-tier event prices checked on 21 Oct 2026.

| Result | Price | Example |
| --- | --- | --- |
| Keyword report (timeline + regions + related queries) | **$2.00 per 1,000** | 100 keywords ≈ **$0.20** |
| Comparison group (up to 5 keywords on one scale) | **$5.00 per 1,000** | 100 groups = 500 keywords ≈ **$0.50** |
| Trending search (one trend with its news) | **$1.00 per 1,000** | A country's daily list (~10 trends) ≈ **$0.01** |
| Topic suggestions (per keyword) | **$1.50 per 1,000** | 100 keywords ≈ **$0.15** |

Higher Apify plans get automatic discounts. Result exemptions do not waive the start fee. Optional daily estimates charge for the complete baseline and each usable fitted window; a missing daily window does not make other complete units free. **No result event charge:** keywords Google blocked after all retries, keywords with no data, reports missing any requested panel (delivered free, marked `partial`), invalid input, the extra rows in flat output, the end-of-run summary, and raw explore widgets. **Max results limits report tasks, not dollars.** Use the platform maximum cost per run for an event-spending cap.

### Input example

```json
{
  "mode": "compare",
  "searchTerms": ["ChatGPT", "Gemini", "Claude"],
  "geo": "US",
  "timeRange": "today 12-m",
  "sections": ["interestOverTime", "interestByRegion", "relatedQueries"]
}
```

More examples:

- **Trends by US metro area:** `"regionResolution": "DMA"`
- **YouTube trends:** `"property": "youtube"`
- **Daily trending searches in India and Brazil:** `"mode": "trending", "geos": ["IN", "BR"]`
- **The same keyword in several countries:** `"geos": ["US", "GB", "DE"]`
- **This year vs last year:** `"comparePeriods": true, "periods": ["2025-01-01 2025-06-30", "2026-01-01 2026-06-30"]`
- **Switch an existing pipeline:** `"outputFormat": "apify-compatible"`
- **Full Trending Now:** `"mode": "trending", "geo": "US", "trendingSource": "full", "trendingHours": 24, "activeOnly": true, "maxTrendsPerCountry": 50`
- **Watch for changes:** `"monitorMode": true, "monitorName": "weekly-brands", "onlyChanges": true`
- **Compare more than five on an estimated common scale:** `"mode": "compare", "chainComparisons": true, "anchorTerm": "coffee"`
- **Several region panels:** `"regionLevels": ["REGION", "CITY"]` (additional requests)
- **Different settings per query:** `"advancedQueries": [{"terms": ["coffee", "tea"], "geo": "GB", "timeRange": "today 3-m"}]`
- **Seasonal content planning:** `"timeRange": "today 5-y", "includeSeasonality": true, "seasonalityLeadDays": 30`
- **A recent result when Google blocks:** `"cachedResultOnRefusal": true, "cacheName": "brand-history"`
- **Reduce sampling noise:** `"sampleCount": 3, "sampleAggregation": "mean"` (up to three times the normal requests and report/group charges)
- **Daily Sheets digest input:** `"mode": "trending", "geo": "US", "monitorMode": true, "monitorName": "daily-digest", "onlyNew": true, "maxItems": 20`

### Output example

One keyword from the demo comparison above (real data, arrays shortened):

```json
{
  "searchTerm": "Claude",
  "geo": "US",
  "timeRange": "today 12-m",
  "averageInterest": 18.865,
  "peakInterest": 34,
  "peakDate": "2026-04-12T00:00:00+00:00",
  "trendDirection": "rising",
  "changePercent": 207.23,
  "topRegion": "District of Columbia",
  "topRegionCode": "US-DC",
  "summaryText": "Interest is rising; complete-period average 18.9/100, peak 34 on 2026-04-12.",
  "shareOfSearchPct": 15.702,
  "rankInComparison": 3,
  "interestOverTime": [
    { "date": "2026-10-18T00:00:00+00:00", "formattedAxisTime": "Oct 18, 2026", "value": 22, "isPartial": true }
  ],
  "interestByRegion": [
    { "geoCode": "US-DC", "geoName": "District of Columbia", "value": 23, "formattedValue": "23%" }
  ],
  "relatedQueries": {
    "top": [
      { "query": "ai claude", "value": 100 },
      { "query": "claude code", "value": 77 }
    ],
    "rising": [
      { "query": "claude cowork", "formattedValue": "Breakout", "isBreakout": true },
      { "query": "claude opus 5.5", "formattedValue": "Breakout", "isBreakout": true }
    ]
  },
  "exploreUrl": "https://trends.google.com/trends/explore?q=ChatGPT%2CGemini%2CClaude&geo=US&date=today+12-m",
  "status": "ok",
  "scrapedAt": "2026-10-20T18:34:26+00:00"
}
```

In a comparison, region values are each keyword's share of searches in that region (here, Claude's share in DC).

Comparison rows also include `winner`, `ranking`, `shareOfSearchPct` and a wide timeline with one column per keyword. Every run ends with a free `_summary` row listing what was delivered, what failed and why, and how many results were charged. Use the **Overview**, **Timeline**, **Regions**, **Related**, **Comparison**, **Trending**, **Status / errors**, **Flat** and **Summary** views, plus **Topic suggestions**, **Daily estimates** and **Related top**. Views project fields; they do not filter row types. Open the **ERRORS** or **SUMMARY** key-value record for errors only or one summary. Compact output removes panel arrays: use Overview or disable compact output for panel views. For flat output use Flat and select row type (`timeline`, `region`, `related`); daily estimates have `series:daily_estimate`. Panel projections can also contain other row types. Comparison members are informational; the envelope carries the group charge.

### Compare keywords on Google Trends

Google Trends values are relative. Each keyword on its own is scaled 0–100 against its own peak, so separate reports can't be compared with each other. Choose **Compare keywords on one scale** to put up to 5 keywords on the same scale, exactly like the compare view on trends.google.com. Lists longer than 5 are split into groups of 5. Each group has its own scale, and one group costs one result.

### Compare more than five Google Trends keywords

Turn on `chainComparisons` to link comparison groups through an anchor keyword. The extra free `_chainedComparison` row contains `normalizedValue` on an estimated common scale and `lowPrecision` warnings. Each underlying group is charged as a normal comparison: 11 keywords need three groups. For very small terms, choose `bridgeTerm` and `bridgeTerms` with `bridgeRemeasurement:true` to add closer comparisons. Integer rounding and Google sampling still limit precision; the scale applies within this run.

### Get daily trending searches by country

Choose **Daily trending searches by country** and enter one or more country codes. Each trend comes with approximate traffic (for example `200K+`), publication time, an image and the related news articles. This uses Google's public trending feed: it is current and country-level only, with no history.

### Google Trending Now: growth, active trends and related searches

Choose `trendingSource:"full"` in trending mode for the full current feed. Each search includes its volume bucket lower bound, reported growth percentage, start and end times, active status, categories and breakdown searches. Choose a 4, 24, 48 or 168 hour window; filter active or ended trends, category IDs or minimum volume; sort by volume, newest or name. `trendingLanguage` sets the feed language. RSS remains the default when you want a short list with news and images.

### Daily Google Trends data for long ranges

Google only returns daily values for ranges up to about 9 months; longer ranges come back weekly or monthly. Enable **Daily estimates over long ranges** (`dailyResolution`). It fetches a normal report plus N overlapping 240-day windows with 21 shared days, then fits daily values to Google's weekly or monthly curve. A year needs 2 windows plus the baseline; five years needs about 9; **2004–present needs about 38, so up to 39 keyword-report charges per keyword** (about $0.08 at the standard price). Timeline-only takes at least 3(N+1) HTTP requests and up to N+1 normal keyword-report charges. Daily windows contain more points, so data transfer need not scale like request count. Each delivered window is charged; failed windows are free and don't block the rest. A window where the keyword had no interest yet is returned as zeros. The full event budget is reserved before work. Use separate keyword mode with a timeline; it cannot be combined with comparison, sampling, monitoring or caching. The `dailySeries` estimates can exceed 100 on the coarse reference scale. Missing days are not filled in.

### Monitor Google Trends and pay only for changes

Turn on **Remember results between runs** (`monitorMode`), give the monitor a name, and schedule the Actor. Each run compares every keyword with what it reported last time:

- **NEW** or **UPDATED** keywords are charged as normal reports.
- **UNCHANGED** keywords are **free**.

Google Trends numbers wobble a little from request to request, because Google samples searches. Those wobbles are ignored, so you don't pay for noise. In our tests, repeat runs minutes apart came back 97–100% UNCHANGED.

**What counts as a change:**

- **New data.** A newly completed week (or day, or hour, depending on the time range). This is the usual reason a scheduled run reports UPDATED; for example, a daily run on a 12-month range updates once a week.
- **A real jump.** A value moving more than the tolerance (normal: the larger of 12 points or 15%), or a clear change in the top regions.
- **A new rising or Breakout query.** It's confirmed on a second check at least an hour later before it counts, because Google's rising list reshuffles between requests. Expect new-query alerts one schedule interval later than they first appear.

**Sensitivity:**

- `normal` (default) suits most monitors.
- `low` ignores more.
- `high` reports smaller moves, but it will also report ordinary sampling noise, so expect more UPDATED (charged) results.

Every changed row lists `changedFields` and a plain reason in `changeReasons` (for example "new complete period"), plus the `previous` values.

Keyword reports are always compared with their last saved result, however long ago it was. Trending searches not seen again within the retention window (default 7 days) expire with a free EXPIRED row. Use a separate monitor name per task or schedule, and avoid overlapping runs of the same monitor.

### Google Trends by city, region and season

Use `regionLevels` for several regional panels in one report; each additional level adds a widget request. `advancedQueries` lets each group have its own country, dates, category or search type. For content planning, `includeSeasonality` adds a monthly profile and heuristic peak-month dates when at least two years of data are available. Shorter histories return null with an explanation.

#### Can I get a saved result if Google refuses a request?

Enable `cachedResultOnRefusal` and choose a `cacheName`. Complete successful reports are saved for later runs. If Google then blocks a request, an eligible recent snapshot is returned free with `freshness:"CACHED"` and `cacheAgeSeconds`. Its original scrape time is preserved. The maximum is 24 hours, with tighter limits for short charts.

### Stable Google Trends samples with uncertainty

Set `sampleCount` to 2–5 to repeat the report through fresh rotating residential connections. Choose `sampleAggregation:"mean"` or `"consensus"`. Numeric points include `valueStdError`, `sampleCount` and `sampleAgreement`; related lists use the most frequent returned panel. **N samples can cost N times the normal report or comparison price**, with failed samples free. All samples must fit your maximum charge before work starts. Pool rotation cannot guarantee that every exit IP is unique, and standard error does not capture Google's rounding or systematic bias.

### Google Trends workflows for n8n, Make and Google Sheets

Use a scheduled run with a named monitor to send new trends or changed keyword reports into Google Sheets, Slack or a database:

1. Create a task with `monitorMode` on and `onlyChanges` on, and schedule it (for example daily at 9:00).
2. Add an integration (Google Sheets, Slack, webhook to n8n or Make) that fires when the run succeeds.
3. In the workflow, skip rows whose `type` is `_summary` or `status`, and upsert the rest by their stable `id`.

Need a ready-made n8n or Make template? Ask on the Issues tab and we'll share one.

### Ways to use Google Trends data

- **SEO and content:** find rising and Breakout queries before competitors, and plan content around seasonal peaks.
- **Market and product research:** compare brands, products or features by country, state or city.
- **E-commerce:** track Google Shopping demand and spot rising product searches.
- **Marketing:** choose regions and timing for campaigns, and measure launch buzz.
- **Data and AI pipelines:** feed clean, structured trend data into dashboards, notebooks, LLM agents or alerts.

### A pytrends alternative that handles rate limits

pytrends, the popular unofficial Python library, was archived in 2025, and it regularly fails with **429 Too Many Requests**. This Actor uses the same Google Trends data but manages the proxies, cookies and retries for you.

| pytrends | This Actor |
| --- | --- |
| `build_payload(kw_list, geo, timeframe, cat, gprop)` | `searchTerms`, `geo`, `timeRange`, `category`, `property` |
| `interest_over_time()` | `interestOverTime` |
| `interest_by_region(resolution, inc_low_vol)` | `interestByRegion`, `regionResolution`, `includeLowVolumeRegions` |
| `related_queries()` | `relatedQueries.top` / `relatedQueries.rising` |
| `suggestions()` | mode **Topic suggestions** |
| `trending_searches()` | mode **Daily trending searches** |
| `related_topics()` | Not offered by this Actor |

### Switching from another Google Trends scraper

Inputs from apify/google-trends-scraper work here: `searchTerms`, `isMultiple`, `timeRange`, `geo`, `viewedFrom`, `startUrls`, `spreadsheetId`, `category`, `customTimeRange` and `maxItems`. With `isMultiple:true`, a comma-separated entry such as `"coffee,tea"` is one comparison. Numeric category strings are accepted.

Set `outputFormat:"apify-compatible"` for `interestOverTime_timelineData`, `interestOverTime_averages`, `interestBySubregion`, `interestByCity`, `interestByMetro`, `interestBy` and `relatedQueries_top` / `relatedQueries_rising`. The usual status and charge fields stay available. Related topics are empty with an explanation; this scraper does not supply them. Extra region levels require the optional region-level setting. Check your downstream field mapping before switching a production workflow.

### Call the Google Trends API

```python
from apify_client import ApifyClient

import os
from decimal import Decimal

## Install apify-client>=3,<4; set APIFY_TOKEN in your environment.
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("suslabs/google-trends-scraper").call(run_input={
    "mode": "compare",
    "searchTerms": ["coffee", "tea", "matcha"],
    "geo": "US",
}, memory_mbytes=512, max_total_charge_usd=Decimal("0.05"))
if run is None or run.status != "SUCCEEDED":
    raise RuntimeError("Run did not succeed; inspect status and log.")
for item in client.dataset(run.default_dataset_id).iterate_items():
    if item.get("type") not in {"_summary", "status", "checkpoint"}:
        print(item)
```

```bash
curl -X POST "https://api.apify.com/v2/acts/suslabs~google-trends-scraper/run-sync-get-dataset-items?memory=512&maxTotalChargeUsd=0.05" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms": ["coffee"], "geo": "US"}'
```

For big jobs, start the run asynchronously and read the dataset when it finishes. Results can go straight to Google Sheets, Slack, Make, Zapier, n8n, Airbyte or a data warehouse through [Apify integrations](https://docs.apify.com/integrations).

### Use with AI agents (MCP)

Add this Actor to Claude, Cursor or any MCP client through the [Apify MCP server](https://mcp.apify.com?tools=suslabs/google-trends-scraper):

```json
{ "mcpServers": { "apify": { "url": "https://mcp.apify.com?tools=suslabs/google-trends-scraper" } } }
```

The hosted URL uses Streamable HTTP and requires Apify authentication (OAuth where supported, or a token in the client's secret configuration). A URL alone is not an authenticated connection. The tool name verified with `tools/list` is `suslabs--google-trends-scraper`; running it can incur charges.

Tip for agents: turn on **Compact output** to get just the insights (average, peak, direction, top regions, Breakout queries) instead of long arrays.

### FAQ

#### Is there an official Google Trends API?

Google announced a Google Trends API alpha in July 2025. Check its current availability and eligibility before choosing an integration. This Actor gives you the data available on trends.google.com through a simple API you can use today, including Trending Now searches.

#### Why are values 0–100 instead of search volumes?

That's how Google Trends works. Values are relative interest: 100 is the peak for the chosen keyword, place and time, and 50 is half as popular. Google doesn't publish absolute search volumes in Trends. The `200K+` traffic on trending searches is Google's rough bucket.

#### Do I pay for keywords that fail?

No. If Google blocks a keyword after every retry, or returns no data, you get a free row explaining why, and nothing is charged.

#### What if one panel is missing?

You still get it, free. If Google refuses one panel even after retries, the report is delivered with the panels that worked, marked `partial`, with the missing panels listed in `missingDataTypes`, and **not charged**. A comparison is free if any panel of any keyword is missing. Partial reports are rare: a refused panel is retried on its own over fresh connections before the report gives up.

#### Why don't you return related topics?

Related topics are unavailable in this Actor; automated sessions returned empty lists in our tests. Related **queries** (top and rising) are supported.

#### Why can numbers differ slightly between runs?

Google Trends is based on a sample of searches, so repeated requests can differ by a few points, especially for small keywords. For a fair comparison, compare keywords in the same group.

#### How accurate is it?

In a short US study of 10 keywords across three ranges with five requested samples per group, 28/30 group samples succeeded. Complete-period averages had a median sample standard deviation of 0–0.021 index points across the ranges; individual points varied by up to 3.29 points. These are measurements of short-term repeatability, not an accuracy guarantee or absolute search volume. Google can return the same cached sample repeatedly. Compare keywords together and use optional sampling to inspect variation.

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

This Actor only collects public, aggregated, anonymous trend data. No personal data is involved. You're responsible for how you use the results. This is not legal advice.

#### Can I run it on a schedule?

Yes. Use Apify **Schedules** to run it daily or weekly, and connect the results to Google Sheets, Slack or email through integrations.

#### How fast is it?

In our tests, 20 keywords took 4–70 seconds: seconds when Google answers the direct connection, around a minute when it is rate-limiting and residential retries kick in. Larger lists run several keywords in parallel.

#### How do you keep costs low?

Each report first tries a direct connection (no proxy cost) and switches to rotating residential proxies only if Google refuses. If Google keeps refusing, the run goes straight to residential for the rest of the keywords. You don't need to configure anything; the price you pay is the same either way.

#### What granularity will I get?

Longer ranges return weekly or monthly points. For daily data over a long range, see **Daily Google Trends data for long ranges** above.

| Time range | Data points |
| --- | --- |
| Past hour / 4 hours | Minutes |
| Past day | ~8-minute buckets |
| Past 7 days | Hours |
| Past 30 / 90 days | Days |
| Past 12 months / 5 years | Weeks |
| 2004 – present | Months |

#### Which category IDs can I use?

Pick a category from the **Category** dropdown, or enter any Google Trends category ID (including sub-categories) in **Category ID**. Main IDs: 0 All · 3 Arts & Entertainment · 5 Computers & Electronics · 7 Finance · 11 Home & Garden · 12 Business & Industrial · 16 News · 18 Shopping · 20 Sports · 45 Health · 47 Autos & Vehicles · 67 Travel · 71 Food & Drink · 174 Games · 958 Jobs & Education.

### Limitations

- Values are relative (0–100), not absolute search volumes.
- No related topics (see FAQ).
- Ordinary comparison groups and independent runs have separate scales; anchor chaining adds an estimate within one run.
- RSS is current and country-level only. Full Trending Now also supports some subregions, including US-CA; availability varies. Neither feed provides historical backfill.
- Very small keywords may have no data in some places or periods. You get a free `no_data` row for those.

### Support and feedback

Found a problem or need a feature? Open an issue on the **Issues** tab with your run ID. We usually reply within a day or two. If this Actor saves you time, a review helps other people find it.

This is an independent tool by **SusLabs**, not affiliated with or endorsed by Google. Google Trends is a trademark of Google LLC. Technical details: output fields, statistics definitions and the billing rules are documented in the input field descriptions and in the free `_summary` row of every run.

# Changelog

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

# Actor input Schema

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

<b>Keyword trends</b>: one report per keyword (its own 0–100 scale). <b>Compare keywords</b>: up to 5 keywords on one shared scale, like the Trends compare view; longer lists are split into groups of 5 and each complete group is one result event. <b>Daily trending searches</b>: today's trending searches per country (set Country below). <b>Topic suggestions</b>: Google's topic matches for each keyword. <b>Raw explore widgets</b>: Google's widget definitions for developers, without a result event; the platform startup fee still applies.

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

One keyword per line, any number. You can also use Google topic IDs such as <code>/m/0k8z</code> for topic-level interest. Not needed for daily trending searches.

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

Country code (US, IN, GB), a region (US-CA) or a US metro code (US-NY-501). Country names like "India" or "Deutschland" also work. Leave empty for worldwide.

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

Explore-based modes (keywords, compare, explore) only. Period to analyze. For exact dates, use Start date / End date below.

## `sections` (type: `array`):

Keyword/compare reports only. Fewer panels reduce requests and can reduce infrastructure usage; the per-result price stays the same. Charged only when every selected panel is delivered; otherwise the report is free and marked partial. The first selected panel is fetched first.

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

Run every keyword (or comparison group) in each of these places, e.g. US, GB, IN. Overrides Country or region. Each place is a separate report and adds requests.

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

Keyword/compare reports only. Level of the Interest by region panel. Automatic = Google's default (countries for worldwide, states/provinces for a country). Metro (DMA) is available for the US. No extra requests.

## `regionLevels` (type: `array`):

Keyword/compare reports only. Opt in to several region panels in the same report. Each additional level costs up to one extra widget request per attempt. Requires Interest by region. Availability varies by place.

## `includeSeasonality` (type: `boolean`):

Keyword/compare reports only. Compute a monthly profile from at least two observed years (for example Past 5 years). Shorter or incomplete histories return null with a reason. Adds no requests.

## `seasonalityLeadDays` (type: `integer`):

With includeSeasonality. Days before the next heuristic peak month to suggest publishing. A planning aid, not a forecast.

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

Keyword/compare reports only. Also return regions with little search volume, like the checkbox on the Trends website.

## `includeRegionsWithNoData` (type: `boolean`):

Keyword/compare reports only. Keep regions Google marks as having no data (hasData: false). By default they are dropped and counted in regionsDroppedNoData.

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

Explore-based modes (keywords, compare, explore) only. Exact start date (YYYY-MM-DD). Overrides Time range. End date defaults to today.

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

Explore-based modes (keywords, compare, explore) only. Exact end date (YYYY-MM-DD). Requires Start date.

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

Explore-based modes (keywords, compare, explore) only. Alternative to the date pickers: <code>YYYY-MM-DD YYYY-MM-DD</code>, hourly <code>YYYY-MM-DDTHH YYYY-MM-DDTHH</code> (last 7 days only), or shortcuts like <code>Q1 2025</code>, <code>90d</code>, <code>5y</code>.

## `categoryName` (type: `string`):

Explore-based modes (keywords, compare, explore) only. Limit results to a Google Trends category, e.g. Finance or Travel. For a sub-category, use Category ID in Advanced.

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

Explore-based modes (keywords, compare, explore) only. Which Google search to analyze.

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

Language for names in the results, e.g. en-US, de, ja.

## `tz` (type: `integer`):

Explore-based modes (keywords, compare, explore) only. Shifts hourly and daily buckets. Google's convention: minutes behind UTC, so India (UTC+5:30) is -330 and New York (UTC-5) is 300.

## `trendingSource` (type: `string`):

Trending mode only. RSS returns a short current list with news and images. Full Trending Now adds hundreds of trends, growth, lifecycle and breakdown terms. Full feed tries direct access first and uses residential only after refusal.

## `trendingHours` (type: `integer`):

Full feed only: 4, 24, 48 or 168 hours (other values are rounded up). This is a current rolling feed, not historical backfill.

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

Full feed only. Filter using Google Trending Now IDs, for example \[17] for Sports. These differ from Explore category IDs. Empty = all.

## `activeOnly` (type: `boolean`):

Full feed only. Keep searches Google still marks as actively trending.

## `trendingStatus` (type: `string`):

Full feed only. Filter by activity; Only active trends also excludes ended searches.

## `trendingSort` (type: `string`):

Full feed only. Order the returned country feed before applying its item limit.

## `maxTrendsPerCountry` (type: `integer`):

Full feed only. Keep up to N matching trends from each country. 0 = all. Google sends a whole country feed; Max results prevents the next country request.

## `minSearchVolume` (type: `integer`):

Full feed only. Minimum Google volume bucket lower bound. This is approximate volume, not an exact search count.

## `trendingLanguage` (type: `string`):

Optional full feed language tag, for example en-US or de. Empty inherits Language.

## `trendingConcurrency` (type: `integer`):

Trending mode only. Countries requested simultaneously. A finite result or charge cap serializes country requests so a later country is not fetched unnecessarily.

## `chainComparisons` (type: `boolean`):

Compare mode only. Link groups with one common anchor for an estimated shared scale. N terms use ceil((N-1)/4) groups; each successful underlying group is one comparison-result event. Adds a free normalized comparison with precision flags.

## `anchorTerm` (type: `string`):

Chaining only. A searchTerms member common to each group. Empty uses the first keyword. Choose a term with measurable interest close to the other terms.

## `bridgeRemeasurement` (type: `boolean`):

Chaining only. Add preplanned groups comparing Bridge keyword with Keywords to re-measure. Each successful extra group is one comparison event. Use a weaker but measurable bridge to improve rounding precision.

## `bridgeTerm` (type: `string`):

With bridgeRemeasurement. A non-anchor keyword already included in searchTerms. Its first measurement links the extra groups to the common scale.

## `bridgeTerms` (type: `array`):

With bridgeRemeasurement. Small members of searchTerms to compare against the bridge. Exclude the anchor and bridge. Four targets per additional group; all requests are planned before work begins.

## `compareLocations` (type: `boolean`):

Explore-based modes (keywords, compare, explore) only. Put one keyword in 2–5 places (from Several countries or regions) on one shared scale.

## `comparePeriods` (type: `boolean`):

Explore-based modes (keywords, compare, explore) only. Put one keyword in 2–5 equal-length periods (below) on one shared scale, e.g. this year vs last year.

## `periods` (type: `array`):

With comparePeriods. One period per line, all the same length: <code>2024-01-01 2024-03-31</code>.

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

Explore-based modes (keywords, compare, explore) only. Paste explore URLs from trends.google.com. Keywords, country, dates, category and search type are read from each URL.

## `advancedQueries` (type: `array`):

Keyword/compare modes only; incompatible with chaining and location/period comparisons. Optional list of {terms, geo, timeRange, property, category}. Each terms array contains 1–5 keywords sharing a scale. Overrides the shared settings per query. Normal report/group pricing and run limits apply.

## `spreadsheetId` (type: `string`):

Term-based modes only (keywords, compare, autocomplete, explore). Imports run on Apify. ID of a public Google Sheet. Keywords are read from the first column; the first row is treated as a header.

## `urlsFromFile` (type: `string`):

Term-based modes only (keywords, compare, autocomplete, explore). Imports run on Apify. Public HTTPS link to a .txt or .csv file; keywords are read from the first column.

## `fileHasHeader` (type: `boolean`):

With urlsFromFile. Skip the first row of the keyword file.

## `outputFormat` (type: `string`):

<b>Nested</b>: one row per keyword report (best for JSON/API). <b>Flat</b>: one row per data point, region and related query plus a report row (best for CSV/Excel). Extra flat rows are never charged.

## `compactOutput` (type: `boolean`):

Keep summary stats (average, peak, direction, top regions, breakouts) and drop the long arrays. Smaller and token-cheap.

## `excludeEmptyFields` (type: `boolean`):

Remove null values and empty lists from results.

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

Stop after this many report tasks, comparison groups or trending items. Attempted failed/unchanged reports also use a slot. Extra flat rows are free and outside the cap. Stable sampling and daily estimates count as one task each but can use several events (N samples, or 1 + delivered windows). 0 = no limit.

## `maxQueries` (type: `integer`):

Only process the first N planned reports (keywords × places, groups, or trending countries). 0 = all.

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

Keyword/compare reports only. Keep only the top N regions. 0 = all.

## `maxRelatedItems` (type: `integer`):

Keyword/compare reports only. Keep only the first N top and rising queries. 0 = all.

## `maxRunSeconds` (type: `integer`):

Stop starting requests or new reports after this many seconds; active requests finish. 0 = no limit.

## `separateDatasets` (type: `boolean`):

Copy free timeline, region, related and trending rows to run-scoped unnamed datasets using aliases. Their IDs appear in the summary. They follow account retention for unnamed storages; no permanent global names are created.

## `monitorMode` (type: `boolean`):

Compare successful results with a named monitor snapshot. NEW and UPDATED results use the normal event; UNCHANGED and EXPIRED rows are free. Schedule this input to monitor changes.

## `monitorName` (type: `string`):

Required with monitoring, up to 100 characters. Use a different name per task (for example per schedule) so tests and production never share state.

## `monitorSensitivity` (type: `string`):

Monitoring only. How big a move has to be before a keyword counts as UPDATED (charged) instead of UNCHANGED (free). Normal ignores moves up to the larger of 12 points or 15%; low 16 points/25%; high 3 points/5%, which also reports ordinary sampling noise. Newly completed periods always count. New rising/Breakout queries count after a second check (normal: at least 1 hour later).

## `monitorRetentionHours` (type: `integer`):

Monitoring only. Snapshot entries unseen for this many hours expire when their query scope is next checked. Named storage persists under your Apify retention settings; run the monitor again to prune stale entries.

## `resetMonitoringState` (type: `boolean`):

Monitoring only. Treat the scopes in this run as new and overwrite their snapshots. Turn off after a single reset run. Does not delete an Apify store.

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

Monitoring only. Suppress previously seen results, including updates. Only newly observed results are delivered and charged.

## `onlyChanges` (type: `boolean`):

Monitoring only. Deliver NEW or UPDATED reports and free expiration notices; suppress unchanged reports.

## `cachedResultOnRefusal` (type: `boolean`):

Keyword/compare reports only. Save complete successful reports and, after an upstream refusal, deliver a recent verified snapshot marked CACHED with its age. Cached delivery is always free.

## `cacheName` (type: `string`):

Required with saved results, up to 100 characters. Separate from the monitor name; reuse it in later scheduled runs of the same task.

## `cacheMaxAgeHours` (type: `integer`):

Up to 24 hours. Short ranges enforce smaller limits: past hour 15 minutes, 4 hours 1 hour, day 6 hours, week 12 hours. Older results never replace a refusal.

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

Google Trends rate-limits aggressively. Residential proxies (default) are strongly recommended.

## `viewedFrom` (type: `string`):

Country the requests come from (e.g. US). Independent of the country being analyzed. Setting it turns off "Try a direct connection first", so every request really leaves from this country.

## `useProxy` (type: `boolean`):

Turn off only for tiny tests. Without a proxy Google blocks quickly.

## `dailyResolution` (type: `boolean`):

Opt-in for separate keyword timelines longer than 270 days. Fetches the normal coarse report plus N overlapping 240-day windows (21-day overlap): N+1 underlying reports, at least 3(N+1) HTTP requests for timeline-only and up to N+1 normal keyword-result charges per keyword. Daily windows have more points, so transfer cost need not follow the request-count multiplier. A year needs 2 windows plus baseline; 5 years about 9; 2004–present about 38 (up to 39 charges per keyword). Each usable fitted window is one normal event; failures are free. Full event budget reserved first. Returns dailySeries estimates on the coarse scale, possibly above 100. Requires timeline, no comparisons, sampling, monitors or cache.

## `sampleCount` (type: `integer`):

1 = normal. 2–5 repeat the whole keyword/comparison request on fresh rotating residential connections. Up to N times the requests and normal report/group event charges, one per individually complete sample. Failed or incomplete samples are free. Reserves the full N-event budget before work. Not combined with extra region levels, period comparison or direct-first.

## `sampleAggregation` (type: `string`):

With sampleCount above 1. Mean averages measured numeric values; consensus chooses the most frequent value (first sample breaks ties). Both include point standard error and agreement. Related lists use the most frequent complete panel.

## `directFirst` (type: `boolean`):

Each report first tries Apify's own connection (no proxy cost) and switches to rotating residential proxies if Google refuses. After 3 refusals in a row the run uses residential only. Measured on 5×20 keywords: median $0.17 vs $0.43 per 1,000 keywords, same delivery. Turned off automatically for sampling, a proxy exit country or custom proxies.

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

How many reports run at the same time.

## `maxRetries` (type: `integer`):

Each retry uses a fresh IP address and cookie.

## `retryCooldownSecs` (type: `integer`):

Rate-limited reports get one more try at the end of the run after this pause.

## `circuitBreakerFailures` (type: `integer`):

Stop starting new reports after this many consecutive failures. 0 = never.

## `requestTimeoutSecs` (type: `integer`):

Timeout for each HTTP request.

## `requestDelayMs` (type: `integer`):

Pause before every request. Usually unnecessary; increases run time.

## `rotateAfterRequests` (type: `integer`):

Start a fresh cookie and token after N data requests (minimum 2). 0 = off.

## `categoryId` (type: `integer`):

Explore-based modes (keywords, compare, explore) only. Numeric Google Trends sub-category, for example 7 = Finance. API clients may also send category as an integer or numeric string. A named category takes precedence.

## `failOnErrors` (type: `boolean`):

Useful for scheduled runs with alerts. Results and diagnostics are still saved.

## `saveDebugPages` (type: `boolean`):

Store redacted raw Google responses in the key-value store (DEBUG-\*). No cookies or tokens are saved.

## Actor input object example

```json
{
  "mode": "compare",
  "searchTerms": [
    "ChatGPT",
    "Gemini",
    "Claude"
  ],
  "geo": "US",
  "timeRange": "today 12-m",
  "sections": [
    "interestOverTime",
    "interestByRegion",
    "relatedQueries"
  ],
  "regionResolution": "auto",
  "regionLevels": [],
  "includeSeasonality": false,
  "seasonalityLeadDays": 30,
  "includeLowVolumeRegions": false,
  "includeRegionsWithNoData": false,
  "property": "",
  "language": "en-US",
  "tz": 0,
  "trendingSource": "rss",
  "trendingHours": 24,
  "trendingCategories": [],
  "activeOnly": false,
  "trendingStatus": "all",
  "trendingSort": "relevance",
  "maxTrendsPerCountry": 0,
  "minSearchVolume": 0,
  "trendingLanguage": "",
  "trendingConcurrency": 1,
  "chainComparisons": false,
  "anchorTerm": "",
  "bridgeRemeasurement": false,
  "bridgeTerm": "",
  "bridgeTerms": [],
  "compareLocations": false,
  "comparePeriods": false,
  "advancedQueries": [],
  "fileHasHeader": false,
  "outputFormat": "nested",
  "compactOutput": false,
  "excludeEmptyFields": false,
  "maxItems": 0,
  "maxQueries": 0,
  "maxRegions": 0,
  "maxRelatedItems": 0,
  "maxRunSeconds": 0,
  "separateDatasets": false,
  "monitorMode": false,
  "monitorSensitivity": "normal",
  "monitorRetentionHours": 168,
  "resetMonitoringState": false,
  "onlyNew": false,
  "onlyChanges": false,
  "cachedResultOnRefusal": false,
  "cacheMaxAgeHours": 24,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "useProxy": true,
  "dailyResolution": false,
  "sampleCount": 1,
  "sampleAggregation": "mean",
  "directFirst": true,
  "maxConcurrency": 5,
  "maxRetries": 6,
  "retryCooldownSecs": 15,
  "circuitBreakerFailures": 0,
  "requestTimeoutSecs": 30,
  "requestDelayMs": 0,
  "rotateAfterRequests": 0,
  "categoryId": 0,
  "failOnErrors": false,
  "saveDebugPages": false
}
```

# Actor output Schema

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

All dataset rows: keyword reports, comparison groups, trending searches, free status rows and the end-of-run \_summary row. Filter type != '\_summary' and type != 'status' for data only.

## `overview` (type: `string`):

Report/member statistics: average and peak interest, direction, change %, top region and summary. This projection can include free status/summary rows; comparison members are informational and group billing belongs to the outer JSON envelope.

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

What was delivered, what failed and why, how many results were charged, and why the run stopped.

## `insights` (type: `string`):

Compact statistics per keyword (average, min, peak, slope, change %), ideal for AI agents and dashboards.

## `errors` (type: `string`):

Failed and partial reports with error codes and missing panels. Missing requested base panels are free; a partial daily estimate can still charge for its complete baseline and usable windows.

## `failedKeywords` (type: `string`):

Legacy arrays of keyword/geo/time job members. These are diagnostics, not Actor inputs. Use Retry inputs for runnable inputs.

## `retryInputs` (type: `string`):

An array of standalone Actor input objects for undelivered jobs. Copy one object into a new run; reselect your own proxy credentials if needed.

## `namedDatasets` (type: `string`):

Run-scoped dataset IDs and item URLs created by separateDatasets; an empty object when that option is off.

# 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 = {
    "mode": "compare",
    "searchTerms": [
        "ChatGPT",
        "Gemini",
        "Claude"
    ],
    "geo": "US",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("suslabs/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 = {
    "mode": "compare",
    "searchTerms": [
        "ChatGPT",
        "Gemini",
        "Claude",
    ],
    "geo": "US",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

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

```

## MCP server setup

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