# Google Trends Scraper & API (`graylark/google-trends-scraper`) Actor

Google Trends scraper and API: interest over time, interest by region, related queries and Trending Now searches. Compare any number of keywords on one scale. Pay only for results with data.

- **URL**: https://apify.com/graylark/google-trends-scraper.md
- **Developed by:** [Graylark](https://apify.com/graylark) (community)
- **Stats:** 2 total users, 1 monthly users, 95.5% runs succeeded, 2 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.70 / 1,000 keyword results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Trends Scraper & API

Get Google Trends data for any keyword, country and time range: interest over time, interest by region, related queries, and the searches trending right now. It's a plain HTTP scraper (no browser), so it's quick, and you're only charged for terms that actually return data.

**Price:** $1.00 per 1,000 keywords on Apify's Free plan, down to $0.70 on paid plans. Platform usage is included, so there's no compute bill on top.

### Why use this one

Google rate-limits Trends hard (HTTP 429), which is why a lot of Trends scrapers time out or fail. This one paces its requests, swaps out IPs that get blocked, and retries failed terms on fresh IPs. In testing, 25 keywords took about 45 seconds with no failed terms.

A few other things it does:

- **Compare more than 5 keywords.** Google's compare view stops at 5. Turn on *Compare terms* and any number of keywords end up on the same 0-100 scale.
- **Paste a Google Trends link.** Set up a view on trends.google.com, copy the URL, and you get exactly that data (country, dates, category and search type included).
- **Failed terms are free.** If a term fails or Google has no data for it, it's listed with the reason and you aren't charged.
- **Results are saved if time runs out.** If a run is about to hit its timeout, it stops early and keeps what it collected.
- **Works as a pytrends replacement.** pytrends was archived in April 2025. No code or API key needed here, though the API is there if you want it.

### What data do you get?

| Data | Description |
|---|---|
| Interest over time | Values from 0 to 100 per hour, day, week or month (depending on the time range), with date, timestamp and a partial-period flag |
| Average & peak interest | Summary numbers for quick comparisons |
| Interest by region | Countries, regions/states, cities or US metro areas |
| Related queries | Top and rising searches related to each term |
| Trending Now | Live trending searches for a country with search volume, increase and related terms |
| Search types | Web, Image, News, Google Shopping and YouTube search |

### How to use it

1. Enter your **search terms** (e.g. `bitcoin`, `electric car`), or paste **Google Trends links**.
2. Pick a **country code** (`US`, `GB`, `DE`…) or leave it empty for worldwide.
3. Choose a **time range**, from the past hour to 2004-present, or a custom date range.
4. Click **Start** and download results as JSON, CSV or Excel, or get them via API.

For live trends, switch **What to scrape** to *Trending now*.

#### Input examples

Compare three phones in the US over the past year:

```json
{
  "searchTerms": ["iphone", "samsung", "pixel"],
  "compareTerms": true,
  "geo": "US",
  "timeRange": "today 12-m"
}
```

Scrape Google Trends links exactly as shown on trends.google.com:

```json
{
  "trendsUrls": ["https://trends.google.com/trends/explore?date=today%205-y&geo=GB&q=tea,coffee"]
}
```

Trending searches in the UK over the past 24 hours:

```json
{ "mode": "trendingNow", "geo": "GB", "trendingHours": "24", "maxTrendingItems": 50 }
```

#### Output example

```json
{
  "searchTerm": "iphone",
  "geo": "US",
  "timeRange": "today 12-m",
  "category": 0,
  "searchProperty": "web",
  "comparedWith": ["samsung", "pixel"],
  "averageInterest": 61.29,
  "peak": { "date": "2025-09-14", "timestamp": 1757808000, "label": "Sep 14 – 20, 2025", "value": 100, "isPartial": false },
  "interestOverTime": [
    { "date": "2025-10-12", "timestamp": 1760227200, "label": "Oct 12 – 18, 2025", "value": 58, "isPartial": false }
  ],
  "interestByRegion": [ { "geoCode": "US-NY", "name": "New York", "value": 100 } ],
  "relatedQueries": {
    "top": [ { "query": "iphone 17", "value": 100, "formattedValue": "100" } ],
    "rising": [ { "query": "iphone 17 pro max", "value": 5000, "formattedValue": "Breakout" } ]
  },
  "topRegions": "New York (100), California (92), Texas (85)",
  "topRelatedQueries": "iphone 17, iphone 16, apple iphone",
  "risingRelatedQueries": "iphone 17 pro max",
  "status": "ok",
  "scrapedAt": "2026-10-09T14:00:21Z"
}
```

Trending Now output:

```json
{ "rank": 1, "geo": "GB", "hours": 24, "title": "premier league", "searchVolume": 200000, "increasePercent": 1000, "startedAt": "2026-10-09T06:40:00Z", "relatedSearches": ["premier league table"], "status": "ok" }
```

#### Result status

| `status` | Meaning | Charged? |
|---|---|---|
| `ok` | Data returned | Yes |
| `noData` | Google has no data for this term with these settings (very rare term, short range, narrow location) | No |
| `failed` | Could not be scraped (see `error`), e.g. the run hit its time limit | No |

An `ok` result can carry `warnings` if an optional extra (regions or related queries) could not be fetched; the interest-over-time data is still complete.

### Compare more than 5 keywords on Google Trends

Google's own compare view stops at 5 search terms. Turn on **Compare terms** and add as many as you like: the scraper fetches them in batches of 5 that all share your first keyword, then rescales every batch onto one 0-100 scale, so the numbers are comparable across the whole list. Pick a first keyword with steady interest (not a one-off spike) for the most accurate result.

### Fixing pytrends "429 Too Many Requests"

If pytrends stopped working for you with `TooManyRequestsError` or HTTP 429, that's Google rate-limiting your IP address. Sleeping between requests helps for a few keywords, but on a long list or a cloud server you get blocked again. This scraper spreads requests over a pool of IPs, replaces any IP that gets a 429, and retries the term on a fresh one, so you get results instead of errors. The input fields map closely to pytrends:

| pytrends | This scraper |
|---|---|
| `build_payload(kw_list, timeframe, geo, cat, gprop)` | `searchTerms`, `timeRange`, `geo`, `category`, `searchProperty` |
| `interest_over_time()` | `interestOverTime` |
| `interest_by_region(resolution=...)` | `interestByRegion` and `regionResolution` |
| `related_queries()` | `relatedQueries` (`top` and `rising`) |
| `trending_searches(pn=...)` | `mode: "trendingNow"` with `geo` |

### Download Google Trends data (CSV, Excel, JSON)

Run the scraper, then export from the Output tab: CSV, Excel, JSON, XML or HTML. Choose the *Keyword trends* view for a spreadsheet with one row per keyword (average and peak interest, top regions, top and rising related queries). Use JSON for the full timeline. How detailed the data is depends on the time range: the past hour and 4 hours give per-minute points, the past day every 8 minutes, the past 7 days hourly, ranges up to about 9 months daily, up to 5 years weekly, and longer ranges (such as 2004 to present) monthly.

### Pricing

Pay per result, platform usage included:

| Event | Free | Starter (Bronze) | Scale (Silver) | Business (Gold) |
|---|---|---|---|---|
| Keyword result | $1.00 / 1,000 | $0.90 / 1,000 | $0.80 / 1,000 | $0.70 / 1,000 |
| Trending Now result | $0.50 / 1,000 | $0.45 / 1,000 | $0.40 / 1,000 | $0.35 / 1,000 |

That is all-in: other Google Trends scrapers add platform usage on top of their per-result price, and charge it even when a run fails. Here 1,000 keywords on the Free plan cost $1.00, full stop.

Plus a tiny $0.00005 per run start. `noData` and `failed` results cost nothing. You can also set a maximum cost per run, and the scraper stops cleanly when it is reached.

### Instant lookups (Standby mode)

For apps and AI agents that need one answer quickly, the Actor also runs as an always-on API. Instead of starting a run, send a request and get JSON back, usually in 2-5 seconds:

```
GET https://graylark--google-trends-scraper.apify.actor/?q=bitcoin,ethereum&geo=US&timeRange=today%2012-m
GET https://graylark--google-trends-scraper.apify.actor/trending?geo=GB
Authorization: Bearer <YOUR_APIFY_TOKEN>
```

Parameters: `q` (comma-separated terms), `geo`, `timeRange`, `compare=1`, `property`, `category`, `regions=0`, `related=0`, `url` (a Google Trends link), and for trending `hours` and `max`. A `POST` with the normal Actor input as JSON works too. Pricing is the same per result.

### Recent results are reused

If the same keywords with the same settings were scraped in the last few hours, you get that result straight away instead of waiting for Google: 12 hours for most time ranges, 1 hour for the past day or 7 days, and never for the past hour or 4 hours. Those items have `"fromCache": true` and a `cachedAt` time. Turn off *Reuse recent results* if you always want live data.

### Google Trends API for Python, Node.js, n8n, Make and AI agents (MCP)

Call it through the Apify API, the Apify MCP server (Claude, Cursor and other agents), or any Apify integration. It takes plain inputs and returns predictable JSON, so agents can use it directly. Python example:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("graylark/google-trends-scraper").call(run_input={"searchTerms": ["bitcoin"], "geo": "US"})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["searchTerm"], item["status"], item.get("averageInterest"))
```

Node.js:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('graylark/google-trends-scraper').call({ searchTerms: ['bitcoin'], geo: 'US' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((i) => console.log(i.searchTerm, i.status, i.averageInterest));
```

