# Google Trends Data (Unofficial): Over Time, Region, Queries (`madrasco/google-trends-interest`) Actor

Google Trends data for a keyword list: interest over time, interest by region and related queries (top and rising), alone or in comparisons of up to 5. Paced, honest requests with back-off; every keyword gets a status row (ok, no data, rate limited). Not affiliated with Google.

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

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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

## Keyword Interest for Google Trends: Over Time, by Region, Related Queries

Give it a list of keywords. For each keyword you get one row with:

- **Interest over time**: Google Trends' 0-100 search-interest timeline for your time range, plus the average, the peak value and the peak date;
- **Interest by region**: 0-100 per country (worldwide) or per state/province (when you pick a country), or per city / US metro area if you ask;
- **Related queries**: the top related queries and the rising ones, with Google's "Breakout" label kept;
- a **status**: `ok`, `no_data`, `partial`, `rate_limited`, `error`, `not_attempted` or `stopped_bot_check`, and a plain-English message when it isn't `ok`. `error` means Google answered with something we could not read (an unexpected HTTP error, a network failure or a response format we could not read) after retries.

Every keyword you give gets a row, so you can see at a glance which ones need a rerun instead of finding them silently missing.

### Input

| Field | What it does | Default |
|---|---|---|
| `keywords` | One search term per line; each is looked up on its own (values relative to its own peak). Also accepted as `searchTerms`, `queries`, `terms`, `keyword`. | `coffee`, `tea` |
| `comparisons` | Optional. One line per comparison, up to 5 keywords separated by commas (`coffee, tea, matcha`). Keywords in a comparison are scaled together, like the website's compare view, so their values can be compared with each other. Each keyword still gets its own row, with `comparedWith` listing the others. | none |
| `geo` | Two-letter country code (`US`, `GB`, `AU`), optionally with a sub-region (`US-CA`); empty = worldwide. Also accepted as `country`. | worldwide |
| `timeframe` | `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 two dates `2024-01-01 2024-12-31`. | `today 12-m` |
| `category` | Google Trends category number, 0 = all. | 0 |
| `searchType` | `web`, `images`, `news`, `shopping` or `youtube`. | `web` |
| `includeInterestOverTime`, `includeInterestByRegion`, `includeRelatedQueries` | Turn sections off to finish faster. | all on |
| `regionResolution` | `auto`, `COUNTRY`, `REGION`, `CITY`, `DMA`. | `auto` |
| `pauseSeconds`, `maxRetries`, `maxMinutes` | Pace (at least 3 s between requests), retries after HTTP 429, and a time budget. | 5 s, 4, until the run timeout |

Example (API / AI agents):

```json
{"keywords": ["air fryer", "sourdough"], "comparisons": ["coffee, tea, matcha"], "geo": "US", "timeframe": "today 5-y"}
```

Invalid input (an unknown time range, a region name instead of a code, more than 5 keywords in a comparison) stops the run at once with a message saying what to change.

### Output

One dataset row per keyword (views: Overview, Interest over time, Interest by region, Related queries), and a run summary in the key-value store record `OUTPUT` (status counts, duration, keywords per minute, requests and HTTP 429 responses). Example row from our test run of 2026-09-25 (worldwide, `today 12-m`; lists cut to their first item — the full row had 53 weekly points, 57 countries and 25 top and 25 rising queries):

```json
{
  "keyword": "coffee",
  "comparedWith": [],
  "status": "ok",
  "message": null,
  "geo": "worldwide",
  "timeframe": "today 12-m",
  "category": 0,
  "searchType": "web",
  "interestOverTime": [{"date": "2025-09-21", "label": "Sep 21 – 27, 2025", "value": 59, "isPartial": false}],
  "averageInterest": 75.6,
  "peakInterest": 100,
  "peakDate": "2026-05-10",
  "interestByRegion": [{"geoCode": "SG", "geoName": "Singapore", "value": 100}],
  "regionResolution": "COUNTRY",
  "relatedQueriesTop": [{"query": "coffee shop", "value": 100}],
  "relatedQueriesRising": [{"query": "how to remove coffee stain from carpet", "increasePercent": 9100, "formattedValue": "Breakout", "breakout": true}],
  "fetchedAt": "2026-09-25T16:10:54Z"
}
```

The average and peak leave out the last point when Google marks it as partial (the current, incomplete week or day).

### How it fetches, and what that means for speed

- It asks Google Trends' own web endpoints at a steady pace (by default one request every 5 seconds), from the run's own address, with a User-Agent that names this actor. It does **not** use proxies, rotate addresses or disguise itself as a browser.
- Each keyword on its own takes 4 requests with all three sections on (2 with only interest over time); a comparison of 5 takes 12 requests. So with the default pace one keyword takes about 20 seconds with all sections, about 10 seconds with interest over time only.
- When Google answers HTTP 429 (too many requests), the actor waits 30 s, 60 s, 120 s... and retries, up to `maxRetries` times. If Google still refuses, that keyword gets a `rate_limited` row (or `partial` if some sections were fetched) and the run moves on.
- If Google ever shows a captcha or "unusual traffic" page, the run stops there: remaining keywords get `not_attempted` rows. It never tries to get past such a page.
- Measured in our own test runs on Apify (256 MB memory, default pace, all three sections, worldwide, last 12 months). These are single runs from one day, not a guarantee; Google's rate limits vary.
  - 200-keyword run on 2026-09-25: all 198 real keywords `ok` (the other 2 were deliberately made-up terms and came back `no_data`), 80 minutes in total, about 2.5 keywords per minute. Google answered HTTP 429 23 times in 824 requests; every one cleared after the back-off wait, so no keyword ended `rate_limited`. No captcha or bot page. Platform usage was US$0.069, about US$0.34 per 1,000 keywords.
  - The default input (coffee, tea) finished in under a minute in each of our smoke runs.

### Limitations

- Google Trends values are relative (0-100) and sampled by Google; two fetches of the same keyword can differ slightly, as they do on the website.
- Very rare keywords return `no_data`, as on the website.
- Related topics and the daily "Trending now" list are not included yet.
- The endpoints are the ones the Trends website itself uses; Google can change them without notice. We run this actor daily to catch that: a run in which no keyword is `ok` and at least one row has status `error` still saves its rows, then ends as **Failed**. Runs where every keyword is `no_data`, `rate_limited`, `not_attempted` or `stopped_bot_check` end as Succeeded, since those are Google's answers, explained in each row's message.

### Use with AI agents

Give `keywords` as a list of strings, and read `status` first: only `ok` and `partial` rows carry data. Values from separate keywords are not comparable with each other; put up to 5 keywords in one `comparisons` line when they need to be.

### Pricing

No charge from us for now: you pay only Apify's platform usage of your run, which is small at the default 256 MB memory. We may add a per-keyword price in a later release; any price is shown on this page and by Apify before you start a run.

### Support

Use the Issues tab on this page. Replies are written with AI assistance; the human owner of Madrasco can be reached on request.

Data source: Google Trends (https://www.google.com/trends). If you publish these figures, cite Google Trends as the source.

Built by Madrasco. Not affiliated with, endorsed by or sponsored by Google. Google Trends is a trademark of Google LLC. This actor returns aggregate, relative search-interest figures; it collects no personal data.

# Actor input Schema

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

One search term per line. Each keyword is looked up on its own, so its values (0-100) are relative to its own peak. Also accepted as searchTerms, queries or terms. If no keyword field is given at all, the run uses coffee and tea.

## `comparisons` (type: `array`):

One comparison per line, up to 5 keywords separated by commas, e.g. 'coffee, tea, matcha'. Keywords in a comparison are scaled together (like the website's compare view), so their values can be compared with each other. Each keyword still gets its own row.

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

Two-letter country code (US, GB, AU...), optionally with a sub-region (US-CA). Empty for worldwide.

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

Google Trends time range: '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' (since 2004), or two dates 'YYYY-MM-DD YYYY-MM-DD'.

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

Google Trends category number; 0 = all categories (e.g. 71 = Food & Drink, 5 = Computers & Electronics).

## `searchType` (type: `string`):

Which Google search the interest figures come from, as on the Trends website.

## `includeInterestOverTime` (type: `boolean`):

Timeline of search interest (0-100) for the time range.

## `includeInterestByRegion` (type: `boolean`):

Search interest (0-100) per country, or per sub-region when a country is chosen.

## `includeRelatedQueries` (type: `boolean`):

Top and rising related queries (rising includes 'Breakout' queries).

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

Level of the interest-by-region table. Automatic = countries when worldwide, sub-regions when a country is chosen.

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

Also list regions with little search volume (as the website's checkbox does).

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

Language for labels and related queries, e.g. en-US, de, ja.

## `pauseSeconds` (type: `integer`):

Minimum wait between requests to Google Trends (at least 3). Slower is more reliable.

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

How often to retry a request Google answers with HTTP 429, waiting 30 s, 60 s, 120 s... in between. After that the keyword gets a 'rate\_limited' row.

## `maxMinutes` (type: `integer`):

Stop starting new keywords after this many minutes (0 = until the run timeout). Keywords not started get a 'not\_attempted' row.

## Actor input object example

```json
{
  "keywords": [
    "coffee",
    "tea"
  ],
  "geo": "",
  "timeframe": "today 12-m",
  "category": 0,
  "searchType": "web",
  "includeInterestOverTime": true,
  "includeInterestByRegion": true,
  "includeRelatedQueries": true,
  "regionResolution": "auto",
  "includeLowVolumeRegions": false,
  "language": "en-US",
  "pauseSeconds": 5,
  "maxRetries": 4,
  "maxMinutes": 0
}
```

# Actor output Schema

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

No description

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

No description

## `summary` (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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("madrasco/google-trends-interest").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",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("madrasco/google-trends-interest").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"
  ]
}' |
apify call madrasco/google-trends-interest --silent --output-dataset

```

## MCP server setup

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

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/SeKkPUP13NEfv07aL/builds/y6zwGRk3TYFuWxCVt/openapi.json
