# Google Trends Scraper: Interest Over Time, Regions, Queries (`meskaoui.azeddine/google-trends-scraper`) Actor

Scrape Google Trends for any keyword: interest over time, interest by region, related and rising queries, keyword comparison, ready-made CSV timeline. Blocked requests are retried automatically and keywords with no data are free. $1.50 per 1,000 results. JSON, CSV, Excel, API.

- **URL**: https://apify.com/meskaoui.azeddine/google-trends-scraper.md
- **Developed by:** [Azeddine MESKAOUI](https://apify.com/meskaoui.azeddine) (community)
- **Categories:** SEO tools, E-commerce, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 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 Scraper: reliable, with retries and CSV export

Get Google Trends data for any keyword, without a browser: interest over time, interest by region, related queries and topics, and keyword comparison on a shared scale.

Google Trends blocks callers quickly, which is why many Trends scrapers end their runs half empty. This Actor treats a refusal as normal: the search is retried from a fresh session and another IP, a run tells you exactly which searches succeeded, and **a keyword that returns no data is not charged**.

### What you get for each keyword

- **Interest over time**: the 0-100 curve, one point per hour, day, week or month depending on the period.
- **Trend figures, already computed**: average, peak value and peak date, latest value, change in percent between the start and the end of the period, and a plain `rising`, `stable` or `falling` label.
- **Interest by region**: countries when you search worldwide, states or provinces inside a country, cities or US metro areas on request.
- **Related queries**: top and rising searches, with the growth in percent and a `breakout` flag.
- **Related topics** (optional, off by default): top and rising topics, when Google returns them.
- **A ready-made CSV**: one line per date, one column per keyword, in the key-value store under `TIMELINE`. It opens straight in Excel or Google Sheets.

### What it is for

- **SEO and content**: find which keyword is growing before you write about it, and which rising queries surround it.
- **E-commerce and product research**: check whether demand for a product is seasonal, rising or fading, and in which regions.
- **Market and brand tracking**: compare your brand with competitors on one scale, country by country.
- **Finance and research**: search interest as a signal for a company, a coin or a topic, as clean time series.
- **Dashboards and AI agents**: schedule a run and read the same structure every day through the API.

### How to use it

1. Type one or more **search terms**, one per line.
2. Choose a **region** (`US`, `FR`, `US-CA`, or empty for worldwide) and a **time range**.
3. Turn on **Compare the terms with each other** if you want them on one shared scale.
4. Click **Start**, then export the dataset as JSON, CSV or Excel, or download the `TIMELINE` CSV.

### Example input

```json
{
    "searchTerms": ["bitcoin", "ethereum"],
    "compare": true,
    "geo": "US",
    "timeRange": "today 12-m",
    "includeInterestByRegion": true,
    "includeRelatedQueries": true,
    "proxyConfiguration": { "useApifyProxy": true }
}
```

Several regions at once: `"geo": "US, GB, DE"` runs every term in every region. Custom dates: `"customTimeRange": "2026-01-01 2026-06-30"`.

### Example output

One row per keyword and region. Lists are shortened here.

```json
{
    "keyword": "air fryer",
    "geo": "US",
    "timeRange": "today 12-m",
    "searchType": "web",
    "category": 0,
    "comparedWith": [],
    "hasData": true,
    "averageInterest": 66.6,
    "peakValue": 100,
    "peakDate": "2026-04-12",
    "latestValue": 55,
    "changePercent": 4,
    "trend": "stable",
    "interestOverTime": [
        { "date": "2025-10-05", "value": 57 },
        { "date": "2025-10-12", "value": 53 },
        { "date": "2026-10-04", "value": 62, "isPartial": true }
    ],
    "interestByRegion": [
        { "geoCode": "US-WY", "geoName": "Wyoming", "value": 100 },
        { "geoCode": "US-KS", "geoName": "Kansas", "value": 38 }
    ],
    "relatedQueries": {
        "top": [{ "query": "ninja air fryer", "value": 100 }],
        "rising": [{ "query": "best air fryer 2026", "growth": "Breakout", "growthPercent": null, "breakout": true }]
    },
    "relatedTopics": { "top": [], "rising": [] },
    "trendsUrl": "https://trends.google.com/trends/explore?q=air+fryer&date=today+12-m&geo=US",
    "scrapedAt": "2026-10-06T12:41:08.512Z"
}
```

### Fields

| Field | Description |
|---|---|
| `keyword`, `geo`, `timeRange`, `searchType`, `category` | What was searched. `geo` is `WORLDWIDE` when no region was given |
| `comparedWith` | The other terms of the same comparison group, empty when the term was measured alone |
| `hasData` | `false` when Google Trends has too few searches for this term, region and period (fewer than three points above zero). Such rows are free |
| `interestOverTime` | `date`, `value` (0-100, `null` when Google has no data for that point) and `isPartial` on the last, incomplete point |
| `averageInterest`, `peakValue`, `peakDate`, `latestValue` | Computed from the timeline, incomplete last point excluded |
| `changePercent`, `trend` | Average of the last quarter of the period compared with the first quarter. `rising` from +15%, `falling` from -15%, otherwise `stable`. Empty on very short timelines |
| `interestByRegion` | `geoCode`, `geoName`, `value`, highest first |
| `relatedQueries`, `relatedTopics` | `top` (0-100 scale) and `rising` (`growth`, `growthPercent`, `breakout`) |
| `missing` | Present only when Google refused one optional block for this keyword |
| `trendsUrl` | The same search on Google Trends, to check a figure by eye |

### How to read the numbers

Google Trends does not publish search volumes. Every value is relative: 100 is the highest point of the chart, 50 is half of it. Two consequences worth knowing:

- Without comparison, each keyword has its own scale, so 80 for one term and 40 for another tells you nothing about which is bigger. Turn **Compare** on for that.
- A comparison holds at most five terms. With more, the Actor makes groups of five in the order of your list; values are comparable inside a group, not across groups. Put a common reference term in each group if you need to chain them.

### Run summary

Each run stores a `RUN_SUMMARY` record in the key-value store: for every search, its status and the number of attempts it took, plus request, retry and replaced-session counts. A search that fails is reported there and in the log; it does not fail the run and is not charged.

### Limits

- **Relative values only**, as explained above. No tool can get absolute volumes out of Google Trends.
- **Related topics are usually empty.** Google rarely returns that block any more, so it is off by default; related queries are the reliable one.
- **Small terms return nothing.** A niche keyword in a small region over a short period has no data on Google Trends itself.
- **Hourly data only exists for short ranges** (up to 7 days). Five years gives weekly points, 2004 to present gives monthly points.
- **Keep the proxy on.** From a single IP, Google blocks after a few dozen requests. The Actor then stops at once with a clear message instead of insisting.
- "Trending now" (the daily list of trending searches) is a different Google product and is not covered.

### FAQ

**Can I reuse the input of another Google Trends scraper?** `searchTerms`, `timeRange`, `geo`, `category` and `isMultiple` keep their usual names and meaning. Unknown keys are ignored.

**Why is `changePercent` empty?** The timeline is too short, or the first quarter of the period is at zero.

**Is this legal?** The Actor reads aggregated, anonymous statistics that Google publishes for anyone. It collects no personal data.

**Something is missing or broken?** Open an issue on the Issues tab with the term, region and period you tried.

# Actor input Schema

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

One keyword or phrase per line, exactly as you would type it into Google Trends.

## `compare` (type: `boolean`):

Off: each term is measured on its own 0-100 scale. On: terms are measured on one shared scale, in groups of up to five, so you can see which one is bigger.

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

Country code (US, FR, MA), subregion (US-CA, GB-ENG), or empty for worldwide. Several regions separated by commas run each term in each region.

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

Period to cover. Short ranges return hourly or daily points, long ranges weekly or monthly points.

## `customTimeRange` (type: `string`):

Two dates, start then end, for example 2026-01-01 2026-06-30. When filled, it replaces the time range above.

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

Which Google property the interest is measured on.

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

Google Trends category id, 0 for all categories. Examples: 7 Finance, 3 Arts & Entertainment, 18 Shopping, 20 Sports.

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

Where the term is searched the most: countries when worldwide, states or provinces inside a country.

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

Leave on automatic unless you want cities or US metro areas (DMA).

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

Top and rising searches made by the same people.

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

Top and rising topics. Off by default: Google rarely returns this block any more, and each extra request raises the risk of being blocked.

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

Language for region and topic names, for example en-US, fr-FR, es-ES.

## `timezoneOffsetMinutes` (type: `integer`):

0 for UTC. Google uses minutes west of UTC: 300 for New York, -60 for Paris and Casablanca.

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

Keep it low: Google Trends blocks fast callers. 3 is a safe value.

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

Keep Apify Proxy on. A blocked request is retried from another IP.

## Actor input object example

```json
{
  "searchTerms": [
    "bitcoin",
    "ethereum"
  ],
  "compare": false,
  "geo": "US",
  "timeRange": "today 12-m",
  "searchType": "web",
  "category": 0,
  "includeInterestByRegion": true,
  "regionResolution": "",
  "includeRelatedQueries": true,
  "includeRelatedTopics": false,
  "language": "en-US",
  "timezoneOffsetMinutes": 0,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `keywords` (type: `string`):

One row per keyword and region: interest over time, by region, related queries and topics, plus trend figures.

## `timelineCsv` (type: `string`):

One line per date and one column per keyword, ready for Excel or Google Sheets.

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

Status of every search, with request, retry and replaced-session counts.

# 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": [
        "bitcoin",
        "ethereum"
    ],
    "geo": "US",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("meskaoui.azeddine/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": [
        "bitcoin",
        "ethereum",
    ],
    "geo": "US",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("meskaoui.azeddine/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": [
    "bitcoin",
    "ethereum"
  ],
  "geo": "US",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call meskaoui.azeddine/google-trends-scraper --silent --output-dataset

```

## MCP server setup

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