# Google Trends Scraper: Interest, Related Queries, Spikes (`datahamster/google-trends`) Actor

Track Google Trends by keyword: daily interest-over-time scores, top and rising related queries, and a spike flag on the latest value versus its 30-day median. Monitor mode alerts on new rising queries or a spike. No login, worldwide or by country/region, any timeframe.

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

## Pricing

from $0.80 / 1,000 result items

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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: Interest, Related Queries, Spikes

Pull Google Trends' own data for any keyword — the same numbers the `/trends/explore` page shows — straight from its JSON API. No login, no headless browser.

### What you get

Real rows from the example dataset (`keywords: ["python"], timeframe: "today 3-m"`):

| type | keyword | date / query | value | kind |
|---|---|---|---|---|
| interest\_over\_time | python | 2026-06-26 | 78 | — |
| interest\_over\_time | python | 2026-09-26 (isPartial) | 32 | — |
| related\_query | python | "python code" | 100 | top |
| related\_query | python | "singapore reticulated python sighting" | 7800 (Google calls this a "Breakout") | rising |

Full row: `id`, `url`, `type` (`interest_over_time` | `related_query` | `related_topic`), `keyword`, `geo`, `timeframe`, `date`, `value`, `isPartial`, `isSpike`, `rank`, `query`, `kind` (`top` | `rising`), `scrapedAt`.

### Use cases

- **Content and SEO planning** — pull `today 12-m` for a shortlist of topics and see which one is trending up before you commit a content calendar to it.
- **Rising-query discovery** — the `related_query` rows with `kind: "rising"` surface breakout queries around your seed keyword days before they show up in generic keyword tools.
- **Spike monitoring** — put a watchlist of keywords into monitor mode; get an alert the day search interest jumps (`isSpike: true`) or a brand-new rising related query appears.

### Try it in 10 seconds

