# Google Trends Scraper & API (`smart-shopping-data/google-trends-fast`) Actor

Scrape Google Trends without a browser: interest over time, interest by region and related queries for many keywords. Compare up to 5, filter by geo, category and property. Flat JSON/CSV rows.

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

## Pricing

$2.00 / 1,000 result rows

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 & API

Pull Google Trends data as clean JSON, CSV or Excel. No browser involved. You get **interest over time**, **interest by region** and **related queries** (plus optional **related topics**) for as many keywords as you need. Each data point comes out as its own flat row, ready for spreadsheets, BI tools, databases or your own code.

### What does Google Trends Scraper do?

The Actor sends plain HTTP requests to the same JSON endpoints that the Google Trends website uses. There is no headless browser, so runs start quickly and stay cheap. For every keyword (or group of up to 5 compared keywords) it:

1. Opens a session with Google Trends and asks the explore endpoint for the widgets for your keyword, geo, timeframe, category and search property.
2. Fetches the data behind each widget you enabled:
   - **Interest over time**: the 0–100 popularity timeline.
   - **Interest by region**: popularity by country, region, city or DMA.
   - **Related queries**: the *top* and *rising* searches related to the keyword.
   - **Related topics**: the *top* and *rising* topics (off by default; see [Limitations](#limitations)).
3. Flattens the response into **one dataset row per data point** and writes it to the dataset right after each widget finishes. You can read partial results while the run is still going.

#### Reliability built in

- **Retries with exponential backoff.** Each request is retried up to `maxRetries` times (default 6). Waits start at about 2 s, double each time, include random jitter and are capped at 60 s.
- **Session rotation.** On HTTP 429, 403 or 5xx responses, empty bodies, captcha or consent pages, or invalid JSON, the Actor drops the session and starts a new one with a fresh proxy IP and cookies.
- **Failures are isolated.** If a keyword or widget still fails after every retry, the Actor writes an `error` row for it and moves on to the remaining keywords. **Error rows are not charged.**
- **Run summary.** When the run ends, the key-value store record `OUTPUT` holds `{ keywords, rows, failures, durationSec }`.

### Use cases

- **SEO and content planning:** compare search interest across topics, find rising queries and time content to seasonal peaks.
- **Market research:** track demand for products, brands or categories over months or years, then compare by country or region.
- **E-commerce:** use the Google Shopping property to see what shoppers are searching for, and when.
- **YouTube and news monitoring:** switch the search property to YouTube or News to measure interest on those surfaces.
- **Data science and forecasting:** feed clean, timestamped time series into models and dashboards.
- **Automated reporting:** schedule the Actor on Apify and send results to Google Sheets, a webhook or your data warehouse.

### How to use Google Trends Scraper

1. Click **Try for free** / **Start** on the Actor page.
2. Enter one or more **Keywords**.
3. Optionally set **Geo** (for example `US`, `GB` or `US-CA`; leave it empty for worldwide), **Timeframe**, **Category** and **Search property**.
4. Turn on the data types you want: interest over time, interest by region, related queries, related topics.
5. Turn on **Compare keywords** if you want keywords measured against each other on one scale (see below).
6. Run the Actor, then download the dataset as JSON, CSV, Excel, XML or HTML, or read it through the Apify API.

#### Using it as a Google Trends API

You can call the Actor from any language through the [Apify API](https://docs.apify.com/api/v2), or use the Apify JavaScript or Python clients. Start a run with the input JSON below and read the dataset items when it finishes. With the `run-sync-get-dataset-items` endpoint, a single HTTP call starts the run and returns the rows.

#### Compare mode vs. separate mode

- **Compare keywords off (default):** each keyword is queried separately, so each one gets its own 0–100 scale. Use this when you want the shape of each trend on its own.
- **Compare keywords on:** keywords are sent in groups of up to **5 per request**, the same way you would compare them on the Google Trends website. Values within a group share one 0–100 scale, so you can compare them directly. If you enter more than 5 keywords, they are split into groups of 5 in the order you entered them. Values are only comparable within a group.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `keywords` | array of strings | *(required)* | Search terms to look up. |
| `geo` | string | `""` | Country or region code, e.g. `US`, `GB`, `US-CA`. Empty means worldwide. |
| `timeframe` | string | `today 12-m` | Google Trends time range. See [Tips](#tips). |
| `category` | integer | `0` | Google Trends category ID. `0` means all categories. |
| `property` | string | `""` | Search property: `""` web search, `youtube`, `news`, `images` or `froogle` (Google Shopping). |
| `hl` | string | `en-US` | Interface or response language. |
| `tz` | integer | `0` | Timezone offset in minutes from UTC. |
| `includeInterestOverTime` | boolean | `true` | Output `interest_over_time` rows. |
| `includeInterestByRegion` | boolean | `true` | Output `interest_by_region` rows. |
| `resolution` | string | `AUTO` | Region granularity: `AUTO`, `COUNTRY`, `REGION`, `CITY` or `DMA` (US). `AUTO` uses `COUNTRY` when `geo` is empty and `REGION` otherwise. |
| `includeRelatedQueries` | boolean | `true` | Output `related_query` rows. |
| `includeRelatedTopics` | boolean | `false` | Output `related_topic` rows. |
| `compareKeywords` | boolean | `false` | Put up to 5 keywords in each request so they share one scale. |
| `maxConcurrency` | integer | `3` | Number of keywords or keyword groups scraped in parallel (1–20). |
| `maxRetries` | integer | `6` | Retries per request after the first attempt (0–20). |
| `proxyConfiguration` | object | Apify Proxy | Proxy settings. A new proxy session starts whenever Google blocks a request. |

#### Input example

```json
{
    "keywords": ["bitcoin", "ethereum", "solana"],
    "geo": "US",
    "timeframe": "today 12-m",
    "category": 0,
    "property": "",
    "includeInterestOverTime": true,
    "includeInterestByRegion": true,
    "resolution": "AUTO",
    "includeRelatedQueries": true,
    "includeRelatedTopics": false,
    "compareKeywords": false,
    "maxConcurrency": 3,
    "maxRetries": 6,
    "proxyConfiguration": { "useApifyProxy": true }
}
```

### Output

Every dataset item has a `type` field. Rows are flat, with no nested arrays, so they export cleanly to CSV and Excel. In the examples below, the dates and values are for illustration only.

#### `interest_over_time`

One row per keyword per point in time. `value` is Google's 0–100 relative interest. `isPartial` is `true` for the latest, still-incomplete period. `date` is an ISO 8601 string in UTC and `timestamp` is in Unix seconds.

```json
{
    "type": "interest_over_time",
    "keyword": "bitcoin",
    "geo": "US",
    "timeframe": "today 12-m",
    "date": "2025-10-19T00:00:00.000Z",
    "timestamp": 1760832000,
    "value": 74,
    "isPartial": false
}
```

```json
{
    "type": "interest_over_time",
    "keyword": "bitcoin",
    "geo": "US",
    "timeframe": "today 12-m",
    "date": "2026-10-11T00:00:00.000Z",
    "timestamp": 1791676800,
    "value": 58,
    "isPartial": true
}
```

#### `interest_by_region`

One row per keyword per region. `geoCode` and `geoName` depend on `geo` and `resolution`: countries for a worldwide search, states or provinces at `REGION`, and so on.

```json
{
    "type": "interest_by_region",
    "keyword": "bitcoin",
    "geo": "US",
    "timeframe": "today 12-m",
    "geoCode": "US-NV",
    "geoName": "Nevada",
    "value": 100
}
```

#### `related_query`

One row per related query. `ranking` is `top` or `rising`. For `top` rows, `value` is relative interest from 0 to 100. For `rising` rows, `value` is the percentage increase, and `formattedValue` holds Google's label, such as `+250%` or `Breakout`. `link` is the Google Trends explore path for that query.

```json
{
    "type": "related_query",
    "keyword": "bitcoin",
    "geo": "US",
    "timeframe": "today 12-m",
    "ranking": "top",
    "query": "bitcoin price",
    "value": 100,
    "formattedValue": "100",
    "link": "/trends/explore?q=bitcoin+price&date=today+12-m&geo=US"
}
```

```json
{
    "type": "related_query",
    "keyword": "bitcoin",
    "geo": "US",
    "timeframe": "today 12-m",
    "ranking": "rising",
    "query": "bitcoin etf",
    "value": 250,
    "formattedValue": "+250%",
    "link": "/trends/explore?q=bitcoin+etf&date=today+12-m&geo=US"
}
```

#### `related_topic`

This is the shape the Actor outputs when Google returns topics. Right now Google returns an empty list, so you will usually get no rows of this type (see [Limitations](#limitations)).

```json
{
    "type": "related_topic",
    "keyword": "bitcoin",
    "geo": "US",
    "timeframe": "today 12-m",
    "ranking": "top",
    "topicTitle": "Cryptocurrency",
    "topicType": "Topic",
    "mid": "/m/0vpj4_b",
    "value": 100,
    "formattedValue": "100"
}
```

#### `error` (not charged)

The Actor writes this row when a keyword, keyword group or single widget still fails after all retries. In compare mode, `keyword` holds the keywords of the group, joined by commas.

```json
{
    "keyword": "bitcoin",
    "type": "error",
    "error": "HTTP 429 for https://trends.google.com/trends/api/explore"
}
```

### Pricing

This Actor uses **pay-per-event** pricing:

- **$2.00 per 1,000 result rows** ($0.002 per row).
- **Platform usage is included.** You are not billed separately for compute or Apify Proxy usage.
- **Error rows are free.** You pay only for data rows: `interest_over_time`, `interest_by_region`, `related_query` and `related_topic`.

#### Worked example

In a test run, **10 keywords** with the default data types returned **1,893 rows** in about **30 seconds**, with **0 failures**, using datacenter proxies.

> 1,893 rows × $0.002 = **$3.79** for the run (about $0.38 per keyword).

The number of rows per keyword depends on your settings. Longer or finer timeframes produce more time points. A finer region `resolution` and a worldwide `geo` produce more regions. Turning off data types you don't need lowers the cost.

To cap your spend, set a **maximum charge** for the run in Apify. When the limit is reached, the Actor stops and saves its summary to `OUTPUT` with `stoppedOnChargeLimit: true`.

### Tips

#### Proxy

- The default Apify Proxy setting worked in testing: 10 keywords, 0 failures on datacenter proxies.
- If you get many `429` errors or `error` rows, try **residential** proxies, lower `maxConcurrency`, or raise `maxRetries`.
- Every block triggers a new session with a fresh IP and cookies, so short bursts of rate limiting are usually absorbed without failed rows.

#### Timeframe formats

`timeframe` is passed to Google Trends as is, so any format Google accepts will work. Common values:

| Timeframe | Meaning |
| --- | --- |
| `now 1-H` | Past hour |
| `now 4-H` | Past 4 hours |
| `now 1-d` | Past day |
| `now 7-d` | Past 7 days |
| `today 1-m` | Past 30 days |
| `today 3-m` | Past 90 days |
| `today 12-m` | Past 12 months (default) |
| `today 5-y` | Past 5 years |
| `all` | 2004 to present |
| `2024-01-01 2024-12-31` | Custom date range (`YYYY-MM-DD YYYY-MM-DD`) |

Google picks the time step from the range: shorter ranges give minute or hourly points, longer ranges give daily, weekly or monthly points.

#### Other tips

- **Geo codes** use Google Trends format: ISO country codes (`DE`), or country plus subdivision (`US-CA`, `GB-ENG`).
- **City and DMA resolution** are most useful when `geo` is set to a country. DMA applies to the US.
- **Category IDs** are the numbers Google Trends uses in its own category picker (`0` = all categories).
- Use the `tz` field (minutes from UTC) to set the timezone that Google uses to bucket the data.

### Limitations

- **Related topics usually come back empty.** Google's related-topics endpoint currently returns an empty list, so `related_topic` rows are usually missing even when the option is on. The option is off by default for this reason. The Actor will output topics if Google starts returning them again. Related queries are not affected.
- **Values are relative, not absolute.** Google Trends reports normalized 0–100 interest, not search volumes. Values from separate requests (separate mode, or different compare groups) are each scaled to their own maximum.
- **Low-volume terms** can return few or no data points, because Google does not show data for terms with too little search volume.
- **Google can change its endpoints** at any time, which may temporarily affect results.

### FAQ

#### Is it legal to scrape Google Trends?

Google Trends publishes **aggregated, anonymized** search-interest statistics that anyone can view without logging in. This Actor collects only that aggregate data. It does not collect **personal data** about any individual. Still, you are responsible for how you use the data and for following the laws and terms that apply to you. If you are unsure, ask a lawyer.

#### Do I need a Google account or API key?

No. The Actor reads the public Google Trends data that the website itself loads.

#### Why are my numbers different from the Google Trends website?

Google samples its data, so values can change slightly between requests. Make sure `geo`, `timeframe`, `category`, `property` and compare mode match what you set on the website. Comparing 3 keywords together gives different numbers than querying each one separately.

#### How many keywords can I compare at once?

Up to 5 per group, which is Google's own limit. You can enter as many keywords as you like. In compare mode they are split into groups of 5.

#### What happens if Google blocks a request?

The Actor waits with exponential backoff, switches to a new session with a fresh IP and cookies, and tries again. If every retry fails, it writes an uncharged `error` row and continues with the other keywords.

#### Can I get results while the run is still going?

Yes. Rows are written to the dataset as soon as each widget has been fetched.

# Actor input Schema

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

Search terms to look up on Google Trends. Required.

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

Region code such as US, GB, or US-CA. Empty string means worldwide.

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

Google Trends time range. Examples: today 12-m, now 7-d, today 5-y, or a custom window like 2024-01-01 2024-12-31.

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

Google Trends category id. 0 means all categories.

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

Search vertical. Empty is web search.

## `hl` (type: `string`):

hl query parameter (UI / response language).

## `tz` (type: `integer`):

tz query parameter: minutes from UTC. 0 is UTC.

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

Fetch TIMESERIES widget (/widgetdata/multiline).

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

Fetch GEO_MAP widget (/widgetdata/comparedgeo).

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

Granularity for interest by region. AUTO uses COUNTRY when geo is empty, otherwise REGION.

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

Fetch RELATED_QUERIES widget (/widgetdata/relatedsearches).

## `includeRelatedTopics` (type: `boolean`):

Fetch RELATED_TOPICS widget (/widgetdata/relatedsearches).

## `compareKeywords` (type: `boolean`):

If true, batch up to 5 keywords per explore request so values share a scale. If false, each keyword is queried separately.

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

How many keyword batches to scrape in parallel.

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

Retries per request after the first attempt. Session (proxy + NID cookie) rotates on 429/403/5xx/parse failure.

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

Apify Proxy is recommended. A new proxy session is opened whenever Google blocks or returns invalid JSON.

## Actor input object example

```json
{
  "keywords": [
    "bitcoin",
    "ethereum"
  ],
  "geo": "",
  "timeframe": "today 12-m",
  "category": 0,
  "property": "",
  "hl": "en-US",
  "tz": 0,
  "includeInterestOverTime": true,
  "includeInterestByRegion": true,
  "resolution": "AUTO",
  "includeRelatedQueries": true,
  "includeRelatedTopics": false,
  "compareKeywords": false,
  "maxConcurrency": 3,
  "maxRetries": 6,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

// Run the Actor and wait for it to finish
const run = await client.actor("smart-shopping-data/google-trends-fast").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": [
        "bitcoin",
        "ethereum",
    ] }

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

```

## MCP server setup

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

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/qJpxGnTwvwyIwNuN7/builds/C72JZugy6KvZW3yn0/openapi.json
