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

Get Google Trends data for any keyword: interest over time, interest by region, related queries and trend stats, plus the Trending Now searches. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/nice_dev/google-trends-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** SEO tools, News, MCP servers
- **Stats:** 3 total users, 1 monthly users, 92.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.27 / 1,000 keyword reports

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

### 📈 What is Google Trends Scraper?

**Google Trends Scraper** extracts **[Google Trends](https://trends.google.com) data for any keyword**: **interest over time, interest by country, state, metro area or city, top and rising related queries**, plus **ready-made figures** (average, peak and its date, latest value, trend direction). It also **compares keywords on one scale — more than 5 of them** — and lists the **searches trending now** in any country, with their search volume, growth, start and end time, and **news articles**. It works as a **Google Trends API alternative**: run it on a schedule, call it from your code, or plug it into Make, Zapier or n8n.

Type a **keyword** (`python`), pick a country and a time range, click **Start**, and download the report in JSON, CSV or Excel. No login, nothing to set up. Several keywords and countries in one run, one report each — a comparison of 9 keywords takes 10 to 40 seconds, and a whole Trending Now list (300 to 2,000 searches) comes in a few seconds.

### 📋 What data can you extract from Google Trends?

Three kinds of results in one dataset (`recordType`): a **keyword report** per keyword and location, a **comparison** per location, a **trending search** per search trending now. 54 fields:

| Category | What you get |
| --- | --- |
| 📈 **Interest over time** | the 0-100 curve point by point, with its dates and which point is still unfinished |
| 🧮 **Ready-made figures** | average, peak and when it happened, lowest, latest value, rising / falling / stable and by how much |
| 🌍 **Interest by region** | countries, states, metro areas or cities with their score, the top region named, cities with coordinates |
| 🔎 **Related queries** | the 25 top and 25 rising queries with their score or growth, "Breakout" flagged |
| 🏷️ **What was asked** | keyword, Google topic, location, time range, category, search type, language |
| 🆚 **Comparisons** | up to 50 keywords on one scale: each one's average, peak, latest value and share of the total, the most searched one, which keyword leads in each region |
| 🔥 **Trending Now** | the searches trending in a country over the last 4 hours to 7 days: rank, search volume (`200K+`), growth %, start and end time, still trending or not, related searches, categories |
| 📰 **News articles** (option) | the articles Google shows for each trending search: title, link, source, date, image |

Every field, with an example, is listed in the **Output** section below.

### ✅ Why use Google Trends Scraper?

- 📊 **Figures included**: average, peak, latest value and trend direction are computed for you, the unfinished last point of a curve never skews them.
- 🆚 **More than 5 keywords on one scale**: Google compares 5 at most; the Actor puts up to 50 on the same scale, so you can rank a whole list of brands or products.
- 🔥 **Trending Now with figures**: search volume, growth, how long each trend has lasted, its categories and — as an option — its news articles, for any country, filtered by category, volume, date or keyword.
- 🧩 **Several keywords and countries in one run**: keywords × locations, one report each, with a cap per source — and keyword reports, comparisons and Trending Now can all go in the same run.
- 🌐 **Region detail**: countries, states, US metro areas or cities with their coordinates; regions Google has too little data for are left out, or kept with an empty value — never a false 0.
- 🧠 **Google topics**: look a keyword up as a Google topic to count every way people search for it.
- 🔔 **Monitoring built in**: tick **Only new results**, schedule the Actor, and each run returns (and charges) only what has moved since the last one.
- 🛡️ **Reliable at volume**: a request Google turns away is retried at once on a fresh proxy session, so a long list of keywords goes through.
- 🔌 API, scheduling, integrations (Make, Zapier, n8n, Google Sheets…), and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape Google Trends

1. Create a free Apify account.
2. Open **Google Trends Scraper** and type a **Keyword** (e.g. `python`), or paste your own Google Trends URLs into **Google Trends URLs**.
3. Pick a **Country or region**, a **Time range**, a **Category** and a **Search type** if you need them; tick **Compare the keywords on one scale** to put them on one scale.
4. For the searches trending now, add country codes to **Trending Now countries** (`US`, `GB`) and pick the period.
5. Set **Max results** (100 by default, 0 = no limit) — and **Max results per source** when you run several keywords — then click **Start**.
6. Download the dataset in JSON, CSV, Excel or via API.

### 💰 How much does it cost to scrape Google Trends?

This Actor uses **pay per event** pricing: you pay for each result delivered plus a small fee for each run start.

| What you get | Price per 1,000 (Free plan → Gold) |
| --- | --- |
| **Keyword report**: one keyword (or one category) in one location, with its curve, regions, related queries and figures | **$0.63** → $0.27 |
| **Compared keyword**: each keyword of a comparison row (a comparison of 5 keywords = 5 compared keywords) | **$4.49** → $4.46 |
| **Trending search**: one search of a Trending Now list | **$0.89** → $0.19 |
| + **Trending search news** (option, off by default): added to a trending search delivered WITH at least one news article; a trend without articles is not charged for them | **+$0.45** → +$0.42 |
| **Run start**: once per run | **$0.01** |

Examples on the Free plan: 100 keyword reports cost 100 × $0.00063 + $0.01 = **$0.07**; a Trending Now list of 1,000 searches for one country costs 1,000 × $0.00089 + $0.01 = **$0.90** (with a Gold subscription: $0.04 and $0.20).

A keyword with no data at all is not saved and not charged; a trending search dropped by a filter costs nothing. Platform usage (compute, proxy) is included in the price.

### ⚙️ Input

```json
{
    "query": "python",
    "location": "US",
    "timeRange": "today 12-m",
    "maxItems": 10
}
```

Several keywords and countries, a custom period, only what is new since the last run:

```json
{
    "searchQueries": ["python", "java", "rust"],
    "locations": ["US", "GB", "FR"],
    "timeRange": "custom",
    "customTimeRange": "2024-01-01 2024-06-30",
    "maxItemsPerQuery": 1,
    "onlyNew": true,
    "stateKey": "languages"
}
```

Nine keywords on one scale (the first one is the anchor of every group of 5, pick a popular one):

```json
{
    "searchQueries": ["python", "java", "javascript", "rust", "golang", "kotlin", "swift", "ruby", "php"],
    "location": "US",
    "compareKeywords": true
}
```

The searches trending now in two countries, sports only, still trending, with their news articles:

```json
{
    "trendingGeos": ["US", "GB"],
    "trendingHours": "24",
    "trendingCategories": ["17"],
    "trendingActiveOnly": true,
    "includeTrendingNews": true,
    "maxItemsPerQuery": 20
}
```

Or with your own Google Trends pages:

```json
{
    "startUrls": [
        { "url": "https://trends.google.com/trends/explore?q=python,java&geo=US&date=today%205-y" },
        { "url": "https://trends.google.com/trends/explore?cat=71&geo=FR&date=now%207-d&gprop=youtube" }
    ],
    "maxItems": 20
}
```

| Field | Notes |
| --- | --- |
| `query`, `searchQueries` | A keyword exactly as typed in Google (`python`), or a Google topic id (`/m/05z1_`); `searchQueries` adds more keywords, one report each. |
| `location`, `locations` | Google location code: `US`, `GB`, `FR`, a state (`US-CA`), a US metro area (`US-CA-807`). Empty = worldwide. Every keyword is analysed in every location (max 2000 searches per run). |
| `startUrls` | Google Trends pages: an Explore page (`https://trends.google.com/trends/explore?q=python&geo=US`) — its keywords, country, time range, category and search type are used as they are, and a page of several keywords (q=python,java) gives one comparison (one place per page: Google's comparison across places, q=python,java\&geo=US,FR, is refused) — or a Trending Now page (`https://trends.google.com/trending?geo=US&hours=24`), its category and its "active only" setting kept. |
| `timeRange` | Period of the curve: `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` (2004 to now) or `custom`. |
| `customTimeRange` | With a custom time range: two days (`2024-01-01 2024-06-30`) or two hours, under 8 days (`2025-03-01T10 2025-03-03T10`). |
| `category` | Google category id, the cat value in the address of an Explore page: `0` is all categories, `71` Food & Drink, `5` Computers & Electronics. The result names it. With a category and no keyword you get the category's own curve and related queries. |
| `property` | Which Google search the data comes from: `images`, `news`, `froogle` (Shopping) or `youtube`; empty is the web. |
| `resolveTopics` | Look each keyword up as a Google topic and analyse the topic: it counts all the ways people search for it, in every language. The topic found is in the result. Not applied to a comparison: its keywords are compared as typed. |
| `timezoneOffsetMinutes` | Minutes west of UTC as Google expects it: `0` is UTC, `300` is New York, `-60` is Paris. Only the formattedTime text of each point follows it: the points, their days and every date in the results stay in UTC. |
| `language` | Language of the region names and queries: `en-US`, `fr`, `de`, `es`. |
| `compareKeywords` | Compare the keywords of a location on one common scale instead of one report each: one comparison row per location, up to 50 keywords. With a single keyword you get its normal report. |
| `includeInterestOverTime`, `includeInterestByRegion`, `includeRelatedQueries` | What each report holds (all on by default; at least one must stay on). A comparison always holds its curve. |
| `regionResolution` | Level of the region list: `auto` (the level Google gives the place: countries for the world, regions inside a country, metro areas inside a US state), `COUNTRY`, `REGION`, `DMA` (US metro areas) or `CITY`. A level you pick is sent as it is, and Google refuses the ones a place has none of (countries inside a country, regions inside a state). |
| `includeLowVolumeRegions` | Keep the regions Google has too little data for, with an empty value (never 0). |
| `trendingGeos` | Country codes (`US`, `GB`, `FR`): each gives its Trending Now list. Empty = no Trending Now. |
| `trendingHours` | Trends started in the last `4`, `24`, `48` or `168` hours. |
| `trendingCategories` | Keep only these Trending Now categories (`17` is Sports, `4` Entertainment). Empty = all. |
| `trendingActiveOnly`, `includeTrendingNews` | Only the searches still trending; the news articles Google shows for each trending search (paid option, off by default). |
| `minSearchVolume` | Keep only the trending searches with at least this many searches: `200`, `1000`, `10000`. |
| `maxItems` | Stop after this many results for the whole run (`0` = unlimited); each keyword of a comparison counts as one result. |
| `maxItemsPerQuery` | Cap for EACH source (a keyword in a location, a comparison, a Trending Now country); each keyword of a comparison counts as one result. 0 = no cap. |
| `postedAfter`, `postedBefore` | Trending Now only: the searches that started after / before this date: `2026-10-01`, or a period before now (`6 hours`, `2 days`). |
| `excludeKeywords` | Trending Now only: drop the searches whose title contains one of these words (case and accents ignored). |
| `stateKey`, `onlyNew`, `resetState` | Monitoring: only what a run with this memory key has not delivered (`us-trending`); `resetState` forgets the memory. |
| `proxyConfiguration`, `requestsPerSession`, `maxConcurrency`, `maxRequestsPerMinute`, `minRequestIntervalMs`, `maxRequestRetries`, `debugLog` | Advanced: the Apify proxy by default (included in the price; the residential proxy is not available), requests per IP address, speed and retries. |

### 📦 Output

One real result, shortened (the curve and the lists keep their first entries only):

```json
{
    "id": "kw:python|US|today 12-m|0|web",
    "recordType": "keyword",
    "url": "https://trends.google.com/trends/explore?q=python&geo=US&date=today%2012-m",
    "keyword": "python",
    "topicId": null,
    "geo": "US",
    "geoName": "United States",
    "timeRange": "today 12-m",
    "startDate": "2025-10-05T00:00:00.000Z",
    "endDate": "2026-10-04T00:00:00.000Z",
    "resolution": "WEEK",
    "category": 0,
    "categoryName": "All categories",
    "property": "web",
    "averageInterest": 60.1,
    "peakInterest": 100,
    "peakDate": "2026-06-14T00:00:00.000Z",
    "latestInterest": 39,
    "latestIsPartial": true,
    "trendDirection": "falling",
    "trendChangePercent": -18.6,
    "minInterest": 37,
    "topRegion": "Wyoming",
    "topRegionCode": "US-WY",
    "topRegionValue": 100,
    "topRelatedQuery": "what is python",
    "topRisingQuery": "walmart near me",
    "interestOverTime": [{ "date": "2025-10-05T00:00:00.000Z", "time": 1759622400, "formattedTime": "Oct 5 – 11, 2025", "value": 59, "isPartial": false }],
    "interestByRegion": [{ "geoCode": "US-WY", "geoName": "Wyoming", "value": 100 }],
    "regionResolution": "REGION",
    "relatedQueriesTop": [{ "query": "what is python", "value": 100, "formattedValue": "100", "link": "https://trends.google.com/trends/explore?q=what+is+python&date=today+12-m&geo=US" }],
    "relatedQueriesRising": [{ "query": "walmart near me", "growthPercent": null, "formattedValue": "Breakout", "isBreakout": true, "link": "https://trends.google.com/trends/explore?q=walmart+near+me&date=today+12-m&geo=US" }],
    "language": "en-US",
    "source": "python",
    "scrapedAt": "2026-10-06T00:24:44.507Z"
}
```

A comparison row (real, shortened: the keys left out are the same as above, empty for a comparison):

```json
{
    "id": "cmp:python~java~javascript~rust~golang|US|today 12-m|0|web",
    "recordType": "comparison",
    "keyword": "python vs java vs javascript vs rust vs golang",
    "keywords": ["python", "java", "javascript", "rust", "golang"],
    "winner": "python",
    "anchorKeyword": null,
    "keywordStats": [{ "keyword": "python", "average": 60, "peak": 100, "peakDate": "2026-06-14T00:00:00.000Z", "latest": 38, "sharePercent": 46.2, "regionsLed": 46 }],
    "interestOverTime": [{ "date": "2025-10-05T00:00:00.000Z", "time": 1759622400, "formattedTime": "Oct 5 – 11, 2025", "values": [59, 28, 9, 25, 2], "isPartial": false }],
    "interestByRegion": [{ "geoCode": "US-DC", "geoName": "District of Columbia", "values": [62, 17, 7, 13, 1], "leader": "python" }]
}
```

A trending search with its news articles (real, shortened):

```json
{
    "id": "trend:US|robert kelker kelly|2026-10-05T17:50:00.000Z",
    "recordType": "trending",
    "title": "robert kelker kelly",
    "geo": "US",
    "rank": 1,
    "searchVolume": 200000,
    "formattedSearchVolume": "200K+",
    "growthPercent": 1000,
    "startedAt": "2026-10-05T17:50:00.000Z",
    "endedAt": null,
    "isActive": true,
    "durationMinutes": 775,
    "trendBreakdown": ["robert kelker kelly", "days of our lives"],
    "categories": [{ "id": 4, "name": "Entertainment" }],
    "newsArticles": [{ "title": "Robert Kelker-Kelly Dies: ‘Days Of Our Lives’, ‘Another World’ Actor Was 62", "url": "https://deadline.com/2026/10/robert-kelker-kelly-dead-days-of-our-lives-another-world-1237146925/", "source": "Deadline", "publishedAt": "2026-10-05T19:32:00.000Z", "imageUrl": "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTJ4j9lG98oDtHhQ_5I3f3LGBvusYedVAX7f04Vqtb_HD2gQyXryDNP2o_VXpg" }]
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### All 54 fields

| Fields | What you get |
| --- | --- |
| `id`, `recordType`, `url` | the result's stable id, its kind (`keyword`, `comparison` or `trending`), the same view on trends.google.com |
| `keyword`, `topicId`, `topicTitle`, `topicType`, `topicSuggestions` | the keyword analysed; the Google topic when the keyword is one or was looked up, with every topic suggested |
| `geo`, `geoName`, `timeRange`, `startDate`, `endDate`, `resolution`, `category`, `categoryName`, `property`, `language`, `source` | where, when and what kind of search; the first and last point of the data; the step of the curve; the input it came from |
| `averageInterest`, `peakInterest`, `peakDate`, `latestInterest`, `latestIsPartial`, `minInterest` | the figures of the curve (the unfinished last point left out), and whether the last point is unfinished |
| `trendDirection`, `trendChangePercent` | `rising`, `falling` or `stable`: the last quarter of the curve against the first, within ±10 % |
| `interestOverTime` | one point per step: date, time, label, value 0-100 (empty when Google has no data), unfinished or not |
| `interestByRegion`, `regionResolution`, `topRegion`, `topRegionCode`, `topRegionValue` | the regions with their 0-100 score, best first; cities carry coordinates instead of a code |
| `relatedQueriesTop`, `relatedQueriesRising`, `topRelatedQuery`, `topRisingQuery` | the related queries with their score or growth in %; a "Breakout" has no number and `isBreakout` set |
| `keywords`, `keywordStats`, `winner`, `anchorKeyword` | comparison results: the keywords, their figures, the most searched one, the anchor of a comparison of more than 5 |
| `title`, `rank`, `searchVolume`, `formattedSearchVolume`, `growthPercent`, `startedAt`, `endedAt`, `isActive`, `durationMinutes`, `trendBreakdown`, `categories`, `newsArticles` | Trending Now results: the search, its place in Google's list, its volume and growth, when it started and ended, its related searches and categories, and its news articles |
| `scrapedAt` | ISO timestamp of the extraction |

### 💡 Tips

#### How to get more results

Add keywords to `searchQueries` and countries to `locations`: each keyword is analysed in each country. Google compares the interest of a keyword with its own highest point (100), so two reports are not on the same scale: use the comparison option to put several keywords on one.

#### How to reduce costs

The price is per result, so the levers are `maxItems`, `maxItemsPerQuery`, and `onlyNew` for recurring runs (a report whose last data point has not moved, or a trending search already delivered, is skipped and not charged). For Trending Now, the filters (`trendingCategories`, `minSearchVolume`, `trendingActiveOnly`, dates, `excludeKeywords`) drop searches for free, before any charge and before any news article is fetched. Leave out the map and the related queries (`includeInterestByRegion`, `includeRelatedQueries`) when you only need the curve: the run is faster.

#### Compare more than 5 keywords

Google compares 5 keywords at most. Tick `compareKeywords` with more: the Actor reads them in groups of 5 that all share the first keyword (the anchor), then puts every group on the anchor's scale, so the highest point of the whole row is 100. Put a popular keyword first: if Google has no data for the anchor in a group, that comparison is not made (the run says why) rather than given on a false scale; if the anchor is very small next to the others, the row comes with a warning in the log. On the ranges of the last hours (`now 1-H`, `now 4-H`, `now 1-d`) Google sets the window of each group at the minute it is read: the row keeps the time steps every group has (a step or two fewer at the edges, at most). With 5 keywords or fewer the averages are Google's own. In the region map of a comparison, the values are each keyword's share of the searches in that region (they add up to 100), and `leader` names the keyword ahead.

#### Trending Now and news articles

Each country of `trendingGeos` gives its whole Trending Now list for the period (about 80 searches in 4 hours and 2,000 in 7 days for the US). `rank` is the search's place in Google's list before any filter. `searchVolume` is the lower bound of Google's bracket (`200K+` → 200000). With `includeTrendingNews`, the news articles are fetched only for the searches you keep, after the filters and the caps.

#### Which time range and step

Google picks the step of the curve from the range: minutes for the last hours, hours for 7 days, days up to 9 months, weeks up to 5 years, months for 2004 to now. The last point is often unfinished (`isPartial`): it stays in the curve but never enters the figures.

#### Monitoring: only the new results

Tick **Only new results** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the reports whose last data point has not moved since the one delivered, and the trending searches already delivered (same country, search and start time): they are not saved and not charged. The memory lives in a named key-value store of your account (`google-trends-scraper-seen`, up to 150,000 results per key) and is only updated with results that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey`, and tick `resetState` once to start over. A trending search that does not pass a time-dependent filter yet (a relative "posted before" date, a minimum search volume) is checked again on the next run.

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one result per keyword and country, with the interest curve, the regions, the related queries and ready-made figures; a comparison of several keywords on one scale (`compareKeywords`); or the searches trending now in a country (`trendingGeos`). Actor id: `nice_dev/google-trends-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/google-trends-scraper`.

Smallest input, for a cheap first call:

```json
{
    "query": "python",
    "location": "US",
    "maxItems": 1
}
```

Key output fields: `keyword`, `geo`, `averageInterest`, `peakInterest`, `latestInterest`, `trendDirection`, `topRegion`, `topRelatedQuery` and `topRisingQuery`; the full curve, regions and queries are in `interestOverTime`, `interestByRegion`, `relatedQueriesTop` and `relatedQueriesRising`. A comparison adds `keywords`, `keywordStats` and `winner`; a trending search has `title`, `rank`, `searchVolume`, `growthPercent`, `startedAt`, `isActive` and, with the option, `newsArticles`.

Cost: pay per event, see the pricing section above. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

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

The Actor only reads what Google Trends shows publicly to any anonymous visitor: aggregated search interest and public news headlines. It logs in to nothing, and the results hold no personal data. You are responsible for using the data in compliance with Google's Terms of Service and applicable law. This Actor is not affiliated with Google.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request Google turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 300 seconds).

#### What does a result with "no data" mean?

When Google has no data at all for a keyword in that place and period (too few searches), the Actor saves nothing for it and does not charge it: the run's last line counts these reports. Inside a report, a point, a region or a query Google has no value for is empty (`null`), never 0.

#### Known limitations

- Values are relative (0-100, the highest point of the report is 100): two reports are not on one scale unless you compare the keywords in one run.
- Google gives the 25 top and 25 rising related queries, up to 250 countries, 51 US states, 210 US metro areas and 200 cities per map; cities with too little data have no value.
- Trending Now keeps the last 7 days at most, and Google has no Trending Now list for some countries (Luxembourg, Iceland…): such a country is said in the log and skipped, the other sources are delivered.
- With news articles, the trending searches are saved as their articles arrive, not in Google's order: sort on `rank` to get it back.
- A comparison is limited to 50 keywords per location; its first keyword must have data in every group of 5.
- Two runs sharing the same `stateKey` at the same time may both return the same new result.

**A run that reaches its timeout** stops itself about 45 seconds before it: no new report is asked, what it read is saved and, with `onlyNew`, remembered, and the run ends *Succeeded* with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).

**A run the platform stops without warning** (out of memory)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the results already saved are skipped — even a report whose data gained a point in between: none is delivered or charged twice, and `maxItems` still counts them (a comparison for each of its keywords).
- With `onlyNew`, the memory is saved within 2 seconds of each write: resurrect the stopped run and the results it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the results of its last 2 seconds once more.

#### Something doesn't work?

The last line of the log counts the results saved, the reports Google had no data for, the trending searches whose news articles could not be read (delivered without them, and not charged for them), and the requests that failed after every retry. Those requests are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause. If Google changes the shape of its answers, you are told instead of paying for blank rows: the report fails with the reason and is listed in `FAILED_REQUESTS`.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which keywords failed and why.

# Actor input Schema

## `startUrls` (type: `array`):

Paste Google Trends pages: an Explore URL (`https://trends.google.com/trends/explore?q=python&geo=US&date=today%2012-m`, its keywords, country, time range, category and search type are used as they are; several keywords give one comparison) or a Trending Now URL (`https://trends.google.com/trending?geo=US&hours=24`, its category and active-only setting kept too).

## `query` (type: `string`):

A search term (`python`) or a Google topic id (`/m/05z1_`). One report per keyword: interest over time, interest by region and related queries.

## `searchQueries` (type: `array`):

Several keywords in one run: one report per keyword (times each country below). Added to **Keyword**.

## `location` (type: `string`):

Google Trends location code: `US`, `GB`, `FR`, a state `US-CA`, a US metro `US-CA-807`. Empty = worldwide.

## `locations` (type: `array`):

Several locations in one run: each keyword is analysed in each location. Added to **Country or region**.

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

Period of the interest-over-time curve. Google picks the step: minute for 1-4 hours, 8 minutes for 1 day, hour for 7 days, day up to 9 months, week up to 5 years, month for 2004 – present.

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

Used when **Time range** is Custom: `2024-01-01 2024-06-30` (days) or `2025-03-01T10 2025-03-03T10` (hours, UTC, under 8 days).

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

Google Trends category id (0 = all categories; e.g. 71 = Food & Drink, 7 = Finance, 5 = Computers & Electronics). The id is the `cat` value in the address of an Explore page; the result names it in `categoryName`. With a category and no keyword, you get the category's own curve and related queries.

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

Which Google search the data comes from.

## `resolveTopics` (type: `boolean`):

Look up each keyword's Google topic (e.g. `tesla` → Tesla, Automotive company) and analyse the topic instead of the exact search term: it counts all the ways people search for it, in every language. The topic found is in topicId / topicTitle / topicType. A keyword with no topic is analysed as a search term. Not applied to a comparison: its keywords are compared as typed.

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

Minutes WEST of UTC, as Google expects it: 0 = UTC, 300 = New York (UTC-5), -60 = Paris (UTC+1). Only the `formattedTime` text of each point follows it (`5:00 AM` instead of `10:00 AM`): the points, their days and every date in the results stay in UTC.

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

Language of the region names and of the Trending Now searches (`en-US`, `fr`, `de`, `es`…).

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

Instead of one report per keyword (each on its own 0-100 scale), compare all the keywords of a location on ONE common scale: averages, winner and region leaders. Up to 5 keywords are compared by Google directly; beyond 5 (50 at most), the first keyword is used as an anchor in every group of 5 and the values are rescaled to it: put a popular one first. One row per location: each keyword in it counts as one result in Max results and is charged as one compared keyword. A single keyword gets its normal report.

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

The 0-100 curve, point by point, with average, peak, latest value and trend direction. A comparison always holds its curve: it is what the comparison is.

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

0-100 interest per country, state, metro or city (see **Region level**).

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

Level of **Interest by region**. Auto = the level Google gives the place: countries for worldwide, regions inside a country, metro areas inside a US state. A level you pick is sent as it is: Google refuses the ones a place has none of (countries inside a country, regions inside a state). Cities: Google gives values for the largest markets only (others have no value).

## `includeLowVolumeRegions` (type: `boolean`):

Keep the regions where Google has too little data, with value `null` (never 0).

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

Top 25 and rising 25 related queries, with their score or growth (`Breakout` = more than +5000%).

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

Country codes (`US`, `GB`, `FR`, `JP`…): each gives its Trending Now list. Empty = no Trending Now.

## `trendingHours` (type: `string`):

Trends started in the last 4, 24, 48 hours or 7 days (≈ 80 / 330 / 780 / 2,000 searches for the US).

## `trendingCategories` (type: `array`):

Keep only these categories. Empty = all.

## `trendingActiveOnly` (type: `boolean`):

Keep only the searches that are still trending (no end time yet).

## `minSearchVolume` (type: `integer`):

Keep only the trending searches with at least this many searches (Google's estimate: 200, 1000, 10000…). 0 = all.

## `includeTrendingNews` (type: `boolean`):

Add the news articles Google shows for each trending search (title, link, source, date, image). Charged per trending search with articles (see Pricing).

## `maxItems` (type: `integer`):

Maximum number of results for the whole run (keyword reports, compared keywords and trending searches). 0 = no limit.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH source (a keyword × location, a comparison, a Trending Now country), so that the first one cannot use up **Max results**. Each keyword of a comparison counts as one result. 0 = no cap.

## `postedAfter` (type: `string`):

Only the trending searches that started on or after this date: `2026-10-01`, or a period before now such as `6 hours`, `2 days` (API: full ISO date-times work too).

## `postedBefore` (type: `string`):

Only the trending searches that started before this date (same formats as **Started after**).

## `excludeKeywords` (type: `array`):

Drop the trending searches whose title contains one of these words (case and accents ignored).

## `onlyNew` (type: `boolean`):

Skip what a previous run (same **Memory key**) already delivered: trending searches already seen, and keyword reports whose data has not moved since (same last data point). Skipped results are not saved and not charged. First run = everything is new.

## `stateKey` (type: `string`):

Name of the memory used by **Only new results**. Give each schedule / task its own key (e.g. `us-trending`). Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) everything again. Untick it afterwards.

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

Apify Proxy or your own proxies. Keep the default: it is included in the price. The residential Apify proxy is not available.

## `requestsPerSession` (type: `integer`):

Requests sent through one proxy IP before switching to a fresh one. Keep the default.

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

Maximum number of requests processed in parallel (each on its own IP).

## `maxRequestsPerMinute` (type: `integer`):

Most requests to Google in any 60 seconds, all of them counted. Lower it if the log shows HTTP 429.

## `minRequestIntervalMs` (type: `integer`):

Smallest gap between two requests, in milliseconds. 0 = no gap.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed. A request Google turns away (HTTP 429) is retried on a new IP without using up these retries.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "startUrls": [],
  "query": "python",
  "searchQueries": [],
  "location": "US",
  "locations": [],
  "timeRange": "today 12-m",
  "category": 0,
  "property": "",
  "resolveTopics": false,
  "timezoneOffsetMinutes": 0,
  "language": "en-US",
  "compareKeywords": false,
  "includeInterestOverTime": true,
  "includeInterestByRegion": true,
  "regionResolution": "auto",
  "includeLowVolumeRegions": false,
  "includeRelatedQueries": true,
  "trendingGeos": [],
  "trendingHours": "24",
  "trendingCategories": [],
  "trendingActiveOnly": false,
  "minSearchVolume": 0,
  "includeTrendingNews": false,
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "excludeKeywords": [],
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "requestsPerSession": 40,
  "maxConcurrency": 4,
  "maxRequestsPerMinute": 120,
  "minRequestIntervalMs": 0,
  "maxRequestRetries": 5,
  "debugLog": 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 = {
    "query": "python",
    "location": "US",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/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 = {
    "query": "python",
    "location": "US",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/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 '{
  "query": "python",
  "location": "US",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/google-trends-scraper --silent --output-dataset

```

## MCP server setup

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