In n8n, Make or Zapier, use the Apify integration and pick this Actor. AI agents (Claude, Cursor and others) can call it through the Apify MCP server.

### FAQ

**Is there an official Google Trends API?** Google has an alpha API, but access is invite-only. This scraper returns the same public data you see on trends.google.com today.

**Do I need a Google account or API key?** No.

**Why do other scrapers fail with 429 errors?** Google throttles fast or repeated requests. This scraper paces requests, refreshes cookies and rotates IPs automatically.

**How long does a run take?** With the default 8 parallel IPs, 25 keywords usually take 25-45 seconds. Speed depends on how hard Google is rate-limiting at the moment. Trending Now takes a few seconds.

**Can I download the results as CSV or Excel?** Yes. Every run can be exported as CSV, Excel, JSON, XML or HTML from the Output tab or the API. For spreadsheets, pick the *Keyword trends* view: it has one row per keyword with average and peak interest, top regions and top/rising related queries as plain text. Use JSON if you need the full week-by-week timeline.

**Why are related topics missing?** Google currently withholds related *topics* from automated requests. Related *queries* work normally.

**Why are some values 0 or 1?** Google Trends values are relative (0-100). Small terms compared with big ones round down. Turn off *Compare terms* to see each term on its own scale.

**What if a term has no data?** You get `"status": "noData"` with an explanation, and you are not charged.

