# Google Trends Scraper (`aurenic/google-trends-scraper`) Actor

Extract Google Trends data — interest over time, interest by region, related queries, and Trending Now — via Google's internal JSON API. No login, no API key, no browser.

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

## Pricing

from $0.25 / 1,000 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

Extract Google Trends data — interest over time, interest by region, related queries, and Trending Now — via Google's internal JSON API. No login, no API key, no browser, no personal data.

### What does Google Trends Scraper do?

Scrape every public Google Trends dataset in three modes:

- **Keyword analysis (Explore)** — compare up to 5 keywords in one query, across any country and any time window. Returns interest over time (0–100 timeline), interest by region (sub-national breakdown), and related queries (top + rising).
- **Trending Now** — the current trending searches for any country, with approximate traffic, publish time, and related news coverage. Uses Google's public RSS feed.
- **Both** — run keyword analysis and Trending Now in a single run.

Google Trends has no official public API. The announced one is a waitlisted alpha. The actor speaks to the same internal JSON endpoints the Trends website itself uses — `/trends/api/explore` → `/trends/api/widgetdata/*` — with the exact session handshake Google expects.

**Rising queries are the most useful output in the whole API** — they show what people are starting to search around a niche before it peaks.

### Output fields

#### Keyword analysis (`trends-query` record)

| Field | Description |
|---|---|
| keywords | The keyword set compared in this query |
| geo | Country/region code |
| timeRange | Time window |
| category | Google Trends category ID |
| interestOverTime | Array of `{ timestamp, formattedTime, values, isPartial }` — one entry per timeline point, `values` maps each keyword to its 0–100 score |
| interestByRegion | Array of `{ geoCode, geoName, value, hasData }` — sub-national breakdown |
| relatedQueries | Object with `top[]` and `rising[]` arrays — each entry has `query`, `value`, `formattedValue`, `link` |
| userConfig | Google's session classification (e.g. `USER_TYPE_SCRAPER`) |

#### Trending Now (`trending-search` record)

| Field | Description |
|---|---|
| geo | Country code |
| rank | Position in the trending list |
| keyword | Trending search term |
| approxTraffic | Approximate search volume (e.g. `20000+`) |
| pubDate | When the trend was published |
| pictureUrl / pictureSource | Associated image |
| newsItems | Array of `{ title, url, source, snippet }` — related news coverage |

### Who is it for?

- **SEO and content teams** finding keyword trends before they peak, and planning content around rising queries
- **E-commerce and DTC brands** reading seasonality over 5 years to plan inventory and ad budget
- **Market researchers** comparing the same product across countries to decide launch order
- **Journalists and content creators** pulling today's trending searches with approximate volume
- **Brand teams** tracking share of search against competitors on a normalised 0–100 scale
- **Data scientists and quant analysts** feeding search-interest signals into forecasting models

### Pricing

**$0.40 per 1,000 results.** No subscription.

| Results | Cost |
|---|---|
| 100 | $0.04 |
| 1,000 | $0.40 |
| 10,000 | $4.00 |

### How to use it

1. Pick a **Mode**.
2. Enter **Keywords** (Explore), pick **Trending Now Countries**, or both.
3. Choose **Geography** and **Time Range**.
4. Toggle which datasets to include: interest over time, interest by region, related queries.
5. Click **Start**.

### Output example

```json
{
  "recordType": "trends-query",
  "keywords": ["bitcoin", "ethereum"],
  "geo": "US",
  "timeRange": "today 12-m",
  "category": 0,
  "interestOverTime": [
    { "timestamp": "1705276800", "formattedTime": "Jan 14 – 20, 2024", "values": { "bitcoin": 47, "ethereum": 38 }, "isPartial": false },
    { "timestamp": "1705881600", "formattedTime": "Jan 21 – 27, 2024", "values": { "bitcoin": 51, "ethereum": 41 }, "isPartial": false }
  ],
  "interestByRegion": [
    { "geoCode": "US-CA", "geoName": "California", "value": 100, "hasData": true },
    { "geoCode": "US-NY", "geoName": "New York", "value": 87, "hasData": true }
  ],
  "relatedQueries": {
    "top": [
      { "query": "bitcoin price", "value": 100, "formattedValue": "100", "link": "/trends/explore?q=bitcoin+price" },
      { "query": "ethereum price", "value": 62, "formattedValue": "62", "link": "" }
    ],
    "rising": [
      { "query": "bitcoin halving 2028", "value": 3200, "formattedValue": "+3,200%", "link": "" },
      { "query": "ethereum etf approval", "value": 1500, "formattedValue": "Breakout", "link": "" }
    ]
  },
  "userConfig": { "userType": "USER_TYPE_SCRAPER" },
  "scrapedAt": "2026-09-21T12:00:00.000Z"
}
```

