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

Google Trends scraper: interest over time, by region, and top and rising related queries for up to 25 keywords or Trends links, plus any country's Trending Now list. Each value is Google's 0 to 100 index against the keyword's own peak, not a search volume. $0.06 per 1,000 rows.

- **URL**: https://apify.com/dami_studio/google-trends-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** SEO tools, News
- **Features:** Limited permissions
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.06 / 1,000 google trends rows

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

**Type up to 25 keywords, or paste Google Trends links, and get Google Trends back as flat rows**:
one per point on the interest chart, one per region, one per related search, and one per entry in a
country's Trending Now list. No Google account and no API key.

Read this before you build on it. Every `value` is Google's own 0 to 100 index, not a search volume.
100 is the peak of the exact series you asked for, so changing the region, the time range or the
category rescales the whole thing, and two keywords pulled in separate runs are not comparable.
Google does not publish absolute search counts to anyone, so no tool can give you them.

| | |
|---|---|
| **Input** | Up to 25 keywords or Trends links, and country codes for Trending Now |
| **Output** | One row per datapoint, region, related query or trending search |
| **Ceiling** | 20,000 rows per run |
| **Account needed** | None, and no Google API key |
| **Price** | $0.06 per 1,000 rows on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 83,000 |

### 🔍 What Google Trends Scraper does

It pulls the three panels the Trends website shows for a keyword, and flattens each into rows.

**Interest over time** is one row per point on the chart. The range decides how fine the points are:
the past day is minute by minute, a year is weekly, `all` is monthly back to 2004.

**Interest by region** is one row per place. Worldwide runs break down by country, a single country
by state or province, or by city or metro area if you ask.

**Related and rising queries** is one row per related search, marked `top` for the ones consistently
searched alongside your keyword and `rising` for the ones growing fastest.

**Trending Now** is separate. Give it country codes and you get what is spiking in each one now,
with the top news story behind it. No keywords needed. Pick a time window, categories or a maximum
and it reads the full Trending Now list instead, hundreds of searches a day in a large country, each
with its search volume, how fast it rose and when it started and stopped, but no news story.

### 📋 What data you get from Google Trends

| What you get | Field |
|---|---|
| Which panel the row came from | `recordType` |
| The keyword and the settings behind it, on every row | `keyword`, `geo`, `timeframe`, `searchType`, `category`, `trendsUrl` |
| Google's 0 to 100 index, and its own label for it | `value`, `formattedValue` |
| The point in time, and the label Google prints on the chart axis | `date`, `dateLabel` |
| Whether the last point is still filling in | `isPartial` |
| A region's name and code, and coordinates at city level | `geoName`, `geoCode`, `latitude`, `longitude` |
| A related search, top or rising, and its rank | `relatedQuery`, `queryType`, `rank` |
| Trending Now: the approximate search count Google publishes, and the story behind it | `trafficEstimate`, `newsTitle`, `newsUrl`, `newsSource` |
| Trending Now, full list: volume, rise, start and end, the searches in it, its categories | `searchVolume`, `increasePercent`, `date`, `endedAt`, `isActive`, `trendBreakdown`, `trendCategories` |

### ▶️ How to scrape Google Trends