**Can I compare more than 5 keywords?** Yes. With *Compare terms* on, extra keywords are fetched in batches that share an anchor term (your first keyword), then rescaled onto one 0-100 scale. Pick a first keyword with steady search interest for the best accuracy.

**Does Google Trends have an API? Is it free?** Google has an official Trends API, but it is an invite-only alpha with no public pricing. Google offers no other official API, which is why tools like pytrends scrape the website. This scraper works the same way without you managing IPs, and costs $1.00 per 1,000 keywords on Apify's Free plan (Apify gives free monthly credit to start).

**Do I need a Google Trends API key?** No. You only need an Apify account; the API token comes with it.

**Does pytrends still work?** pytrends was archived in April 2025 and often fails with 429 errors. If it still works for your small jobs, keep using it. For long keyword lists, or when it keeps getting blocked, this scraper is the drop-in alternative.

**Can Google Trends show the number of searches?** No. Google Trends only gives relative interest from 0 to 100, not absolute search volume. Trending Now is the exception: it shows an approximate volume such as "200K+".

**How far back does Google Trends data go?** To 2004 for web search. Choose *2004 to present* or a custom date range.

**Why does Google Trends say "not enough data"?** The term has too little search volume for that location, time range or category. The scraper returns `"status": "noData"` for those terms and doesn't charge you. Try a wider location or a longer time range.

