# Google Trends Scraper: Multi-Keyword & Regions (`olliolli/google-trends-batch`) Actor

Compare Google Trends keywords with shared-anchor scaling. Get regional interest and Trending Now RSS, or monitor search-interest spikes. No Google login.

- **URL**: https://apify.com/olliolli/google-trends-batch.md
- **Developed by:** [Tom J](https://apify.com/olliolli) (community)
- **Categories:** SEO tools
- **Stats:** 2 total users, 1 monthly users, 85.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 keyword 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 Batch** compares search interest for a company’s keyword list, reads regional interest and Trending Now RSS, and monitors spikes. No Google login or source API key is required. Use it for SEO research, content planning, market comparisons and scheduled search-interest alerts.

### What you can do

- Compare up to 100 keywords using classic public Trends widgets and a shared anchor.
- Request timelines, regional/city interest, related queries and topics where the source exposes them. A missing requested section is reported as a failed keyword, not silently omitted from a paid result.
- Read Trending Now RSS for a country, with a timestamp window and row cap.
- Monitor the last complete period against the preceding four weeks, deduplicating alerts by keyword/settings/date.

### How to use it in 3 steps

1. Enter keywords and a country, or choose `trendingNow`.
2. Choose requested sections and a small output scope.
3. Run and inspect OUTPUT, not only the run status. Export the dataset through Apify.

```json
{"mode":"keywords","keywords":["coffee","tea","chocolate"],"geo":"BE","timeRange":"today 12-m","include":["timeline"]}
```

```json
{"mode":"trendingNow","trendingCountry":"BE","trendingHours":24,"trendingMaxItems":10}
```

### Input

Keywords: at most 100 distinct terms. `geo` is empty for worldwide or a country/subregion. `timeRange` supports standard Trends windows; `customRange` accepts two ISO dates. `property` supports web, images, news, youtube and froogle (shopping). `include` supports timeline, regions, cities, relatedQueries and relatedTopics; timeline is always fetched for alignment.

For monitoring, set `mode: monitor`, a unique `stateName`, `spikeThreshold` (default 50 percent) and an optional webhook. Use a sufficiently long range, usually `today 3-m` or `today 12-m`. Short or monthly series may lack a four-week baseline and generate a diagnostic instead of a spike.

Default limits: 600 seconds, 500 HTTP requests, sequential requests at least one second apart, and at most three connection attempts. Browser bootstrap is only available on the last network-error recovery attempt. Default memory: 1 GB.

### Output

Keyword rows contain the term, geography, range, granularity, raw timeline and anchor-aligned `valueScaled`, averages, anchor/group, requested sections and a Trends URL. Monitor rows additionally contain the percentage change and last complete date. Trending rows include term, RSS order, published traffic label, timestamp and news headline/source/link. No article bodies or authors are collected.

OUTPUT records completed/failed/unchecked keywords, delivered rows, connection attempts, safe error reasons, recovery actions, event counts and stop reasons. An empty result does not establish that nobody searches for the term.

### Scaling multiple keyword groups

Each classic widget request contains at most five terms. The first successful group supplies the automatic anchor: the term with the highest mean interest within that group. This is not a global popularity ranking. An explicit `anchorKeyword` can instead be supplied.

Subsequent groups contain that anchor and up to four more terms. At each common timestamp, multiply raw values by reference-anchor / current-anchor. If either anchor rounds to zero, use the ratio of means from overlapping positive, complete anchor intervals. If no usable overlap exists, the group fails. Missing intervals are not invented.

In a small live check on 25 October 2026, four cross-group keyword/anchor ratios differed from a separate Google UI sample by approximately 1.7–4.5% on average across completed periods; individual differences reached 20%. This is an observed example, not an accuracy guarantee.

Scaled values share the reference group's scale and **can exceed 100**. They are estimates affected by rounding, sampling and independent request normalization, not exact search volumes. Geography values retain their own source scales and are not comparable as absolute regional search counts. Google’s newer interface may support different comparison limits; this Actor uses the classic widget format it actually receives.

### How much does it cost?

Pay per delivered result, at the following base prices:

| Event | USD |
|---|---:|
| Delivered keyword result, including requested sections | 0.004 |
| Delivered Trending Now row | 0.001 |
| Residential session, once after the first delivered residential keyword | 0.03 |
| Standard start, per allocated GB, minimum one | 0.00005 |

At 1 GB, 10 keyword rows through datacenter cost $0.04005; with the residential event, $0.07005. Ten trending rows cost $0.01005. The active Apify pricing table is authoritative. No automatic dataset-item event should be enabled.

#### What you are not charged for

No keyword-result charge for failed, empty, unaligned or incomplete requested results; no keyword charge when monitor produces no new spike. No residential event before a keyword row is delivered. The start event still applies to failed runs. A zero-output run is therefore not necessarily free.

### Automate and schedule

Use an Apify task/schedule with a fixed stateName for monitor mode. Do not overlap runs against the same state. A repeated alert for the same completed interval is suppressed; changing the threshold or comparison settings establishes a separate alert scope. Webhook failure is reported and not automatically retried; use your dataset as the authoritative delivered output.

### Good to know

Public Google Trends interfaces are unofficial and can change or block requests. Rate limits, access blocks and CAPTCHA pages stop the session/run without IP escalation. Network/temporary-server failures may use bounded residential recovery; there is no unlimited rotation. No personal browser profile, Google login or CAPTCHA solving is used.

RSS is a limited current feed: 4/24/48/168-hour settings only filter available feed timestamps. They do not reconstruct missing history. Category filtering and related terms are unavailable in RSS; category input is rejected rather than pretending to filter it. The RSS order is not a verified popularity ranking.

### Privacy

Only supplied search terms and public aggregated trend fields are processed. No Google account data, browsing history, cookies, headers or raw exception fragments are persisted. Anonymous session cookies remain in memory. Monitor state stores a hashed settings key and last delivered alert date. A supplied webhook receives keyword/geography/spike summaries.

### FAQ

#### Are these search volumes?

No. Google Trends measures sampled, relative search interest. Raw values are 0–100 within the source request; anchor-scaled values use the reference group’s scale.

#### Why did Google return 429?

The source rate-limited the session. This Actor stops instead of switching IPs to continue that blocked session.

#### Why is a keyword missing?

Check OUTPUT: insufficient volume, blocked access, missing requested widgets and response format changes are separate reasons. None is silently turned into a paid empty row.

#### Can I compare cities worldwide?

City availability varies by geography and source widget. A missing widget fails the affected result. A valid source response can contain only zero-valued cities or empty related lists; these mean no reportable detail, not proof of zero demand. Such sections are preserved with a valid paid keyword timeline. Try regions or a country-specific input.

#### Why is there no spike alert?

The latest complete value may be below the threshold, already alerted, or lack a sufficiently long nonzero baseline. Partial current periods are excluded.

#### Is this an official Google API?

No. It reads public web-app interfaces and RSS; access and response formats are not guaranteed.

### Disclaimer

Independent tool, not affiliated with Google. A research aid, not certified search-volume data or polling. Respect source terms and your rights to process supplied terms and output.

### Need help?

Provide the run ID, safe OUTPUT reason and a non-sensitive sample input. Do not share proxy credentials, cookies or private webhook tokens.

### Integrate with your application

Python (Apify client):

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('olliolli/google-trends-batch').call(
    run_input={'keywords': ['coffee', 'tea'], 'geo': 'BE'},
    memory_mbytes=1024,
    timeout_secs=180,
)
rows = client.dataset(run['defaultDatasetId']).list_items().items
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('olliolli/google-trends-batch').call({
  keywords: ['coffee', 'tea'], geo: 'BE'
}, { memory: 1024, timeout: 180 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Your Apify token authenticates your platform call; it is not a Google account credential. Use the returned key-value-store OUTPUT diagnostics alongside dataset rows.

### MCP and agent workflows

An Apify-compatible MCP integration can invoke the Actor with the same structured input when your account has access. This Actor does not expose its own standalone MCP server. Keep the keyword list and run limits small in unattended workflows.

### Source references

- [Google Trends data: sampling and normalization](https://support.google.com/trends/answer/4365533?hl=en)
- [Google Trending Now and RSS export](https://support.google.com/trends/answer/3076011?hl=en)
- [Google Trends API alpha](https://developers.google.com/search/apis/trends): a separate, access-controlled official service; it is not bundled with this Actor.

# Actor input Schema

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

Mode.

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

Up to 100 terms. Terms are compared in groups with a shared anchor; low volumes may be unavailable.

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

Empty means worldwide; use BE, US, or a region such as BE-VLG.

## `anchorKeyword` (type: `string`):

Stable, sufficiently popular term shared across comparison groups. Otherwise chosen from the first successful group.

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

Time range.

## `customRange` (type: `string`):

YYYY-MM-DD YYYY-MM-DD, overrides time range.

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

Google Trends category.

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

Search property.

## `include` (type: `array`):

timeline, regions, cities, relatedQueries, relatedTopics. Missing requested sections fail the keyword without charging. Timeline is always included for scaling.

## `trendingCountry` (type: `string`):

Trending country.

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

Use 4, 24, 48 or 168 hours. Filters timestamps in the current RSS feed; does not provide exhaustive historical coverage.

## `trendingMaxItems` (type: `integer`):

Maximum trending rows.

## `spikeThreshold` (type: `integer`):

Spike threshold (%).

## `stateName` (type: `string`):

Required for monitor. Avoid overlapping runs; only public term/settings and latest alert timestamps are stored.

## `webhookUrl` (type: `string`):

One POST with spike summaries. Public HTTPS recommended; redirects are not followed. Keep private tokens out of shared input.

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

Language.

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

Apify datacenter by default. At most three connection attempts; no IP switching after a 429, CAPTCHA or access block.

## `residentialFallback` (type: `boolean`):

Only for connection/temporary server errors. $0.03 once per run after the first delivered residential keyword result. No fallback after access blocks.

## `browserFallback` (type: `boolean`):

One anonymous browser bootstrap on the third network-error attempt; no user cookies, login or CAPTCHA solving.

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

Run time limit.

## `maxRequests` (type: `integer`):

Request cap.

## Actor input object example

```json
{
  "mode": "keywords",
  "keywords": [
    "coffee",
    "tea",
    "chocolate"
  ],
  "geo": "BE",
  "timeRange": "today 12-m",
  "category": 0,
  "property": "web",
  "include": [
    "timeline"
  ],
  "trendingCountry": "BE",
  "trendingHours": 24,
  "trendingMaxItems": 50,
  "spikeThreshold": 50,
  "language": "en-US",
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "residentialFallback": true,
  "browserFallback": true,
  "maxRunSeconds": 600,
  "maxRequests": 500
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `diagnostics` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "coffee",
        "tea",
        "chocolate"
    ],
    "geo": "BE"
};

// Run the Actor and wait for it to finish
const run = await client.actor("olliolli/google-trends-batch").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": [
        "coffee",
        "tea",
        "chocolate",
    ],
    "geo": "BE",
}

# Run the Actor and wait for it to finish
run = client.actor("olliolli/google-trends-batch").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "coffee",
    "tea",
    "chocolate"
  ],
  "geo": "BE"
}' |
apify call olliolli/google-trends-batch --silent --output-dataset

```

## MCP server setup

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

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/a2I4XXvcy9WrvLqLp/builds/xY9eXeftbYKyS2y4Y/openapi.json
