# Google Trends Scraper - Reliable API (`atlasdata/google-trends-scraper-reliable`) Actor

Reliable Google Trends API: interest over time, interest by region and related queries (top & rising) for many keywords. Retries and proxy fallback beat 429s.

- **URL**: https://apify.com/atlasdata/google-trends-scraper-reliable.md
- **Developed by:** [Christian Machon](https://apify.com/atlasdata) (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

Pay per event

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 API

**Get Google Trends data without the failed runs.** This Google Trends scraper and API returns **interest over time**, **interest by region** (country, state/subregion, US metro/DMA) and **related queries** (top & rising, including *Breakout*) for one or many keywords - for any country, time range, category and Google property (Web, Images, News, YouTube, Shopping).

It was built for one thing: **reliability**. Google Trends answers automated traffic with `429 Too Many Requests` very aggressively. This scraper handles it for you with cookie sessions, exponential backoff, IP rotation and automatic proxy fallback - and it never silently returns an empty dataset: every run ends with a per-keyword status report.

**Tested before release: 24/24 test runs passed** (23 data runs succeeded across geos, time ranges, properties and comparison mode, plus 1 invalid-input run correctly rejected with a clear error), **~12 s average run time**.

### What can you use Google Trends data for?

- **SEO & keyword research** - find rising search queries, breakout keywords and seasonal peaks before you write.
- **Market & product research** - compare brands, products or categories over 5 years or since 2004.
- **E-commerce & dropshipping** - spot trending products on Google Shopping and YouTube.
- **Finance & crypto signals** - feed daily/hourly search interest into models and dashboards.
- **Local marketing** - see which countries, states or US metros (DMA) search a term most.
- **AI agents & automations** - call it from Make, Zapier, n8n, LangChain or Apify's MCP server and get clean JSON back.

### Why this Google Trends scraper?

| | This Actor |
|---|---|
| Reliability | 24/24 test runs passed, ~12 s average; every keyword gets an explicit status |
| 429 / rate-limit handling | Cookie (NID) bootstrap, per-session browser fingerprints, exponential backoff with jitter, new IP on every block |
| Proxy fallback | Your proxy -> Apify datacenter -> Apify residential -> direct, switched automatically when one gets blocked |
| Empty results | Never silent: every keyword gets a status (`SUCCEEDED`, `PARTIAL`, `NO_DATA`, `FAILED`) with the reason |
| Clean schema | One flat, consistent schema (same columns on every row) - spreadsheet, BI and LLM friendly. Nested per-keyword format optional |
| Honest about gaps | When Google withholds a section (e.g. city-level regions), the run summary says so instead of returning silent blanks |
| Input | Keywords **or** Google Trends URLs, presets or custom dates, IANA timezones, input validated with clear error messages |
| Speed & cost | Pure HTTP (no browser), 256 MB memory, a single keyword typically finishes in ~10-15 s |

### How to use it

1. Click **Try for free**.
2. Enter your **search terms** (or paste a Google Trends explore URL).
3. Optionally choose a **location**, **time range**, **category** and **property**.
4. Click **Start** and download results as JSON, CSV, Excel or via API.

### Input example

```json
{
  "searchTerms": ["chatgpt", "gemini", "claude"],
  "geo": "US",
  "timeRange": "today 12-m",
  "property": "",
  "category": 0,
  "includeInterestOverTime": true,
  "includeInterestByRegion": true,
  "regionResolution": "AUTO",
  "includeRelatedQueries": true,
  "compareTerms": false,
  "outputFormat": "flat"
}
```

Custom date range:

```json
{ "searchTerms": ["world cup"], "timeRange": "custom", "startDate": "2022-10-01", "endDate": "2022-12-31", "geo": "GB" }
```

| Field | Description |
|---|---|
| `searchTerms` | Keywords or Google Trends URLs (up to 500). |
| `compareTerms` | `true` = query in groups of up to 5 so values are relative to each other (Google "compare" view). |
| `geo` | Empty = Worldwide, `US`, `GB`, `US-CA`, `US-NY-501` (metro)... |
| `timeRange` | `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`, `custom`. Aliases like `7d`, `90d`, `5y` also work via API. |
| `startDate` / `endDate` | `YYYY-MM-DD` (or `YYYY-MM-DDTHH` for hourly ranges up to 7 days) when `timeRange` = `custom`. |
| `category` | Google Trends category ID (0 = all). |
| `property` | `""` Web, `images`, `news`, `youtube`, `froogle` (Shopping). |
| `timezone` | `UTC`, `America/New_York`, `UTC+2` or minutes offset. |
| `regionResolution` | `AUTO`, `COUNTRY`, `REGION`, `DMA`, `CITY`. City-level data is often withheld by Google; the Actor then falls back to subregions and says so. |
| `includeRelatedTopics` | Experimental, off by default: Google currently withholds related topics from automated sessions, so this section is normally empty. |
| `outputFormat` | `flat` (default) or `perTerm`. |
| `proxyConfiguration`, `proxyFallback`, `maxRetries`, `maxConcurrency` | Reliability controls (defaults are good). |

### Output example

Every row has the same columns; `recordType` tells you what it is (`interestOverTime`, `interestByRegion`, `relatedQuery`). Columns that don't apply are `null`.

```json
[
  { "recordType": "interestOverTime", "searchTerm": "bitcoin", "geo": "US", "timeRange": "Past 12 months", "date": "2025-10-26T00:00:00.000Z", "dateFormatted": "Oct 26 - Nov 1, 2025", "value": 31, "isPartial": false },
  { "recordType": "interestByRegion", "searchTerm": "bitcoin", "geo": "US", "regionCode": "US-WY", "regionName": "Wyoming", "regionResolution": "REGION", "value": 82 },
  { "recordType": "relatedQuery", "searchTerm": "bitcoin", "geo": "US", "rankType": "top", "rank": 1, "query": "bitcoin price", "value": 100, "formattedValue": "100", "link": "https://trends.google.com/trends/explore?q=bitcoin+price&date=today+12-m&geo=US" },
  { "recordType": "relatedQuery", "searchTerm": "chatgpt", "geo": "Worldwide", "rankType": "rising", "rank": 1, "query": "how to use chatgpt effectively", "value": 2650, "formattedValue": "+2,650%", "isBreakout": false }
]
```

The Output tab has ready-made table views: **Interest over time**, **Interest by region** and **Related queries**. With `outputFormat: "perTerm"` you get one item per keyword with nested arrays instead.

#### Run summary

Each run stores a summary in the key-value store record **`OUTPUT`**: per-keyword status and row counts, errors, data-availability notes (for example when Google withheld city-level data), number of requests/retries/429s and which connection succeeded. Use it in pipelines to detect partial results.

### Pricing

Simple **pay per event** pricing - you pay only for what you get:

| Event | Price | When |
|---|---|---|
| Run start (`apify-actor-start`) | **$0.02** per run | Once when the run starts |
| Keyword report (`keyword-report`) | **$0.002** per keyword | Each search term that returns data (all requested sections: interest over time, by region, related queries) |

Examples: 1 keyword = **$0.022**, 10 keywords = **$0.04**, 100 keywords = **$0.22**. You are **not charged** for keywords that fail or have no data. A keyword report is one keyword, not one row - a single keyword can produce 100+ flat rows at no extra charge. Set a *maximum cost per run* in the run options and the Actor stops cleanly when it is reached. Standard Apify platform usage applies per your plan.

### Use it from AI agents (MCP)

This Actor is ready for AI agents via the [Apify MCP server](https://mcp.apify.com) (Claude, Cursor, ChatGPT and any MCP client). An agent only needs `searchTerms`; everything else has sensible defaults. Example tool call: `{"searchTerms": ["electric bikes"], "geo": "DE", "timeRange": "today 5-y", "includeInterestByRegion": false}`. Results are flat, typed JSON rows with a documented schema, and the run summary explains any missing data so the agent can react instead of guessing.

### FAQ

**Is scraping Google Trends legal?** Google Trends data is public and aggregated (no personal data). Make sure your use complies with Google's terms and the laws that apply to you.

**What do the values mean?** 0-100 relative interest: 100 is the peak for the chosen term, place and time. With `compareTerms` the scale is shared across up to 5 terms. Values are not absolute search volumes.

**Why are values different from yesterday / from the website?** Google samples its data; small fluctuations between requests are normal, especially for low-volume terms and the tails of related-query lists.

**Do you return related topics?** No. Google currently withholds the *related topics* list from all automated (not logged-in) sessions, so it is always empty for every scraper. The `includeRelatedTopics` option is kept as an experimental switch (off by default) in case Google changes this. Related queries (top & rising) are fully supported.

**Can I get city-level data?** You can request `regionResolution: "CITY"`, but Google often withholds city-level breakdowns for automated sessions. When that happens the Actor automatically returns subregion (state/province) data instead and notes it in the run summary. Country and subregion (state/province) breakdowns work reliably.

**How many keywords can I run?** Up to 500 per run. Large batches are processed with gentle concurrency to avoid rate limits.

**Do I need a proxy?** The default Apify Proxy works for most runs. If Google blocks the datacenter IPs, the Actor falls back to residential proxy (if your Apify plan includes it) and then to a direct connection automatically.

**What if a run still fails?** The Actor retries each request up to 8 times with new IPs. If a keyword still fails, the summary says why and you are not charged for it. Please open an issue - we respond quickly.

### Limits

- Max 5 terms per comparison group (Google limit); values aren't comparable across groups.
- Hourly custom ranges max 7 days; data starts 2004-01-01.
- Related topics are not available (withheld by Google for automated sessions).
- City-level regions are often withheld by Google; the Actor then returns subregion-level data and says so in the summary.
- The overview table shows all row types; filter by the `recordType` column (or use `outputFormat: "perTerm"`).
- Very low-volume keywords return `NO_DATA` (Google shows "not enough data").
- Values are relative indices (0-100), not absolute search volumes.

# Actor input Schema

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

Keywords to look up on Google Trends, e.g. \["bitcoin", "ethereum"]. You can also paste Google Trends explore URLs (https://trends.google.com/trends/explore?q=...); their q, geo, date, cat and gprop parameters are used. Up to 500 terms per run.

## `compareTerms` (type: `boolean`):

If enabled, terms are queried together (groups of up to 5, like the Google Trends compare view) so their 0-100 values are relative to each other. If disabled (default), each term is queried on its own and scaled 0-100 independently.

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

Leave empty for Worldwide. Otherwise an ISO country code ("US", "GB", "DE", "IN"), a region ("US-CA", "GB-ENG") or a US metro/DMA ("US-NY-501").

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

Preset time range, or "custom" to use Start date / End date below.

## `startDate` (type: `string`):

Used when Time range = Custom. Format YYYY-MM-DD (earliest 2004-01-01). For hourly data use YYYY-MM-DDTHH (max 7-day span).

## `endDate` (type: `string`):

Used when Time range = Custom. Format YYYY-MM-DD. Defaults to today.

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

Google Trends category ID. 0 = All categories. Common IDs: 3 Arts & Entertainment, 5 Computers & Electronics, 7 Finance, 8 Games, 11 Home & Garden, 12 Business & Industrial, 13 Internet & Telecom, 14 People & Society, 16 News, 18 Shopping, 20 Sports, 22 Books & Literature, 44 Beauty & Fitness, 45 Health, 47 Autos & Vehicles, 66 Pets & Animals, 67 Travel, 71 Food & Drink, 174 Science, 958 Jobs & Education, 299 Online Communities, 533 Reference, 29 Real Estate, 19 Law & Government.

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

Which Google search product the interest is measured on.

## `timezone` (type: `string`):

Timezone used for dates in interest over time: IANA name ("America/New_York", "Europe/Prague"), "UTC+2", or Google's offset in minutes west of UTC ("300" = UTC-5). Default UTC.

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

Language for region and topic names (Google hl parameter), e.g. en-US, de, fr, es, ja.

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

Timeline of search interest (0-100).

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

Breakdown by country (worldwide) or subregion/metro/city (inside a country).

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

Granularity of Interest by region. Auto = countries for Worldwide, subregions (states/provinces) inside a country. DMA = US metros. City: Google often withholds city-level data for automated sessions; the Actor then falls back to subregion-level data and says so in the run summary.

## `includeLowSearchVolumeRegions` (type: `boolean`):

Also return regions with very low volume / value 0.

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

Top and rising related search queries (incl. Breakout).

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

Experimental, off by default. Google currently withholds the related topics list from automated (not logged-in) sessions, so this section is normally empty. The run summary tells you when it was withheld. Related queries are unaffected.

## `outputFormat` (type: `string`):

Flat = one clean row per data point (best for spreadsheets, BI tools and AI agents; every row has the same columns, filter by recordType). Per term = one item per search term with nested arrays.

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

Google Trends rate-limits (HTTP 429) heavily. Apify Proxy is recommended. The Actor automatically falls back to other connection types if the selected one gets blocked.

## `proxyFallback` (type: `boolean`):

When Google keeps blocking the current connection, automatically switch: your proxy -> Apify datacenter -> Apify residential (if your plan has it) -> direct connection.

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

How many times a blocked/failed request is retried (with exponential backoff, a fresh cookie session and a new IP).

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

Search terms processed in parallel. Keep low (1-3) to avoid Google rate limits.

## `failOnNoData` (type: `boolean`):

Mark the run as FAILED when Google has not enough data for any term (useful in pipelines). By default the run succeeds and the summary explains why it is empty.

## Actor input object example

```json
{
  "searchTerms": [
    "chatgpt",
    "gemini"
  ],
  "compareTerms": false,
  "geo": "US",
  "timeRange": "today 12-m",
  "category": 0,
  "property": "",
  "timezone": "UTC",
  "language": "en-US",
  "includeInterestOverTime": true,
  "includeInterestByRegion": true,
  "regionResolution": "AUTO",
  "includeLowSearchVolumeRegions": false,
  "includeRelatedQueries": true,
  "includeRelatedTopics": false,
  "outputFormat": "flat",
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "proxyFallback": true,
  "maxRetries": 8,
  "maxConcurrency": 2,
  "failOnNoData": false
}
```

# Actor output Schema

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

No description

## `interestOverTime` (type: `string`):

No description

## `relatedQueries` (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 = {
    "searchTerms": [
        "chatgpt",
        "gemini"
    ],
    "geo": "US",
    "timeRange": "today 12-m",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("atlasdata/google-trends-scraper-reliable").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": [
        "chatgpt",
        "gemini",
    ],
    "geo": "US",
    "timeRange": "today 12-m",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("atlasdata/google-trends-scraper-reliable").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": [
    "chatgpt",
    "gemini"
  ],
  "geo": "US",
  "timeRange": "today 12-m",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call atlasdata/google-trends-scraper-reliable --silent --output-dataset

```

## MCP server setup

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

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/Th0myCkaA08AneMHS/builds/wYz5XBuYQb0TS13iL/openapi.json
