# Google Trends Scraper (`munin/google-trends-scraper`) Actor

Search interest over time, by region, plus related queries and what is trending now. Rotates sessions so rate limits do not fail your run. Charges only for rows it delivers.

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

## Pricing

$1.00 / 1,000 item delivereds

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

Search interest over time, interest by region, related queries and what is trending right now — as
clean rows you can put straight into a sheet, a database or a dashboard. No Google account, no API key.

**It does not fail when Google rate-limits you.** That is the whole point of this actor. Google Trends
answers `429 Too Many Requests` to anything that has not first picked up a session cookie, and it goes
back to `429` when a session gets stale. Most Trends scrapers treat that as an error and hand you a
failed run. This one opens a fresh session and carries on, so a rate limit costs you a few seconds
instead of your run.

### What you get

| Data | What a row looks like |
|---|---|
| **Interest over time** | one row per keyword per data point: `date`, `value` (0-100), `isPartial` |
| **Interest by region** | one row per keyword per region: `regionCode`, `regionName`, `value` |
| **Related queries** | top and rising searches around your keyword, with `rank` and `value` |
| **Trending now** | what is being searched right now in a country, with `approxTraffic` and the news stories behind it |

Every row carries `keyword`, `geo`, `timeRange`, `category`, `property` and `scrapedAt`, so results
from different runs stack in one table without you having to remember what each run asked for.

### What it costs

**$0.001 per row delivered.** You are charged for rows that actually land in your dataset and for
nothing else — not for the run starting, not for compute, not for failed keywords. A year of weekly
data for one keyword is 53 rows, about $0.05.

### Use it for

- **SEO and content planning** — which of your topics is growing, which is flat, which is seasonal.
- **Demand forecasting** — pull 5 years of weekly data for a product category and find the yearly shape.
- **Market entry** — compare interest across countries before deciding where to launch.
- **Newsroom and social monitoring** — poll *Trending now* for your markets and get the stories behind each spike.
- **Brand tracking** — put your brand and your competitors on one shared 0-100 scale.

### Input

```json
{
  "searchTerms": ["air fryer", "pizza oven"],
  "geos": ["US", "GB"],
  "timeRange": "today 12-m",
  "outputs": ["interestOverTime", "interestByRegion", "relatedQueries"],
  "trendingNowGeos": ["US"]
}
```

Every term is fetched for every geo. Leave `geos` as `[""]` for worldwide. Set `compareAsOneChart`
to `true` to put your terms on one shared scale, the way the Compare tab on Google Trends works
(Google allows 5 terms per comparison, so longer lists are split into groups of 5).

Time ranges: `now 1-H`, `now 4-H`, `now 1-d`, `now 7-d`, `today 1-m`, `today 3-m`, `today 12-m`,
`today 5-y`, `all`, or your own `2024-01-01 2024-12-31` in `customTimeRange`.

`category` narrows an ambiguous word (for example `47`, Autos & Vehicles, for *jaguar*).
`property` switches the surface: web, images, news, Google Shopping or YouTube search.

### Output

```json
{
  "type": "interest_over_time",
  "keyword": "air fryer",
  "comparison": "air fryer",
  "date": "2026-09-13",
  "timestamp": 1757808000,
  "formattedTime": "Sep 13 – 19, 2026",
  "value": 78,
  "isPartial": false,
  "geo": "US",
  "timeRange": "today 12-m",
  "category": 0,
  "property": "web",
  "scrapedAt": "2026-09-19T09:12:03.221Z"
}
```

Values are Google's own 0-100 index, not search counts: 100 is the peak of the series you asked for.
Two separate runs are not comparable unless you asked for the same period and geo, which is why every
row repeats those fields.

### What it cannot do

- **Related topics is not offered.** Google's public endpoint returns an empty list for it on this
  access path for every keyword we tested, and the request is signed, so it cannot be asked for a
  different way. Related *queries* works and is what you want in almost every case.
- **No search volumes.** Google Trends does not publish them, so nobody can scrape them. Rows are the
  0-100 relative index. If you need absolute volumes you need a keyword tool, not Trends.
