# Google Trends Scraper — Interest, Regions & Related Queries (`hapster/google-trends-scraper`) Actor

Google Trends data for keywords or comparisons of up to 5: interest over time, interest by country, region, metro or city, and top and rising related queries. Any geo, time range, category and search type. Keywords without data are free.

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

## Pricing

from $0.30 / 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.
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

Get Google Trends **top and rising related queries**, **interest over time** and **interest by country, region, metro area or city** for any keyword, or compare up to 5 keywords. Pick any location, time range (past hour to 2004–today, or custom dates), category and search type (web, images, news, shopping, YouTube).

**You pay only for keywords whose interest over time has data.** Keywords with too little search volume, inputs that can't be sent, and searches Google rate-limits are free rows with the reason. A charged row can still have an empty region list or empty related-query lists: when Google has none for that keyword (small keywords, city level), or when Google kept rate-limiting or refused that one part (then `sectionErrors` says so).

### What you get

One row per keyword per search:

| Field | What it is |
|---|---|
| `keyword`, `comparedWith` | The keyword and the other keywords in its comparison |
| `interestOverTime` | `date` (UTC), `value` (0–100, relative to the peak in the search), `formattedValue` (as the website shows it: "<1" when the value is 0 but there is data), `isPartial` (the last, still-running period) |
| `averageInterest` | Average over the period (comparisons only; Google gives none for single keywords) |
| `interestByRegion` | `geoCode`, `geoName`, `value` (0–100) and `formattedValue` ("<1" where the value is 0) for each place with data, highest first. City level gives coordinates instead of a code |
| `relatedQueries` | `top` and `rising` lists: `query`, `value` and `formattedValue` (rising: % growth, or "Breakout") |
| `sectionErrors` | Only when a region list or related queries could not be fetched although the interest over time could: which part, and why |
| `status` | `ok` (charged), or `no_data`, `invalid`, `rejected`, `blocked`, `error` (free, with `error` saying why) |

### Input

- **Search terms:** one search per line. `coffee` is one search; `coffee, tea, water` compares three keywords on one scale (values are relative to the highest of them). A comma always means compare: `Washington, DC` is two keywords and two results; write `Washington DC`. Empty lines are skipped.

- **Location:** a country or region code (`US`, `GB`, `US-CA`); empty for worldwide. `UK` is read as `GB`.

- **Region level** must be finer than the location (a country: regions, metro areas or cities; a US state: metro areas or cities).

- **Time range:** past hour, 4 hours, day, 7 days, 30 days, 90 days, 12 months, 5 years, since 2004, custom dates (`2024-01-01 2024-06-30`), or custom hours in UTC (`2026-10-09T10 2026-10-10T22`). Upper or lower case both work.

- **Category ID** and **search type** narrow the search, as on the Trends website.

- **Sections:** switch interest by region or related queries off if you don't need them; runs get faster.

- **Max concurrency:** searches fetched in parallel, 5 by default, at most 8. Above that Google rate-limits harder and more searches end up blocked.

### Good to know