**How is Google Trends data scaled? What does 100 mean?** 100 is the peak popularity of the term (or of the compared terms) in the chosen place and time range. Everything else is relative to that peak, so 50 means half as popular as the peak.

**Is scraping Google Trends legal?** It collects publicly available, aggregated data. You are responsible for how you use it and for complying with Google's terms and local laws.

### More from Graylark

[Google Autocomplete Scraper](https://apify.com/graylark/google-autocomplete-scraper): keyword ideas from Google's search suggestions, expanded with a-z, 0-9 and question words. Pairs well with this Actor: find keyword ideas there, then check their trends here.

### Feedback

Found a problem or need a feature? Open an issue on the **Issues** tab. Issues are answered quickly.

# Changelog

This Actor's version history is a separate document: https://apify.com/graylark/google-trends-scraper/changelog.md

# Actor input Schema

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

Keyword trends: interest over time, by region and related queries for your terms. Trending now: today's fastest-rising searches in a country.

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

Keywords or phrases, one per line, e.g. 'bitcoin' or 'electric car'. Duplicates are removed. Keyword trends only.

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

Paste links from trends.google.com/trends/explore. Each link is scraped exactly as shown (its terms, country, dates, category and search type), so you can mix different settings in one run.

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

Two-letter country code like US, GB or DE (use GB, not UK), or a region like US-CA. Keyword trends: leave empty for worldwide. Trending now: leave empty for US.

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

How far back to look. Short ranges have less data, so small terms may come back as 'noData' (not charged). Keyword trends only.

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

On: all terms share one 0-100 scale like Google's compare view, even with more than 5 terms. Off: each term gets its own 0-100 scale.

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

Adds a breakdown of interest by country, region or city.

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

Optional. Leave empty for Google's default. Worldwide searches only support Country, and Metro area only works for US locations.

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

Top and rising related searches for each term.

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

How recent the trending searches should be.

## `maxTrendingItems` (type: `integer`):

Maximum number of trending searches to return. Each result is one billed event.

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

Overrides Time range. Two dates, oldest first: '2024-01-01 2024-06-30'. Keyword trends only.

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

Google Trends category ID, for example 7 = Finance, 71 = Food & Drink, 20 = Sports. 0 means all categories. Tip: pick a category on trends.google.com and copy the 'cat=' number from the link.

## `searchProperty` (type: `string`):

Which Google search to measure: web, images, news, Google Shopping or YouTube.

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

Language for date labels, e.g. en-US, en-GB, de. Does not change which searches are counted.

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

How many IPs work in parallel (8 recommended). The scraper replaces rate-limited IPs automatically; higher finishes long lists faster.

## `useCache` (type: `boolean`):

If the same keywords with the same settings were scraped recently, return that result instantly instead of asking Google again (fresh for 12 hours for most time ranges, 1 hour for past day / 7 days, never cached for past hour / 4 hours). Turn off to always fetch live data.

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

Apify Proxy is used by default and works best. Rate-limited IPs are replaced automatically; terms that keep failing get a last retry through residential IPs if your account has them.

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

Google currently withholds related topics from automated requests, so this is usually empty.

## Actor input object example

```json
{
  "mode": "keywords",
  "searchTerms": [
    "bitcoin",
    "ethereum"
  ],
  "trendsUrls": [
    "https://trends.google.com/trends/explore?date=today%205-y&geo=US&q=iphone,samsung"
  ],
  "geo": "",
  "timeRange": "today 12-m",
  "compareTerms": false,
  "includeInterestByRegion": true,
  "includeRelatedQueries": true,
  "trendingHours": "24",
  "maxTrendingItems": 100,
  "category": 0,
  "searchProperty": "web",
  "language": "en-US",
  "maxConcurrency": 8,
  "useCache": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "includeRelatedTopics": false
}
```

# Actor output Schema

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

One item per search term (or per trending search). Check `status`: only `ok` items are charged.

## `overview` (type: `string`):

Summary view: search term, location, average and peak interest, status.

## `trending` (type: `string`):

Trending Now view: rank, trend, search volume, increase and related queries.

# 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"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

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