- **Hourly data only goes back 7 days**, daily back 90 days. Ask for longer and Google returns weekly
  points. This is Google's rule, not ours.
- **The most recent point is partial.** It is flagged `isPartial: true` — drop it if you are plotting
  a trend line, because it is a part-week compared against full weeks.
- **A keyword with too little search volume returns no rows.** That is an answer, not a failure: the
  run finishes normally and reports it.
- **Datacenter IPs do not work.** Residential proxy is on by default. Turn it off and Google will
  refuse almost everything.
- **Trending now is per country**, uses Google's own country lists, and returns roughly the last day.

### Failed inputs

If a keyword cannot be fetched, the run does not stop. The other keywords are still delivered, and the
failed one is written to the dataset as a row with `success: false` and the reason — free of charge,
so you can see exactly what did not arrive.

# Actor input Schema

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

Terms to measure search interest for. One row per term per data point. Leave empty if you only want the "Trending now" lists below.

## `compareAsOneChart` (type: `boolean`):

Off (default): every term is measured on its own scale, so numbers stay comparable across runs. On: terms are put on one shared 0-100 scale, the way the Compare tab on Google Trends works. Google allows 5 terms per comparison, so longer lists are split into groups of 5.

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

ISO codes such as US, GB, JP, DE-BY, US-CA. Use an empty string for worldwide. Every term is fetched for every entry here.

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

The period to measure. Weekly points for a year or more, daily for 90 days or less, hourly for 7 days or less.

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

Overrides the dropdown above. Format: YYYY-MM-DD YYYY-MM-DD, for example 2024-01-01 2024-12-31.

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

Google Trends category ID, 0 for all categories. Useful when a word means two things, for example 47 (Autos & Vehicles) for "jaguar".

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

Which Google surface the search interest comes from.

## `outputs` (type: `array`):

Related topics is not offered. Google's public endpoint returns it empty for every keyword on this access path, and we do not fake data.

## `geoResolution` (type: `string`):

Only applies to "Interest by region". Auto uses states or regions when you picked a country, and countries when you picked worldwide.

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

Returns what is searched right now in each country, with the news stories behind each one. Independent of the search terms above.

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

Language of region names and related queries, as a locale like en-US or ja.

## `timezoneOffsetMinutes` (type: `integer`):

Shifts which local day an hourly or daily data point falls in. 0 is UTC.

## `maxItemsPerSource` (type: `integer`):

0 means no limit.

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

Hard stop for the whole run, so you can cap what you spend. 0 means no limit.

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

Higher is faster but meets Google's rate limit sooner. The run recovers from rate limits on its own; this only changes how often it has to.

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

Google Trends refuses datacenter traffic on most endpoints. Residential proxy is the default and is what makes the run succeed.

## Actor input object example

```json
{
  "searchTerms": [
    "air fryer",
    "pickleball"
  ],
  "compareAsOneChart": false,
  "geos": [
    "US"
  ],
  "timeRange": "today 12-m",
  "category": 0,
  "property": "web",
  "outputs": [
    "interestOverTime",
    "relatedQueries"
  ],
  "geoResolution": "auto",
  "trendingNowGeos": [
    "US",
    "JP"
  ],
  "language": "en-US",
  "timezoneOffsetMinutes": 0,
  "maxItemsPerSource": 0,
  "maxItems": 0,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `rows` (type: `string`):

Every row with every field, including the keyword, geo and time range each row came from.

## `rowsCsv` (type: `string`):

The same rows as a spreadsheet: type, keyword, date, interest value, region, related query, rank and geo.

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

The dataset in the Apify console, with the table view.

# 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",
        "ethereum"
    ],
    "geos": [
        "US"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("munin/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",
        "ethereum",
    ],
    "geos": ["US"],
}

# Run the Actor and wait for it to finish
run = client.actor("munin/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",
    "ethereum"
  ],
  "geos": [
    "US"
  ]
}' |
apify call munin/google-trends-scraper --silent --output-dataset

```

## MCP server setup

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