Trending Now output:

```json
{
  "recordType": "trending-search",
  "geo": "US",
  "rank": 1,
  "keyword": "hurricane watch",
  "approxTraffic": "200000+",
  "pubDate": "Mon, 21 Sep 2026 09:00:00 GMT",
  "newsItems": [
    { "title": "Hurricane watch issued for Gulf Coast", "url": "https://...", "source": "Reuters", "snippet": "..." }
  ],
  "scrapedAt": "2026-09-21T12:00:00.000Z"
}
```

### Technical details

- **No browser, no CAPTCHA, no API key.** Uses Google's internal Trends JSON endpoints directly.
- **Cookie-session handshake.** The famous Google Trends 429 is not a rate limit — it's a missing `NID` cookie. The actor warms the session with a request to `/trends/explore`, captures the cookie **even from a 429 response**, and retries with it. This is the fix most broken scrapers miss.
- **Anti-XSSI prefix stripping.** Google prefix responses with `)]}'` to break naive `JSON.parse` calls. The actor strips it before parsing.
- **Self-throttled** at a configurable `requestDelayMs` (default 1500 ms) — Google's limiter cuts sessions at ~800 ms per request.
- **Datacenter IPs work.** With a valid cookie session, Google Trends accepts datacenter requests. Proxy support is available but disabled by default.
- **Keyword batching.** Google allows up to 5 keywords per Explore query. Larger lists are automatically split.

### Known limits

- **Related Topics return empty.** Google marks keyless sessions as `USER_TYPE_SCRAPER`, and the RELATED\_TOPICS widget returns `[]` for such sessions. The token is signed over the request — editing `userType` yields 401. Related **Queries** work fine; only Related **Topics** is affected.
- **Session-scoped data.** Google Trends returns normalised 0–100 values, not absolute search volumes. Values are comparable within a query, not across queries. Run keyword sets together to compare them.
- **Google changes endpoints.** The internal API is undocumented and can shift. The actor logs the exact failing URL if a call fails, making recovery fast.
- **Trending Now geo coverage varies.** Some countries return a rich feed, others return few or no items.
- **No Google account required**, and no personal data is collected — Google Trends publishes only aggregated search interest.

### FAQ

**Do I need an API key?** No. Google Trends has no public API. The actor uses the same endpoints the Trends website uses, keyless.

**Do I need a proxy?** No. With a valid cookie session, Google Trends accepts datacenter IPs. Enable `useProxy` only if you see repeated 429s.

**Why is `interestByRegion` empty for some keywords?** Not every keyword has sub-national data. Low-volume terms are often aggregated to the country level only.

**Why is `relatedQueries.topics` missing?** Google marks keyless sessions `USER_TYPE_SCRAPER` and returns empty for Related **Topics**. Related **Queries** (top + rising) work fine. This is a Google-side restriction, not a bug.

**How do I compare two keyword sets?** Google normalises each query independently. To compare keywords, put them all in one `keywords` array — the actor batches them 5 at a time, and each query's 0–100 scale is internally consistent.

**How do I export data?** After a run, go to Storage → Export as JSON, CSV, Excel.

### Support

Open an issue on the Actor's page for bugs or feature requests.

# Actor input Schema

## `mode` (type: `string`):

What to fetch from Google Trends.

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

Keywords to analyse. Up to 5 are compared in one query (Google's limit); larger lists are batched automatically.

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

Country or region code (US, GB, DE, FR, IN, BR, JP, …). Leave empty for worldwide.

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

Google Trends time window.

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

Google Trends category ID (0 = all categories).

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

Return the 0–100 timeline for each keyword.

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

Return sub-national breakdown per region.

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

Return top and rising related queries. Rising queries are the most useful output in the whole API.

## `trendingGeos` (type: `array`):

Country codes for Trending Now RSS (US, GB, DE, FR, IN, BR, JP, …). Used in trending and both modes.

## `requestDelayMs` (type: `integer`):

Delay between widget calls. Google's limiter cuts sessions at ~800ms per request; default 1500ms is safe.

## `useProxy` (type: `boolean`):

Google Trends works from datacenter IPs with a valid cookie session. Enable only if you hit repeated 429s.

## Actor input object example

```json
{
  "mode": "explore",
  "keywords": [
    "bitcoin",
    "ethereum"
  ],
  "geo": "US",
  "timeRange": "today 12-m",
  "category": 0,
  "includeInterestOverTime": true,
  "includeInterestByRegion": true,
  "includeRelatedQueries": true,
  "trendingGeos": [
    "US"
  ],
  "requestDelayMs": 1500,
  "useProxy": false
}
```

# Actor output Schema

## `results` (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"
    ],
    "trendingGeos": [
        "US"
    ]
};

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

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

```

## MCP server setup

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