# Google Trends Scraper - Trends & Keywords (`ziomixshot/google-trends-scraper`) Actor

Analyze Google Trends keywords, compare terms, collect Trending Now data, and monitor stable trend changes for research, SEO, automation, and AI workflows.

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

## Pricing

from $0.75 / 1,000 trend reports

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 - Trends & Keywords

Analyze keyword interest, compare search terms on one shared scale, collect
current Trending Now searches, or monitor stable changes between runs. The
Actor returns compact, typed results for Apify Console, API, exports, and AI
agents using Apify MCP.

Google Trends Scraper uses live Google Trends data. It is not affiliated with
or endorsed by Google.

### Quick start

1. Choose **Analyze keywords**, **Compare terms**, **Trending now**, or
   **Monitor changes**.
2. Enter search terms or a country, depending on the selected mode.
3. Set **Maximum result rows** to control output and product charges.
4. Click **Start**.
5. Open **All results**, a mode-specific view, or the machine-readable run
   summary.

An empty API input runs one bounded demo report for `Google`; it never starts a
large crawl.

### Ready-to-use recipes

#### Analyze keywords

Each keyword produces one report when at least one selected data surface has
data. Empty surfaces are explicit in `missingDataTypes`; all-empty results and
technical failures remain free.

```json
{
    "mode": "analyze",
    "searchTerms": ["ChatGPT", "/m/0dl567"],
    "dataTypes": ["timeline", "regions", "relatedQueries", "suggestions"],
    "timeframe": "today 12-m",
    "geo": "US",
    "maxItems": 2
}
```

Literal phrases and Google topic IDs are both supported. Topic IDs can aggregate
spellings and languages more consistently than literal search terms.

#### Compare two to five terms

All terms share one Google Trends request and one relative `0–100` scale.

```json
{
    "mode": "compare",
    "searchTerms": ["ChatGPT", "Claude", "Gemini"],
    "timeframe": "today 12-m",
    "geo": "US",
    "searchProperty": "web"
}
```

Do not compare scores from separate runs as if they were absolute search
volumes. Changing any term can rescale every series.

#### Collect Trending Now searches

RPC supplies ranked growth and relative-volume metrics. RSS supplies ranked
searches with approximate traffic and news articles. The Actor fetches both by
default, preserves each source's metrics, and deduplicates exact normalized
titles.

```json
{
    "mode": "trending",
    "geo": "PL",
    "language": "pl-PL",
    "trendingSources": ["rpc", "rss"],
    "trendingWindow": 8,
    "maxItems": 50
}
```

When a small limit is used with both sources, shared rows are returned first,
then RPC-only and RSS-only rows are interleaved. `rpc.rank` and `rss.rank`
preserve the source positions.

#### Monitor Trending Now changes

Monitoring compares one stable Trending Now population between runs. The first
complete run creates a free baseline. Later runs return only `NEW`, `UPDATED`,
and `ENDED` records; a run without stable changes returns a free `NO_CHANGES`
status.

```json
{
    "mode": "monitor",
    "monitorId": "pl-daily",
    "geo": "PL",
    "language": "pl-PL",
    "trendingSources": ["rpc", "rss"],
    "trendingWindow": 8,
    "maxItems": 50
}
```

Keep `monitorId`, `geo`, `language`, `trendingSources`, `trendingWindow`, and
`maxItems` unchanged between runs. A scope change intentionally creates an
independent baseline. For automation, save this input as an Actor Task and run
it from an Apify Schedule with `isExclusive: true`. Do not overlap manual and
scheduled runs of the same monitor.

One complete population turnover can emit at most `2 × maxItems` paid changes.
At `maxItems: 50`, the maximum user charge is
`100 × $0.00055 = $0.055`. Set the Schedule or run maximum charge accordingly.
Baseline and no-change runs have no product-event charge.

#### Reuse a Google Trends URL

Paste an Explore or Trending Now URL as an advanced alternative to structured
fields. Each URL owns its complete query and conflicting structured fields are
ignored.