1. Open [Google Trends Scraper](https://apify.com/dami_studio/google-trends-scraper) and click **Try
   for free**.
2. Put your keywords into **Keywords**, deleting the examples first. Or paste links from the Trends
   Explore page into **Google Trends links**: each keeps its own region, range and category.
3. Set **Region** and **Time range**, and untick anything in **What to return** you do not need.
4. Set **Maximum rows**. Around 200 is enough to see what one keyword produces. Then click **Start**.
5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

An empty input writes one labelled sample row and stops there, so you can see the shape first.

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

**$0.06 per 1,000 rows** on the Free plan, $0.059 on Starter, $0.058 on Scale and $0.057 on Business.
The free plan's $5 a month covers about 83,000 rows.

Every delivered row costs the same, whichever panel it came from. Points Google marks as empty never
become rows. Sample rows, diagnostic rows and a keyword with no data are free.

### 📥 What you give it

```json
{
  "searchTerms": ["bitcoin", "ethereum"],
  "geo": "US",
  "timeframe": "today 12-m",
  "dataTypes": ["interestOverTime", "interestByRegion", "relatedQueries"],
  "maxItems": 500
}
```

| Field | Default | What it is |
|---|---|---|
| `searchTerms` | none, the box starts at `bitcoin`, `ethereum` | Keywords or phrases, up to 25. Each is looked up on its own. |
| `geo` | worldwide, the box starts at `US` | A two-letter country, a sub-region like `US-CA` or `GB-ENG`, or empty for worldwide. |
| `timeframe` | `today 12-m` | One of the ranges in the dropdown, or a custom range typed as `2024-01-01 2024-12-31`. |
| `dataTypes` | all three | `interestOverTime`, `interestByRegion`, `relatedQueries`. Untick what you do not need and the row count falls with it. |
| `maxItems` | `1000` | Total rows for the run, up to 20,000. |
| `compareKeywords` | off | Puts the first five keywords on one shared scale. Needs at least two keywords to do anything. |
| `searchType` | `web` | `web`, `images`, `news`, `youtube` or `shopping`. |
| `regionLevel` | `default` | `country`, `region`, `city` or `metro`. City and metro need a single country, and metro is United States only. |
| `category` | `0` | Google's own numeric category id, like `71` for Food and Drink. `0` is every category. |
| `language` | `en-US` | How region names and labels are spelled. It changes no numbers. |
| `trendingNowGeos` | none | Country codes for the Trending Now list, up to 20. Usable on its own. |
| `trendingNowHours` | none | `4`, `24`, `48` or `168`. Set this, the categories or the maximum and the full Trending Now list is read, over 24 hours unless you pick another window. |
| `trendingNowCategories` | none | Keep only these categories, such as `sports` or `technology`, as Google files each search. |
| `trendingNowMaxItems` | none | Most trending searches per country, in Google's order. |
| `trendsUrls` | none | Links from the Trends Explore page, up to 25. Several terms in one link share one scale. |
| `splitCommas` | off | Turns `bitcoin, ethereum` on one line into two keywords. Off, the comma is part of the term. |
| `proxyUrls` | none | Optional. Your own servers, used exactly as given. |

**Budget about 150 rows per keyword** with all three data sets over twelve months. City and metro
detail add roughly 200 rows each on their own.

**A `geo` the run cannot read means worldwide, not an error**: it wants `US`, not `USA`. An
unreadable `timeframe` falls back to twelve months the same way, and an API call with no `geo` is
worldwide too, whatever the form suggests.

### 📤 What you get back

A real row from a run in September 2026:

```json
{
  "ok": true,
  "keyword": "bitcoin",
  "geo": "US",
  "timeframe": "today 12-m",
  "searchType": "web",
  "category": 0,
  "trendsUrl": "https://trends.google.com/trends/explore?q=bitcoin&date=today+12-m&geo=US",
  "recordType": "interest_over_time",
  "date": "2025-09-21T00:00:00.000Z",
  "dateLabel": "Sep 21, 2025",
  "value": 26,
  "formattedValue": "26",
  "isPartial": false,
  "scrapedAt": "2026-09-21T01:23:40.241Z"
}
```

| Field | How to read it |
|---|---|
| `value` | Google's 0 to 100 index for this row. Not a volume. |
| `formattedValue` | Google's own label. On rising related queries this is where `Breakout` and `+450%` appear, which the number cannot express. |
| `date` | ISO 8601 in UTC, on interest-over-time rows and on a trending row's publication time. `null` on regional and related rows. |
| `dateLabel` | The same instant as Google prints it on the chart axis, kept because a weekly point covers a range the timestamp hides. |
| `isPartial` | True on a final point whose period has not finished. It will move. Drop those before charting a trend line. |
| `rank` | On related queries, the position with 1 strongest. |

### 🧾 Reading the output

Three kinds of row can land in your dataset.

| Row | How to spot it | Charged |
|---|---|---|
| A datapoint | `_sample` and `_diagnostic` both absent | yes |
| The sample row | `_sample: true` and `recordType: "sample"` | no |
| A diagnostic | `_diagnostic: true` and an `errorCode` | no |

| Code | What it means |
|---|---|
| `NO_RESULTS` | Google has no data for that keyword in that region and range. Broaden one of them. |
| `RATE_LIMITED` | Google throttled that request and would not answer it. Re-run, or ask for less in one go. |
| `NOT_SERVED` | This request was not served this run. Re-run it later. Runs before 13 October 2026 wrote `BLOCKED` here. |
| `NOT_FOUND` | Google's trending feed for that country did not answer. |
| `NETWORK` | Google was unreachable or answered badly. |
| `TIME_BUDGET` | The run hit its time limit before reaching that keyword. Everything already delivered is complete. |
| `BAD_INPUT` | A Trends link or a Trending Now option the run could not use, refused before anything was fetched. The row says which and why. |
| `PROXY_INPUT_ADJUSTED` | A network setting in your input was not usable, so it was not applied. |
| `CHARGE_ERROR` | A charge could not be recorded. The run stops handing over rows rather than continuing quietly. |

One keyword with no data never stops the others, and a diagnostic row fails the run only when an unexpected error left nothing delivered.

### 💡 What people use it for

- Checking whether a product name is actually growing before committing a budget to it.
- Pulling rising related queries every week and using them as the content or keyword backlog.
- Finding which states or cities index highest for a term, then pointing spend at those first.
- Watching the Trending Now list for a country on a schedule, with the news story attached.

From a rising query to the questions behind it, in three runs:

1. Run this with `dataTypes` set to `relatedQueries` and keep the rows where `queryType` is `rising`.
2. Paste those `relatedQuery` values into
   [Keyword Autocomplete Scraper](https://apify.com/dami_studio/keyword-autocomplete-scraper)'s
   `seeds` with `expandQuestions` on.
3. Run the best questions through
   [Google Search Results Scraper](https://apify.com/dami_studio/google-search-results-scraper)'s
   `query` to see who answers them today.

### 🚧 What it does not do

- **No absolute search volumes.** The 0 to 100 index is all Google publishes.
- **No related topics.** Google returns an empty list for that panel to callers who are not signed
  in, so shipping the field would mean shipping an always-empty column. Related queries are
  unaffected.
- **Two separate runs are not comparable.** Each keyword is scaled against its own peak unless you
  turn on `compareKeywords` and run them together.
- **Comparison mode takes five keywords**, which is Google's own limit. Extras are dropped and the
  run says so in the log.
- **A low-volume keyword returns nothing**, not a flat line of zeroes. Google suppresses series it
  considers too thin, and you get a free `NO_RESULTS` row.
- **City and metro detail is best effort.** Google publishes city data only for some terms and
  countries; elsewhere the run falls back to the level it does publish.
- **The last point of a series is usually partial** and will move if you re-run later the same day.
- **Trending Now is a live snapshot**: two runs an hour apart differ. The full list carries no news.
- **A Trends link that compares regions or time ranges** against each other is refused. Links that
  compare search terms are fine.
- It is not an official Google tool. Dami's Studio is independent and is not affiliated with or endorsed by Google, or by any other company named on this page.

### 🧭 Which Google scraper do you need?

| If you want | Use |
|---|---|
| The web results page for a keyword: organic, ads, People Also Ask | [Google Search Results Scraper](https://apify.com/dami_studio/google-search-results-scraper) |
| What a search box suggests as people type | [Keyword Autocomplete Scraper](https://apify.com/dami_studio/keyword-autocomplete-scraper) |
| Interest in a keyword over time and by region | This one |
| News articles with the publisher's real link | [Google News Scraper](https://apify.com/dami_studio/google-news-scraper) |
| Image results and the pages they sit on | [Google Images Scraper](https://apify.com/dami_studio/google-images-scraper) |
| The ads a brand runs on Google | [Google Ads Transparency Scraper](https://apify.com/dami_studio/google-ads-transparency-scraper) |

### ❓ Questions people ask

#### Do I need a Google account or an API key to scrape Google Trends?

No. Nothing to sign up for and no quota.

#### Why don't the numbers match the Trends website?

Check that the region, the time range, the category and the Google property match: each one
rescales the series. The surest way is to paste the page's own link into `trendsUrls`. And a keyword run on its own is scaled against its own peak, while the website
puts several typed together on one scale. Turn on `compareKeywords` for that view.

#### What happens when a keyword has no data?

One free `NO_RESULTS` row for it, and the run carries on to the rest.

#### Can I call it from code or connect it to an AI assistant?

The [API tab](https://apify.com/dami_studio/google-trends-scraper/api/python) has code for Python, JavaScript and the
CLI. MCP clients like Claude and ChatGPT use
`https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/google-trends-scraper`; coding assistants can load [our
skill file](https://api.apify.com/v2/key-value-stores/BTBHU3DdiuoF4JOsK/records/apify-search-app-stores-SKILL.md). All
three bill your Apify account at the same price.

#### Is scraping Google Trends legal?

Trends is public and aggregated. Apify's write-up on
[the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) is a good starting
point, and we are not lawyers.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Send the keyword, the region and the run ID. The
`errorCode` on the diagnostic row usually names the problem on its own.

# Actor input Schema

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

The keywords or phrases to look up on Google Trends. Up to 25 per run. Each one is looked up on its own and scaled 0-100 against its own peak, exactly as it is when you type a single term into Google Trends.

## `trendsUrls` (type: `array`):

Optional. Paste links from the Google Trends Explore page, one per line, and each is run with its own terms, region, time range, category and search surface. A link with several terms keeps them on one shared scale, as Google shows them. A link that compares regions or time ranges against each other is refused with a free row saying why. Up to 25.

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

Two-letter country code such as US, GB, DE, IN or BR, or a sub-region such as US-CA or GB-ENG. Leave empty for worldwide.

## `timeframe` (type: `string`):

How far back to look. Pick one of the standard ranges, or type a custom range as two ISO dates, for example "2024-01-01 2024-12-31". Shorter ranges return finer-grained points: the last day is minute-by-minute, the last week is hourly, a year is weekly, five years is weekly and "all" is monthly.

## `dataTypes` (type: `array`):

Which of the three data sets to pull for each keyword. Fewer data sets means fewer rows and a smaller bill. Leave all three ticked to get everything.

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

Total rows to return across every keyword and data set. A single keyword with all three data sets and a 12-month range produces roughly 150 rows, so budget about 150 rows per keyword. Keep this low while you are testing - you pay per row.

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

Off by default. When off, each keyword is scaled 0-100 against its own peak. When on, the first five keywords are put on one shared scale so their interest-over-time values can be compared directly, exactly like typing several terms into Google Trends at once.

## `splitCommas` (type: `boolean`):

Off by default. When on, a line such as "bitcoin, ethereum" becomes two keywords, each looked up on its own. When off, the comma is part of the search term, as before.

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

Which Google surface the interest is measured on.

## `regionLevel` (type: `string`):

How finely to break down the interest-by-region data. "Automatic" uses whatever level Google itself shows for the region you picked - countries for a worldwide run, states or provinces for a single country. "City" and "Metro area" produce far more rows (roughly 200 each) and are only available inside a single country; Metro area is United States only. If a level is not available for your region, the run falls back to Automatic instead of failing.

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

Optional Google Trends category id to narrow the search, for example 71 for Food & Drink, 7 for Finance or 174 for Sports. Leave at 0 for all categories.

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

Language for region names and formatted labels, as a code like en-US, de, fr or ja. It does not change which data is returned, only how names are spelled.

## `trendingNowGeos` (type: `array`):

Optional. Add country codes such as US, GB or DE to also pull that country's current Trending Now list - the searches spiking right now, with the top news story behind each one. This is independent of the keywords above and can be used on its own.

## `trendingNowHours` (type: `string`):

Optional. Set this, the categories or the maximum below, and the trending list comes from the full Trending Now page instead of the short feed of about ten searches. The full list holds hundreds of searches a day in a large country, and each row carries the search volume, the rise in percent, when the trend started and whether it is still going, the searches behind it and its categories. It does not carry the news story; the short feed does. Leave all three empty to keep the short feed.

## `trendingNowCategories` (type: `array`):

Optional. Keep only trending searches Google files under one of these categories. Empty means all categories. Uses the full Trending Now list, over 24 hours unless you pick a window.

## `trendingNowMaxItems` (type: `integer`):

Optional. Stop after this many trending searches in each region, in the order Google lists them. Maximum rows above still caps the whole run. Uses the full Trending Now list.

## `proxyUrls` (type: `array`):

Leave this empty for a normal run. Fill it in only if you want the traffic to leave through proxy servers you already pay for, one URL per line, in the form http://user:pass@host:port.

## Actor input object example

```json
{
  "searchTerms": [
    "bitcoin",
    "ethereum"
  ],
  "geo": "US",
  "timeframe": "today 12-m",
  "dataTypes": [
    "interestOverTime",
    "interestByRegion",
    "relatedQueries"
  ],
  "maxItems": 1000,
  "compareKeywords": false,
  "splitCommas": false,
  "searchType": "web",
  "regionLevel": "default",
  "category": 0,
  "language": "en-US"
}
```

# Actor output Schema

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

Every row in the default dataset: recordType, keyword, geo, geoName, timeframe, date, value, formattedValue, relatedQuery, queryType, rank, isPartial, trendsUrl, geoCode, dateLabel, searchType, category, latitude, longitude, trafficEstimate, newsTitle, newsUrl, newsSource, newsCount, scrapedAt. An empty, blocked or unmatched run returns a single uncharged row explaining what happened instead.

# 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",
    "timeframe": "today 12-m",
    "dataTypes": [
        "interestOverTime",
        "interestByRegion",
        "relatedQueries"
    ],
    "maxItems": 1000,
    "compareKeywords": false,
    "splitCommas": false,
    "searchType": "web",
    "regionLevel": "default",
    "category": 0,
    "language": "en-US"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/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",
    "timeframe": "today 12-m",
    "dataTypes": [
        "interestOverTime",
        "interestByRegion",
        "relatedQueries",
    ],
    "maxItems": 1000,
    "compareKeywords": False,
    "splitCommas": False,
    "searchType": "web",
    "regionLevel": "default",
    "category": 0,
    "language": "en-US",
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/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",
  "timeframe": "today 12-m",
  "dataTypes": [
    "interestOverTime",
    "interestByRegion",
    "relatedQueries"
  ],
  "maxItems": 1000,
  "compareKeywords": false,
  "splitCommas": false,
  "searchType": "web",
  "regionLevel": "default",
  "category": 0,
  "language": "en-US"
}' |
apify call dami_studio/google-trends-scraper --silent --output-dataset

```

## MCP server setup

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