Hit **Start**/**Try it** — the input already works: `keywords: ["python"]`, `timeframe: "today 3-m"`, `maxItems: 20`.

**Monitor mode** — save the task, then set:

```json
{
  "mode": "monitor",
  "monitorStateId": "my-watchlist",
  "keywords": ["python", "typescript"],
  "spikeThreshold": 2.0,
  "webhookUrl": "https://your-endpoint.example.com/hook"
}
```

and put it on a schedule (Apify → Schedules). Each monitor run charges one `monitor-check` event; only new or changed rows (a new day's point, a value change, a brand-new related query) are billed as `change` events.

### Related actors

- [Google News Scraper (search, headlines, alerts, no login)](https://apify.com/datahamster/google-news-feed) — see the actual headlines behind a spike in search interest.
- [Reddit Scraper (subreddit posts, search, comments, no login)](https://apify.com/datahamster/reddit-posts) — community discussion signal to compare against search-interest spikes.
- [Google Ads Transparency Scraper (advertiser, domain, alerts)](https://apify.com/datahamster/google-ads-transparency) — see who is buying ads around a rising topic.
- [Yahoo Finance Scraper (quotes, key stats, history, alerts)](https://apify.com/datahamster/yahoo-finance-quotes) — pair search-interest spikes with the underlying stock or ticker data.

### How it works

1. **Explore** — up to 5 keywords per call go to Google Trends' own `trends/api/explore` endpoint (the same call the `/trends/explore` page makes), which returns a token per widget (interest-over-time chart, related queries, related topics).
2. **Widget data** — each token is exchanged for its data at `widgetdata/multiline` (interest over time) and `widgetdata/relatedsearches` (related queries/topics).
3. A warm-up request seeds a session cookie first; without it Google's explore endpoint answers the very first call of a session with a 429 regardless of keyword.
4. **Spike flag** — the latest interest-over-time point gets `isSpike: true` when its value is at least `spikeThreshold` (default 2.0) times the median of the trailing 30 points.

### Input

| Field | Meaning | Default |
|---|---|---|
| `keywords` | Keywords to track, up to 5 compared together per batch (more are split into batches automatically) | `[]` |
| `geo` | Region code, e.g. `US`, `US-CA` — empty for worldwide | `""` (worldwide) |
| `timeframe` | Google Trends timeframe string, e.g. `today 3-m`, `today 12-m`, `2024-01-01 2024-06-01` | `"today 3-m"` |
| `includeRelated` | Also fetch related queries and related topics per keyword | `true` |
| `spikeThreshold` | Latest value must be at least this many times the trailing 30-point median to flag `isSpike` | `2.0` |
| `maxItems` | Stop after this many rows | `500` |
| `mode` | `scrape` or `monitor` (only new/changed since last run) | `scrape` |
| `monitorStateId`, `webhookUrl`, `telegramBotToken`, `telegramChatId` | Monitor-mode state key and alert targets | empty |

### Pricing

| Event | Price |
|---|---|
| result | $0.001 per row ($1 per 1,000) |
| monitor-check | $0.005 per monitor run |
| change | $0.001 per new/changed row |

Charged only for rows actually pushed. An interest-over-time timeframe of `today 3-m` returns roughly 93 daily rows per keyword plus up to ~45 related-query rows when `includeRelated` is on.

**Found it useful?** A short review on the Store page helps other people find this actor and tells us what to improve. If a spike or interest score looks wrong, open an issue on the actor page — issues are answered within a day.

### Why this actor

- Reads Google Trends' own API directly — the same numbers the site itself shows, not a scrape of rendered HTML.
- One row schema for interest-over-time, related queries and related topics, so a single dataset covers the whole picture for a keyword.
- Spike detection and a monitor mode built in — no separate script needed to notice when a term breaks out.
- A run that finds nothing pushes nothing and charges no result events; the run summary explains why instead of leaving you guessing.

### Limits

- Up to 5 keywords are compared per batch (Google Trends' own limit for the interest-over-time chart); more keywords are split into sequential batches, one `explore` call each.
- Related topics (`related_topic` rows) come back empty for every keyword tried during development — Google's backend answers `rankedList: []` on the `none` proxy tier for this widget right now. Related queries (`related_query`) are unaffected. The parser is ready for topic data the day it returns.
- `value` for interest-over-time is Google's own 0-100 relative score, not an absolute search count; for related queries it is 0-100 relative to the top query, or a large number (Google's UI labels these "Breakout" instead of showing the number) for a rising query with too little prior volume to compute a normal percentage.
- No person-level data of any kind — this actor never touches per-searcher data; Google Trends does not expose it.

### FAQ

**Does it need a Google account or cookies?** No. The actor makes its own warm-up request internally; there is no login field.

**What happens when a keyword has (almost) no search volume?** It still returns rows — Google Trends' own near-zero score — rather than nothing. That is the real answer, not a block; the run summary only reports a block when the source itself refuses every request.

**What does monitor mode actually save me?** It keeps state per `monitorStateId` (or per saved task) across runs, so a schedule returns only the days/queries that are new or changed instead of the whole series again — you pay one `monitor-check` plus one `change` event per new/changed row, not a full `result` for every row every time.

### Changelog

- 0.1: initial release — interest over time, related queries/topics, spike flag, monitor mode.

***

If this actor saved you time, a short review on its Store page genuinely helps other people find it. Found a bug or need a field that is missing? Open a ticket on the **Issues** tab.

# Actor input Schema

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

Stop after this many results (you are charged only for pushed items)

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

scrape = full results; monitor = only new/changed items since the previous run of this task

## `monitorStateId` (type: `string`):

Optional state id when not running as a saved task (monitor mode)

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

POST a change summary here in monitor mode

## `telegramBotToken` (type: `string`):

Optional: bot token for monitor-mode change summaries

## `telegramChatId` (type: `string`):

Optional: chat id that receives monitor-mode summaries

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

Keywords to track, e.g. "python", "typescript". Up to 5 are compared together per batch (Google Trends' own limit); more are split into sequential batches automatically.

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

Google Trends region code, e.g. "US", "GB", "US-CA". Leave empty for worldwide.

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

Google Trends timeframe string, e.g. "today 3-m", "today 12-m", "today 5-y", or an explicit range "2024-01-01 2024-06-01".

## `includeRelated` (type: `boolean`):

true = also fetch top/rising related queries and related topics for each keyword. false = interest-over-time only (faster, fewer rows).

## `spikeThreshold` (type: `number`):

The latest interest-over-time point is flagged isSpike=true when its value is at least this many times the median of the trailing 30 points. Example: 2.0 (double the recent median).

## Actor input object example

```json
{
  "maxItems": 500,
  "mode": "scrape",
  "keywords": [
    "python"
  ],
  "geo": "",
  "timeframe": "today 3-m",
  "includeRelated": true,
  "spikeThreshold": 2
}
```

# Actor output Schema

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

All pushed rows (dataset, JSON)

## `resultsTable` (type: `string`):

Dataset in the Console viewer

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

RUN\_SUMMARY record

# 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": [
        "python"
    ],
    "timeframe": "today 3-m"
};

// Run the Actor and wait for it to finish
const run = await client.actor("datahamster/google-trends").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": ["python"],
    "timeframe": "today 3-m",
}

# Run the Actor and wait for it to finish
run = client.actor("datahamster/google-trends").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": [
    "python"
  ],
  "timeframe": "today 3-m"
}' |
apify call datahamster/google-trends --silent --output-dataset

```

## MCP server setup

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

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/r2DqCaoMBgzrYryPl/builds/zwUr7O0Dfi6w9HD98/openapi.json