```json
{
    "startUrls": [
        "https://trends.google.com/trends/explore?date=today%2012-m&geo=PL&q=Google,ChatGPT"
    ]
}
```

Up to 50 URLs can be processed sequentially. Explore URLs with one term create
analysis reports; two to five terms create comparison reports.

#### Call the synchronous API

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/ziomixshot~google-trends-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "analyze",
    "searchTerms": ["Google"],
    "dataTypes": ["timeline", "regions"],
    "geo": "US",
    "maxItems": 1
  }'
```

For longer runs, start the Actor asynchronously and paginate the default
dataset.

#### Use the Actor through Apify MCP

AI agents should follow this sequence:

1. Fetch Actor details to inspect the current input and output schemas.
2. Call the Actor with structured input.
3. Read the returned dataset ID with `get-dataset-items`.
4. Read `OUTPUT` when counters, route usage, or final run status are needed.

`call-actor` returns run and storage identifiers, not dataset rows.
Use `"searchProperty": "web"` for Web Search. The legacy empty value remains
accepted for existing integrations.
For monitoring, an agent must reuse the same `monitorId` and scope, wait for one
run to finish before starting another, and treat `ENDED` as leaving the
configured top-N population rather than the end of global interest.

### Input reference

| Field             | Purpose                                                                    |
| ----------------- | -------------------------------------------------------------------------- |
| `mode`            | `analyze`, `compare`, `trending`, or `monitor`.                            |
| `searchTerms`     | One to 50 terms for analyze; two to five for compare.                      |
| `dataTypes`       | Analyze surfaces: timeline, regions, related queries, and suggestions.     |
| `maxItems`        | Hard cap for paid reports or deduplicated trending rows.                   |
| `timeframe`       | Google preset or `YYYY-MM-DD YYYY-MM-DD` UTC range.                        |
| `geo`             | Country, region, or empty worldwide scope; RSS requires a country.         |
| `language`        | Google interface language such as `en-US` or `pl-PL`.                      |
| `category`        | Numeric Google Trends category; `0` means all categories.                  |
| `searchProperty`  | `web`, `images`, `news`, `youtube`, or `froogle`; legacy `""` is accepted. |
| `resolution`      | Country, region, or city granularity for regional interest.                |
| `trendingSources` | RPC metrics, RSS articles, or both.                                        |
| `trendingWindow`  | Verified RPC values: `4`–`10` plus `12`; `11` is rejected.                 |
| `monitorId`       | Lowercase slug identifying one independent monitor.                        |
| `startUrls`       | Up to 50 copied Google Trends Explore or Trending URLs.                    |

Related queries need a range of at least seven days. Invalid combinations fail
before a Google request is sent. `startUrls` cannot be combined with
`mode: "monitor"`.

### Output contract

Every default-dataset item has a `recordType` discriminator:

- `trendReport` - one keyword analysis, with explicit partial metadata when needed;
- `comparisonReport` - one comparison on a shared scale;
- `trendingResult` - one deduplicated current trend;
- `trendChange` - one `NEW`, `UPDATED`, or `ENDED` monitoring event;
- `status` - a free baseline, no-change, no-data, preservation, or error row.

All successful records include `operationId`, `fetchedAt`, and provenance with
the direct or residential route and attempt count. The run summary in `OUTPUT`
contains final status, counters, retry usage, free status counts, and charged
event counts. `CRAWL_STATE` supports safe platform migration and resume without
reprocessing completed operations.

Every timeline point includes `isPartial`. A value of `true` means Google marked
the current time bucket as incomplete, so its score must not be interpreted as
a finished-period decline. Analyze status rows include `keyword` so no-data and
error results remain attributable in multi-keyword runs.

Every analysis report also includes top-level `isPartial` and
`missingDataTypes`. Region rows preserve Google's localized `label` plus
`geoCode` for country/region rows or `coordinates` for city rows when Google
returns them. Related queries expose raw numeric `value`, localized
`formattedValue`, and locale-independent `isBreakout`; the legacy `breakout`
text remains for compatibility.

Trending rows deliberately keep RPC and RSS in separate nested objects because
their `traffic` fields have different meanings. `isPartial: true` means a
selected source failed; a row that naturally appears in only one successful
source is not a transport failure.

A `trendChange` contains top-level identity fields plus nullable `previous` and
`current` states and `changedFields`. `UPDATED` is intentionally limited to
changes in sorted `sources` or `rss.startedAt`. Rank, growth, volume, traffic,
articles, display casing, timestamps, provenance, and row order do not trigger
alerts. Partial, empty, failed, corrupt-state, and budget-exhausted runs never
replace the last complete snapshot.

### Pricing

Pay per event. All-empty results, technical errors, status rows, monitoring
baselines, no-change runs, and cross-source duplicates are not product events.
A partial analysis with at least one useful selected surface is one
keyword-report event.
Actor users are charged only the fixed event prices; Apify platform usage is included
in those prices.

| Event                            |                   Price |
| -------------------------------- | ----------------------: |
| Keyword analysis report          | $0.75 per 1,000 reports |
| Shared-scale comparison report   | $3.75 per 1,000 reports |
| Deduplicated Trending Now result |    $0.55 per 1,000 rows |
| Trending monitor change          | $0.55 per 1,000 changes |

`maxItems` caps paid output. Apify's maximum-cost-per-run setting can add an
account-level spending limit. Before monitoring writes a transition, it checks
that the remaining event budget covers every change. If not, it writes one free
`STATE_PRESERVED` status, charges no transition row, and keeps the previous
snapshot. Other modes stop writing paid rows when the limit is reached.

### Data quality and reliability

- Google Trends scores are relative and sampled. Repeating the same query can
  produce different values.
- A timeline containing only zeroes can be a valid low-volume result.
- Direct HTTP is used first. After a network error, `403`, or `429`, the whole
  logical operation is retried through at most five new sticky Apify residential
  sessions. Retries after the first residential attempt use bounded backoff.
- Cookies, request parameters, and IP stay together for one logical operation.
- Unknown RPC responses fail closed as contract drift instead of being hidden by
  proxy rotation.
- A naturally empty analyze surface is reported in `missingDataTypes` without
  discarding other useful surfaces. A technical surface failure still produces
  a free error row after transport fallback.
- Trending RPC and RSS are independent sources. One can produce explicit
  partial output when the other fails.
- Monitor state is a single versioned `SNAPSHOT` in an isolated named
  key-value store. It is saved only after every transition row is written.

On 2026-09-26, the access R\&D matrix completed `36/36` HTTP checks on Apify:
`30/30` direct and `6/6` through sticky residential proxy. Local production
smoke tests also completed analyze, compare, and dual-source trending flows.
These are dated observations, not a guarantee against future Google changes or
rate limits.

On 2026-09-27, raw-contract probes confirmed region identifiers for `16/16`
Polish regions and `250/250` countries, coordinates for `200/200` US cities,
and numeric growth for `42/42` sampled rising queries. Browser research
completed `0/17` successful Related topics sessions, including `0/3` with
Camoufox on independent residential IPs.

### Current limitations

- Related topics are not exposed. Related queries and topic suggestions are
  available and are different Google Trends surfaces. Chrome, Firefox, and
  Camoufox did not provide a reliable production path on the tested Apify
  proxy pool.
- Google does not provide a supported public production API for this exact
  output. Endpoint changes can require an Actor update.
- RSS Trending Now requires a two-letter country and returns fewer, news-focused
  rows than RPC.
- The Actor does not provide absolute keyword search volume.
- Long-running results can change while Google updates its live index.
- Monitoring has no built-in webhook and requires one writer per monitor.
- `ENDED` means absent from the configured top-N snapshot, not globally ended.

Use the Actor in accordance with Google terms, applicable law, and your own data
processing obligations.

### Development

Runtime and CI use Node.js `>=20.19`.

```bash
npm ci
npm run quality
```

`npm run quality:audit` runs the core stateless cloud matrix,
`npm run quality:audit-extended` runs the conditional pairwise and boundary
matrix, `npm run quality:audit-invalid` confirms invalid inputs remain free, and
`npm run quality:audit-monitor` verifies a sequential baseline/no-change
lifecycle. A manual release also runs the 50-term benchmark and
`npm run quality:audit-public` for sync API, async API, views, `OUTPUT`, MCP, and
Store before publication. Product decisions and live evidence are tracked in
[`docs/backlog.md`](docs/backlog.md); architecture is in
[`docs/diagram.md`](docs/diagram.md).

# Actor input Schema

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

analyze creates one report per term; compare creates one shared timeline; trending returns the current rows; monitor stores a baseline and later returns only NEW, UPDATED, and ENDED changes.

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

Required for analyze (1–50) and compare (2–5). Enter literal phrases such as ChatGPT or Google topic IDs such as /m/0mkz. Topic IDs aggregate spellings and languages.

## `dataTypes` (type: `array`):

Select report surfaces. If at least one surface has data, one report is written and charged; empty surfaces are listed in missingDataTypes. All-empty and technical-error results are free. Compare always uses timeline; trending and monitor ignore this field.

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

Caps analyze reports or the Trending Now population. Monitor compares this exact top-N population, so changing the value starts an isolated baseline.

## `timeframe` (type: `string`):

Google preset such as now 7-d, today 3-m, today 12-m, today 5-y, or a custom UTC range formatted YYYY-MM-DD YYYY-MM-DD. Related queries require at least 7 days.

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

Google Trends geo code: US, PL, US-CA, or empty for worldwide analysis. RSS trending requires a two-letter country.

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

BCP 47 language tag used by Google, for example en-US or pl-PL.

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

0 means all categories. Use a Google Trends category ID to disambiguate a term.

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

Separate Google indexes are not comparable with each other. Use web for Web Search; the legacy empty value remains accepted.

## `resolution` (type: `string`):

Granularity used by interest by region in analyze mode.

## `trendingSources` (type: `array`):

RPC provides up to about 50 trends with growth and relative volume. RSS provides about 10 trends with news articles. Selecting both merges exact normalized titles without conflating their traffic metrics.

## `trendingWindow` (type: `integer`):

RPC recency selector. Supported values are 4, 5, 6, 7, 8 (Rising), 9, 10 (Top), and 12. Google currently returns no RPC payload for 11, so the Actor rejects it. RSS ignores this setting.

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

Stable lowercase slug that identifies one independent monitor, for example pl-daily. Reuse it with the same scope on every scheduled run. Used only in monitor mode.

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

Advanced alternative to structured input for analyze, compare, and trending. Monitor mode rejects copied URLs because its population must remain explicit and stable.

## Actor input object example

```json
{
  "mode": "analyze",
  "searchTerms": [
    "Google"
  ],
  "dataTypes": [
    "timeline",
    "regions",
    "relatedQueries",
    "suggestions"
  ],
  "maxItems": 10,
  "timeframe": "today 12-m",
  "geo": "PL",
  "language": "en-US",
  "category": 0,
  "searchProperty": "web",
  "resolution": "REGION",
  "trendingSources": [
    "rpc",
    "rss"
  ],
  "trendingWindow": 8,
  "monitorId": "pl-daily",
  "startUrls": [
    "https://trends.google.com/trends/explore?date=today%2012-m&geo=PL&q=Google,ChatGPT"
  ]
}
```

# Actor output Schema

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

Default dataset overview with every report, current trend, monitoring change, and free status row.

## `reports` (type: `string`):

Default dataset with columns optimized for analyze and compare reports.

## `trending` (type: `string`):

Default dataset with columns optimized for deduplicated trending rows.

## `monitoring` (type: `string`):

Default dataset with columns optimized for NEW, UPDATED, and ENDED trend changes.

## `statusRows` (type: `string`):

Default dataset with columns optimized for baselines, unchanged runs, no-data, preservation, and errors.

## `status` (type: `string`):

Machine-readable counters, billing result, retry use, and final run status stored in OUTPUT.

# 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": [
        "Google"
    ],
    "maxItems": 10
};

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

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

```

## MCP server setup

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