# Google Trends Scraper & API: pytrends Alternative (`hiver/google-trends-scraper`) Actor

Google Trends API and pytrends alternative: interest over time, by region, city or US metro, rising related queries, keyword comparison, plus Trending Now searches by country with volume. Empty or refused terms are free. $1.90/1k terms, $0.80/1k trends. Unofficial.

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

## Pricing

from $1.33 / 1,000 search term results

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

## Google Trends Scraper & API: pytrends Alternative

**Get Google Trends data for a whole list of search terms in one run:** interest over time, interest by country, region, city or US metro area, and top and rising related queries. You can also pull Trending Now searches by country. Download it as JSON, CSV or Excel, or read it from Python or JavaScript through the Apify API.

**$1.90 per 1,000 search terms** on the free Apify plan, less on paid plans. Failed terms and terms with no data are free. Apify platform usage is covered by that price; Apify adds only its standard start event ($0.00005 per run at 1 GB).

Unofficial. Not affiliated with, endorsed by or sponsored by Google. Public data endpoints only; no login and no CAPTCHA solving.

### Measured against the alternatives

![Real output rows from our board's test runs on 2026-10-09: python vs java on YouTube search in the UK, coffee by UK city, python by US state](https://raw.githubusercontent.com/hiver-data/pytrends-alternative/main/media/google-trends/readme.gif)

[Watch the walkthrough (MP4)](https://github.com/hiver-data/pytrends-alternative/blob/main/media/google-trends/walkthrough.mp4)

Our board's Lab bench gives this Actor and the two most-used Google Trends Actors on the Apify Store the same two jobs, and checks each answer against facts read by hand on trends.google.com: `python` in the United States over 12 months (a timeline exists, Wyoming is in the state list, "python code" is among the top related queries), and `python` compared with `java` on YouTube search in the United Kingdom (a timeline exists, England is in the region list, the row says what it was compared with). Bench run 2026-10-09 21:40 UTC, build 0.1.16:

| | This Actor | Popular fast alternative | Most-used Google Trends Actor |
|---|---|---|---|
| Facts matched | 6 of 6 | 4 of 6 | 2 of 6 |
| Jobs finished with data | 2 of 2 | 2 of 2 | 1 of 2 (one run timed out at 300 s) |
| Fields filled | 88% | 75% | 50% |
| Run time per job | 11.1 to 14.9 s | 4.7 to 6.8 s | 103.7 s, and a 300 s timeout |
| Price per 1,000 terms in these runs | $1.74 | $21.00 (one term per run, start fee per run) | $1.00 |

The fast alternative is quicker, and the most-used Actor costs less per result when it finishes. Apify's public Store stats for the most-used Actor: 13,041 of its 22,909 runs in the last 30 days succeeded (57%), and 5,221 timed out (read 2026-10-10).

Google refuses some requests with HTTP 429. On 2026-10-09 it refused some of this Actor's too: the bench of 19:43 UTC (build 0.1.15) got data in 0 of 2 jobs. Build 0.1.16 waits out a 429 within a fixed time budget instead of stopping at the first one, and the board's daily health check of 2026-10-10 18:35 UTC returned data for all 3 test terms. The Actor never rotates IPs or cookies to get around a refusal, so expect refused terms on some runs; refused terms cost nothing.

Two jobs are a small sample, so read this as a measurement, not a guarantee. The bench runs again after every new build.

### Coming from pytrends

The pytrends repository on GitHub is archived (read-only) and its last release, 4.9.2, dates from April 2023, so fixes for Google's changes and its HTTP 429 refusals no longer ship. This Actor returns the main pytrends outputs. It reuses one session and paces direct requests. Plain HTTP 429 responses permit bounded waits as described below; other explicit Google refusals stop source traffic. The Actor never rotates IPs or cookies to bypass them.

| pytrends | This Actor (input or output field) |
|---|---|
| `build_payload(kw_list, cat, timeframe, geo, gprop)` | `searchTerms`, `category`, `timeRange` (same strings: `today 12-m`, `now 7-d`, `today 5-y`), `geo`, `searchProperty` |
| up to 5 terms on one shared scale | `compareTerms: true` |
| `interest_over_time()` | `interestOverTime` (date, value, `isPartial`) |
| `interest_by_region(resolution=...)` | `interestByRegion`, with `regionResolution`: `COUNTRY`, `REGION`, `CITY` or `DMA` |
| `related_queries()` | `relatedQueries.top` and `relatedQueries.rising` (with growth and breakout) |
| `trending_searches(pn=...)` | `trendingGeos`: Trending Now by country |

```python
import os

import pandas as pd
from apify_client import ApifyClient  # pip install apify-client pandas

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("hiver/google-trends-scraper").call(run_input={
    "searchTerms": ["python", "rust", "golang"],
    "geo": "US",
    "timeRange": "today 12-m",
    "outputs": ["interestOverTime", "interestByRegion", "relatedQueries"],
})
rows = [r for r in client.dataset(run.default_dataset_id).iterate_items() if r.get("searchTerm")]

## like interest_over_time(): one column per term
timeline = pd.DataFrame(
    [{"date": p["date"], "term": r["searchTerm"], "value": p["value"]} for r in rows for p in r["interestOverTime"] or []]
).pivot(index="date", columns="term", values="value")

regions = pd.DataFrame(rows[0]["interestByRegion"])          # like interest_by_region()
rising = pd.DataFrame(rows[0]["relatedQueries"]["rising"])   # like related_queries()["python"]["rising"]
```

### What you get

One item per search term, containing the outputs you select:

- `interestOverTime`: UTC dates, relative values from 0 to 100, `hasData`, `isPartial`, plus `averageInterest` and `peakInterest`.
- `interestByRegion`: countries, regions, cities or US metro areas, highest interest first.
- `relatedQueries`: top and rising queries, with growth and breakout indicators.
- `relatedTopics`: top and rising topics when Google provides them. Google returned empty topic lists in all our cloud tests, so do not rely on this output. An empty answer is recorded in `warnings` and is never filled with guesses.
- `comparedWith`: the other terms in the same comparison group (up to five).

One item per Trending Now search: country, start and end time, whether it is still trending, approximate search volume, increase, categories and related searches. Optional `news` links come from the public news request behind each trend's panel on Google's Trending Now page, not the RSS feed's ten newest trends.

### Trending Now: trending searches by country

Put country codes in `trendingGeos` (`US`, `GB`, `IN`, or a region such as `US-CA`) and get Google Trends' Trending Now list as rows: one row per trending search, highest search volume first. Pick the window with `trendingHours` (4, 24, 48 hours or 7 days), keep only some categories with `trendingCategories`, cap each country with `trendingMaxItemsPerCountry`. You can run it alone (leave `searchTerms` empty) or in the same run as your terms. $0.80 per 1,000 trending searches on the free plan.

```json
{ "trendingGeos": ["US", "GB"], "trendingHours": "24", "trendingMaxItemsPerCountry": 20 }
```

A row from a US run on 2026-10-12 (related searches shortened):

```json
{
  "trend": "cam little",
  "geo": "US",
  "startedAt": "2026-10-11T15:50:00Z",
  "endedAt": null,
  "isActive": true,
  "searchVolume": 1000000,
  "searchVolumeLabel": "1000K+",
  "increasePercent": 500,
  "categoryIds": [17],
  "categories": ["Sports"],
  "relatedSearches": ["eagles", "eagles game", "jaguars", "jaguars vs eagles"],
  "trendingWindowHours": 24
}
```

`searchVolume` is Google's rounded estimate. With `trendingIncludeNews` on (the default), the Actor asks for up to three news links for each selected output trend: `news` contains `{title, url, source}` objects, with the publisher URL as supplied by Google. Country/category filters and both row caps are applied before requesting news. News requests share serial batches of at most 25 trends and the same direct session and two-second pacing. If Google supplies no articles, a news request fails, or source traffic stops, `news` is an empty array; the collected trend still returns, with no extra news charge. Turning this option off skips news requests. Ready-made input: [Trending searches today in the US and UK](https://apify.com/hiver/google-trends-scraper/examples/trending-searches-by-country).

### Example input

```json
{
  "searchTerms": ["python", "rust", "golang"],
  "geo": "US",
  "timeRange": "today 12-m",
  "outputs": ["interestOverTime", "interestByRegion", "relatedQueries"],
  "trendingGeos": ["US", "GB"],
  "trendingMaxItemsPerCountry": 20
}
```

You can also paste Google Trends Explore URLs. The Actor reads their terms and filters and calls the data behind them without opening the page.

### Reliability and diagnostics

No browser. Direct requests only, with one reused session, an honest `hiver-google-trends/1.0` user agent, and a minimum two-second request gap. Terms run serially; an explicit comparison uses one shared timeline call for its group. `maxConcurrency` is accepted for compatibility but does not create parallel sessions. Network errors and server failures have at most three attempts on the same session.

On a plain HTTP 429 the Actor honours `Retry-After` (seconds or HTTP date), or waits 30 seconds then 60 seconds when it is missing or invalid. There are at most two such waits across the entire run, not per term. If Google's delay will not fit the 160-second source-traffic budget, the Actor stops rather than retrying early. That budget leaves time for result and summary writes within the 180-second health timeout; it also limits large batches, so split those into smaller runs. HTTP 403, redirects, CAPTCHA/consent responses, a missing bootstrap cookie, or an exhausted 429 budget stop further source traffic. No proxy or cookie rotation bypasses a refusal. Failed terms and Trending Now HTTP 400/parse failures become uncharged `error` rows with an explanatory final status; completed rows remain. Topics-only failures preserve the other outputs. This intentionally limits coverage on throttled IPs.

The run log and the `RUN_SUMMARY` key-value-store record report requests, estimated traffic, refusals, retries, `rateLimitWaits`, and `waitSeconds`. `newsRequestedRows` counts selected trends for which news was enabled, and `newsRows` counts trends with at least one returned news link. Terminal refusal metadata includes the endpoint and HTTP status, plus `retryAfter` when supplied; no tokens or cookies are recorded.

Board cloud test, 2026-10-08 (build 0.1.10, 1 GB): 11 terms and 40 Trending Now searches, 0 failed, 54.6 s, direct requests only (64 requests, 0 refused). This is a test run, not a production success rate.

### Price

Free Apify plan: $1.90 per 1,000 search-term results and $0.80 per 1,000 Trending Now results. Higher Apify plans pay less, down to $1.33 and $0.56. Apify adds its standard start event ($0.00005 per run at 1 GB). A search-term result includes every part you selected. Failed terms and terms with no data are not charged. Selecting fewer parts makes runs faster but does not change the per-term price. `maxItems` caps the number of successful rows.

Apify platform usage is included in these prices. This build uses direct traffic only; the legacy proxy input is accepted but ignored.

### Limits

- Trends values are relative (0-100) and sampled, not absolute search volumes. Repeated requests can differ slightly.
- Low-volume terms and narrow filters can return empty timelines, regions or related results. Read `warnings`.
- Related topics were empty in all our cloud tests (see above).
- Trending Now volumes are Google's rounded estimates.
- Cloud-verified on 2026-10-08, build 0.1.13: `compareTerms: true` with python + java, `geo: GB`, `searchProperty: youtube`; and coffee with `geo: GB`, `searchProperty: web`, `category: 71`, `regionResolution: CITY`, all over `today 12-m`. The single board test returned 3 populated term rows, 0 failed terms, in 18.1 s at $0.0001 run cost, using direct requests only. Coffee returned city rows; the YouTube comparison returned timelines but empty city lists. This verifies these exact combinations, not every category, location or search property. News, Shopping, Images and DMA coverage remain unverified by this test.
- Google can throttle or change these unofficial endpoints. A run can finish with partial results or error rows (not charged), and runtime depends on Google's limits.
- One direct session and serial jobs, regardless of the legacy `maxConcurrency` value. Large batches may hit the 160-second source budget and return partial results.
- With `compareTerms`, more than five terms are split into groups of five. Values are not comparable across groups.

### FAQ

#### How many terms can I collect in one run?

As many as you list. Batch size and completion time depend on Google's limits. Start with a few terms, check `warnings` and `RUN_SUMMARY`, then scale up. Use `maxItems` to cap the number of rows.

#### Why are related topics empty?

Google returned empty topic lists in our tests even when timelines and related queries were populated. We keep Google's answer, add a warning, and never substitute guesses or change your filters.

#### Can I get YouTube, News or Shopping interest?

Yes. Set `searchProperty` to `youtube`, `news`, `shopping`, `images` or `web`. Availability varies by term and filters.

#### Can I compare keywords?

Turn on `compareTerms`. Up to five terms per group share Google's 0-100 scale, as when you type several terms into Google Trends.

#### Do I need a proxy?

No. This build uses direct requests only. It stops on source refusals rather than bypassing them with a proxy. The legacy proxy setting has no effect.

#### What if a run returns errors?

Check the input, `warnings` and `RUN_SUMMARY`. If that does not explain it, open an issue on this Actor's Issues tab with the input and the run link (never include tokens).

# Actor input Schema

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

One term per line, for example `ai agents`. Each term is looked up on its own, unless you switch on **Compare terms** below. Leave empty if you only want Trending Now.

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

On: terms are grouped five at a time and scored against each other on Google's shared 0-100 scale (the same as typing several terms into Google Trends). Off: every term gets its own 0-100 scale.

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

Two-letter country code (`US`, `GB`, `DE`, `JP`) or a region code like `US-CA` or `GB-ENG`. Leave empty for worldwide.

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

How far back the interest-over-time chart goes. Shorter ranges give hourly or daily points; longer ones weekly or monthly.

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

Overrides the time range. Format `YYYY-MM-DD YYYY-MM-DD`, for example `2025-01-01 2025-06-30`.

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

Google web search, or one of the other Google search sites that Trends separates out.

## `category` (type: `string`):

Narrow the search to one Google Trends category. Helps with ambiguous words like `apple` or `python`.

## `outputs` (type: `array`):

Every item is one search term with the parts you pick. Google returned empty relatedTopics in our 11-term cloud tests; that output is optional and unverified. Fewer parts means fewer requests. Pay per populated term, not per part.

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

Interest by region: countries, regions (states), cities or metro areas. Which levels exist depends on the country you chose.

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

Google hides regions with little data by default. Turn on to list them too (values are less reliable).

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

Paste Explore links such as `https://trends.google.com/trends/explore?q=python,rust&geo=US&date=today 12-m`. Terms, country, time range, category and search type are read from the URL. The Actor does not open the page; it calls the data behind it.

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

Two-letter country codes (`US`, `GB`, `IN`) or `US-CA` style regions. One item per trending search, with when it started, approximate search volume, growth and related searches. Leave empty to skip Trending Now.

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

How far back Trending Now looks.

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

Keep only trends in these Google Trends Now categories. Empty keeps all.

## `trendingMaxItemsPerCountry` (type: `integer`):

Highest search volume first.

## `trendingIncludeNews` (type: `boolean`):

Requests up to three news links (title, publisher URL, source) from each selected trend's public Trending Now panel. Country/category filters and row caps apply first. Serial batches of at most 25 trends use the same direct session and pacing. Missing or failed news stays an empty array; no extra news charge. Off skips news requests.

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

Language code for topic names and related-query labels, for example `en-US`, `de`, `es`.

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

Offset used for hourly points, as in the Google Trends URL `tz` value. 0 is UTC; -480 is UTC+8.

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

Caps non-error rows (search terms plus trending searches). Uncharged error rows may be additional; this is not a dollar cap on platform usage.

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

Accepted for compatibility. All jobs run serially on one direct session. Plain HTTP 429 permits at most two Retry-After waits per run within a 160-second source budget; other explicit refusals stop traffic.

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

Legacy compatibility setting, ignored. The Actor uses one direct session, honours bounded Retry-After waits on plain HTTP 429, and never uses proxies to bypass blocks.

## Actor input object example

```json
{
  "searchTerms": [
    "python",
    "rust",
    "golang"
  ],
  "compareTerms": false,
  "geo": "",
  "timeRange": "today 12-m",
  "searchProperty": "web",
  "category": "0",
  "outputs": [
    "interestOverTime",
    "interestByRegion",
    "relatedQueries",
    "relatedTopics"
  ],
  "regionResolution": "REGION",
  "includeLowVolumeRegions": false,
  "startUrls": [],
  "trendingGeos": [
    "US",
    "GB"
  ],
  "trendingHours": "24",
  "trendingMaxItemsPerCountry": 50,
  "trendingIncludeNews": true,
  "language": "en-US",
  "timezoneOffsetMinutes": 0,
  "maxItems": 1000,
  "maxConcurrency": 1,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "searchTerms": [
        "python",
        "rust",
        "golang"
    ],
    "startUrls": [],
    "trendingGeos": [
        "US"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("hiver/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": [
        "python",
        "rust",
        "golang",
    ],
    "startUrls": [],
    "trendingGeos": ["US"],
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

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