- Google Trends values are relative (0–100), not search counts, and relative to each search: the same keyword gives different numbers in a different comparison, region or time range.
- Values come from the Trends API that the website itself uses, as Google answers automated requests.
- Google Trends is a sample with added noise. Each request can get a different sample (it changes by day and by the requesting location), so values can differ by a few points from the website, and more for small keywords or regions. For research, average runs from different days.
- Values from different lines are on different scales. To compare more than 5 keywords, repeat one well-searched anchor keyword in every line and rescale by it.
- Ranges up to 7 days are in UTC here; the website shows your local time. Weekly points are labelled by the Sunday that starts the week. `value` is empty (null) for periods without data.
- Region values are each place's share of its own searches, so a small place can top a worldwide list; `formattedValue` "<1" marks a 0 that means "below 1". Long ranges show Google's own method changes, e.g. a jump on 1 January 2016.
- Rising related queries sometimes contain generic phrases unrelated to the keyword (e.g. "top songs this week" for `coffee`). The Trends website shows the same ones; they are in Google's data.
- In a comparison, a keyword far smaller than the others shows "<1" (value 0) for most periods, exactly as on the website. It has data, so it is a charged result.
- Filter your results on `status` = `ok` to keep only rows with data.
- **Spreadsheets:** the default export puts every date in its own column. The dataset views **Interest over time** and **Interest by region** give one row per date or per place instead. Through the API, add `fields=keyword,geo,interestOverTime&unwind=interestOverTime` (or `interestByRegion`) to the dataset items URL.
- **Run outcome:** the `OUTPUT` record in the run's key-value store says whether the run succeeded, with its final message, the number of keyword results, counts per status and searches not processed. Handy for Make, Zapier, n8n and AI agents.
- **Long lists:** a list over ~50 keywords takes longer than 5 minutes, so start it as a normal (asynchronous) run; Apify's synchronous API endpoint gives up after 300 seconds. The default run timeout is 24 hours, and the actor stops cleanly before any timeout, telling you how many searches were not processed. Google's rate limits set the pace: one run gets through roughly 10,000–20,000 searches in 24 hours, so split bigger lists into several runs. One run takes at most 50,000 searches.
- Google rate-limits Trends heavily. The actor paces its requests, rotates IPs and retries, and gives searches that were still rate-limited one more try at the end of the run; a search that still fails is a free `blocked` row, and a run where most searches fail ends as failed so you can retry later. On Apify's free plan your runs share fewer proxy IPs and see more rate-limited (free) rows.
- Metro areas (DMA) exist only for the United States.
- Related topics are not included.
- This actor reads public, aggregated Trends data only. No personal data.

### Pricing

Pay per result: one charge per keyword whose interest over time has data, plus a small charge per run start. Rows without data are free. A 5-keyword comparison is 5 results; there is no platform usage on top. Set a maximum charge per run in the run options; the actor stops cleanly when it is reached.

# Actor input Schema

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

One search per line. A comma always means compare: up to 5 comma-separated keywords are compared on one scale (e.g. coffee, tea), and each keyword gives one result row and one charge. So 'Washington, DC' is two keywords; write 'Washington DC' for one. Empty lines are skipped; duplicates are removed.

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

Country or region code, e.g. US, GB, DE, US-CA (UK is read as GB). Leave empty for worldwide.

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

The period to look at. Google picks the resolution: minutes for the last hours, days up to 9 months, weeks up to 5 years, months beyond.

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

Overrides the time range: start and end date as YYYY-MM-DD YYYY-MM-DD, e.g. 2024-01-01 2024-06-30, or hours in UTC as YYYY-MM-DDTHH YYYY-MM-DDTHH, e.g. 2026-10-09T10 2026-10-10T22. Earliest start 2004-01-01.

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

Google Trends category ID to narrow the search, e.g. 71 (Food & Drink), 5 (Computers & Electronics). 0 = all categories.

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

Which Google search to measure.

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

Add each keyword's interest per country (worldwide) or per region (inside a country).

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

Level for interest by region; it must be finer than the location (country: region, metro or city; US state: metro or city; metro area: city). Default: countries for worldwide, regions inside a country. Metro area (DMA) works only with a US location.

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

Add each keyword's top and rising related searches.

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

Searches fetched in parallel, each from its own IP. Above 8, Google rate-limits harder and more searches end up blocked, so 8 is the maximum.

## Actor input object example

```json
{
  "searchTerms": [
    "web scraping",
    "coffee, tea"
  ],
  "geo": "",
  "timeRange": "today 12-m",
  "category": 0,
  "searchType": "web",
  "includeInterestByRegion": true,
  "regionResolution": "",
  "includeRelatedQueries": true,
  "maxConcurrency": 5
}
```

# Actor output Schema

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

One row per keyword per search: its trend data (status ok, charged) or the reason there is none (free).

## `summary` (type: `string`):

Whether the run succeeded, its final message, keyword results, counts per status and searches not processed.

## `runStats` (type: `string`):

Counts per status, requests, rate limits and proxy traffic per row.

# 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": [
        "web scraping",
        "coffee, tea"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("hapster/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": [
        "web scraping",
        "coffee, tea",
    ] }

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

```

## MCP server setup

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