# Google Trends Scraper | Trends, Regions & Charts (`peerless_columbine/google-trends-scraper-api`) Actor

Collect Google Trends interest over time, regional interest, related queries and trending searches. Compare keywords and export structured data, with optional chart snapshots and clear partial-data warnings.

- **URL**: https://apify.com/peerless\_columbine/google-trends-scraper-api.md
- **Developed by:** [tingyou333 zhuang](https://apify.com/peerless_columbine) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.10 / 1,000 trend report or trending queries

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Google Trends Scraper | Trends, Regions & Charts

Collect Google Trends keyword reports and trending-search queries. Export interest over time, geographic interest, related queries and topics for SEO, content planning and market research.

[Quick start](#quick-start) · [Workflows](#common-workflows) · [Pricing](#pricing) · [Input reference](#input-reference) · [Output reference](#output-reference) · [API and automation](#api-and-automation) · [FAQ](#faq) · [Technical reference](#technical-reference)

### What you can do

- **Keyword reports and trending searches** — Choose Explore-style reports or Trending Now queries.
- **Comparison and geography** — Compare terms within a shared request; collect available regional, city and metro widgets.
- **Optional source snapshots** — Save page screenshots and HTML when requested, with separate readiness diagnostics.
- **Transparent partial data** — Each report shows coverage and warnings so missing widgets are visible.

#### Who uses it

- SEO teams: compare relative search interest across keywords and regions.
- Editors: follow trending searches and discover related topics.
- Analysts: export time-series reports and optional page snapshots for research workflows.

### Quick start

1. Open **Input**, enter your target and a small result limit.
2. Click **Start** and inspect the dataset and run log.
3. Export JSON/CSV, or save the input as a Task for recurring runs.

```json
{
  "searchTerms": [
    "ChatGPT"
  ],
  "maxItems": 1,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

Form prefills, schema defaults and empty API input can differ. Use explicit targets and limits; see the technical reference for source and default behavior.

<details>
<summary>Default input behavior and source options</summary>

Empty local input uses ChatGPT in keyword mode with direct-first recovery. The input Schema defaults `proxyConfiguration` to enabled, which makes a default-injected platform input use a proxy from its first request. For direct-only collection explicitly disable it as below. Proxy access and charges depend on your account; data availability remains source-dependent.

</details>

#### Locale selection and optional Data Xplorer output

Country and category controls show named suggestions. Custom subdivisions such as `US-CA` and custom numeric categories remain accepted. `viewedFrom` configures the Apify residential proxy country and requires compatible proxy settings; it is independent of the data region `geo`. Residential traffic can add platform costs.

The legacy boolean `enableTrendingSearches` overrides `mode` when explicitly supplied. Leave it absent to use `mode`.

Set `outputSchema` to `data-xplorer` for the documented alternative output: keyword reports contain `keyword`, `timeframe`, `geo`, `timeline_data`, `region_data`, `data_granularity` and `trends_url`; trending mode returns one report with a `trending_searches` array containing rank, term, related terms and traffic estimates. Native output remains the default. Multi-keyword comparison reports require native output. Coverage and warnings remain available; source estimates and timestamps may differ from another run or provider.

```json
{"dataXplorerInput": {"mode": "trending", "trendingSearchesCountry": "FR", "trendingSearchesMaxItems": 5, "outputSchema": "data-xplorer", "proxyConfiguration": {"useApifyProxy": false}}}
```

**Billing unit:** native trending output charges one result event per delivered query row. The optional bundled output charges one result event for the delivered bundle, irrespective of its contained query count. Error-only or empty collections create no billable bundle. Platform usage remains additional in either format.

### Common workflows

#### Compare keywords on one scale

```json
{
  "searchTerms": [
    "ChatGPT,Claude,Gemini"
  ],
  "isMultiple": true,
  "geo": "US",
  "timeRange": "today 3-m",
  "maxItems": 1
}
```

#### Collect trending queries

```json
{
  "mode": "trending",
  "trendingSearchesCountry": "US",
  "trendingSearchesTimeframe": "24",
  "trendingSearchesMaxItems": 10
}
```

#### Request a source-page snapshot

```json
{
  "searchTerms": [
    "Python"
  ],
  "geo": "US",
  "timeRange": "today 3-m",
  "maxItems": 1,
  "skipDebugScreen": false
}
```

### Output at a glance

Illustrative field subset below; these are example values, not a captured customer review or a claim about source coverage. Native and compatibility output profiles can differ.

```json
{
  "type": "trend_report",
  "searchTerm": "Python",
  "geo": "US",
  "timeRange": "today 3-m",
  "interestOverTime_timelineData": [
    {
      "time": "1788220800",
      "value": [
        54
      ],
      "hasData": [
        true
      ]
    }
  ],
  "coverage": "partial",
  "warnings": [
    "Illustrative warning: one optional geographic widget was unavailable."
  ]
}
```

Interest values are normalized relative measures, not absolute search volume. Comparison requests may omit per-keyword related widgets. Source throttling and proxy availability can affect output. Snapshots may be partial and are not proof that every chart loaded.

### Pricing

Pay per delivered event, with automatic discounts based on **your Apify subscription plan**. These are result fees in USD, not separate subscriptions sold by this Actor. All tiers have the same Actor features. **Apify compute, storage, transfers and any proxy usage are charged additionally.**

| Billable event (1,000 events) | Free | Starter | Scale | Business |
|---|---:|---:|---:|---:|
| Trend report or trending query | $0.5 | $0.4 | $0.2 | $0.1 |

Platinum and Diamond currently use the Business rate. The **Pricing** tab is the source of truth for the active schedule and your applicable plan.

- **Trend report or trending query**: One Explore report, one native trending-search query row, or one optional bundled trending report. Partial reports can be charged; error rows are not. Platform usage is additional.

Example on the Free plan: 10 / 1,000 / 10,000 events cost $0.005 / $0.5 / $5 in result fees, plus platform usage.

There is no additional developer setup or monthly rental fee. A run with no billable results can still consume platform resources. Start small, cap results and review run costs before scheduling a larger workload. Requested counts are ceilings, not guaranteed deliveries.

### Input reference

Fields below are grouped like the Input form. Optional fields need not be supplied. Compatibility input envelopes and transformations are explained in the technical reference.

#### Targets and collection

| Field | Type | Default | Meaning |
|---|---|---|---|
| `searchTerms` | array | Not set | One or more Google Trends search terms. With Multiple terms enabled, comma-separated terms are compared in the same Google Trends request. |
| `isMultiple` | boolean | false | Treat commas inside each searchTerms entry as comparison separators. Google Trends supports up to five terms per comparison group. |
| `timeRange` | string | Not set | Choose a predefined Google Trends time window. Empty means Past 12 months. |
| `geo` | string | "" | Choose Worldwide or a country; custom subdivisions such as US-CA remain accepted. A geo in a start URL takes precedence for that URL. Source availability determines regional/city/metro coverage. |
| `category` | string | "" | Choose a named Google Trends category or enter a numeric category ID. Blank/0 means all categories. |
| `startUrls` | array | Not set | Paste Google Trends Explore URLs. q, geo, date, cat and gprop parameters are preserved. |
| `spreadsheetId` | string | Not set | Optional public one-column Google Sheet. The first row is treated as a header. |
| `requestDelayMillis` | integer | 0 | Minimum spacing in milliseconds between Google Trends HTTP request starts across all workers. |
| `viewedFrom` | string | Not set | Optional proxy-origin country, separate from the data geography. Requires available Apify residential proxies; custom two-letter country codes remain accepted. |
| `mode` | string | "keyword" | Historical keyword reports or live trending searches. |
| `keyword` | string | Not set | Single search term alias. |
| `predefinedTimeframe` | string | Not set | Alias for timeRange. |
| `trendingSearchesCountry` | string | Not set | Trending-search input; same field name as data\_xplorer. |
| `trendingSearchesTimeframe` | string | Not set | Trending-search input; same field name as data\_xplorer. |
| `trendingSearchesCategories` | array | Not set | Trending-search input; same field name as data\_xplorer. |
| `trendingSearchesMaxItems` | integer | Not set | Trending-search input; same field name as data\_xplorer. |
| `fetchRegionalData` | boolean | true | Fetch regional and city data. Disable to skip regional requests while retaining timeline and related data. |
| `dataXplorerInput` | object | Not set | Explicit data\_xplorer input object. Defaults to trending mode and fetchRegionalData=false using the frozen competitor contract. Put all settings inside this object, including optional native snapshot/URL settings. Outer non-default settings cannot be mixed. Omit this field to retain native defaults. |

#### Result limits and cost

| Field | Type | Default | Meaning |
|---|---|---|---|
| `maxItems` | integer | 0 | Maximum number of report rows. Zero means no limit. |
| `maxRequestRetries` | integer | 4 | Retries for transient network errors and 403/408/429/5xx responses. |
| `rateLimitRecoverySeconds` | integer | 30 | Wait before each direct-only 429 recovery round. When an Apify fallback proxy is available, proxy recovery starts immediately. Zero disables waiting. |
| `rateLimitRecoveryRounds` | integer | 2 | Maximum number of bounded batch-level 429 recovery rounds. Each round retries only groups that are still rate-limited. |

#### Compatibility and transformations

| Field | Type | Default | Meaning |
|---|---|---|---|
| `customTimeRange` | string | Not set | Optional YYYY-MM-DD YYYY-MM-DD range. Takes precedence over timeRange. |

#### Connection and advanced settings

| Field | Type | Default | Meaning |
|---|---|---|---|
| `proxyConfiguration` | object | {"useApifyProxy": true} | Used only for retrying groups that Google rate-limits on the direct connection. The fast first pass remains direct. |
| `maxConcurrency` | integer | 4 | Maximum number of independent Google Trends comparison groups processed in parallel. |
| `pageLoadTimeoutSecs` | integer | 30 | Per-request timeout in seconds for Google Trends HTTP calls. |
| `skipDebugScreen` | boolean | true | When false, save a real Chromium PNG and HTML snapshot for every requested Explore or trending page to the run key-value store. Optional browser diagnostics run after data delivery; failure does not discard results. Defaults to true to avoid browser overhead. |

#### Additional compatibility options

| Field | Type | Default | Meaning |
|---|---|---|---|
| `enableTrendingSearches` | boolean | Not set | Legacy Data Xplorer alias. When supplied, overrides mode: true selects trending, false selects keyword. Leave unset for normal mode selection. |
| `outputSchema` | string | Not set | Native preserves detailed widget rows. data-xplorer returns timeline\_data reports, or one bundled trending\_searches report per run. A delivered bundle counts as one report event; platform usage is additional. Use native for multi-term comparisons. |

### Output reference

The table describes native fields; fields can be absent or null when the source does not provide them. Error rows and selected compatibility profiles have different shapes. Nested objects remain structured in JSON; CSV exports may serialize them.

| Field | Type | Meaning |
|---|---|---|
| `type` | \['string', 'null'] | Row kind: trend\_report, trending\_search or error. Fields depend on the collection mode. |
| `searchTerm` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `inputUrlOrTerm` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `geo` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `timeRange` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `property` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `interestBy` | \['array', 'null'] | Compatibility geographic-interest rows returned for the selected resolution. |
| `query` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `keyword` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `trendsUrl` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `trendStartTime` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `retrievalMethod` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `scrapedAt` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `schemaVersion` | \['string', 'null'] | Source/request context. Availability depends on row kind and output profile. |
| `coverage` | \['string', 'null'] | Reported completeness of retrieval; inspect warnings for omitted widgets or fields. |
| `searchTerms` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `interestOverTime_timelineData` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `interestOverTime_averages` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `interestBySubregion` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `interestByCity` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `interestByMetro` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `relatedTopics_top` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `relatedTopics_rising` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `relatedQueries_top` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `relatedQueries_rising` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `relatedQueries` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `categories` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `warnings` | \['array', 'null'] | Structured source values or diagnostics. An empty list can mean an unavailable widget, not zero demand. |
| `category` | \['number', 'null'] | Source value or summary count; trending searchVolume is distinct from normalized Explore interest. |
| `timelinePointCount` | \['number', 'null'] | Source value or summary count; trending searchVolume is distinct from normalized Explore interest. |
| `regionCount` | \['number', 'null'] | Source value or summary count; trending searchVolume is distinct from normalized Explore interest. |
| `relatedQueryCount` | \['number', 'null'] | Source value or summary count; trending searchVolume is distinct from normalized Explore interest. |
| `relatedTopicCount` | \['number', 'null'] | Source value or summary count; trending searchVolume is distinct from normalized Explore interest. |
| `timeframeHours` | \['number', 'null'] | Source value or summary count; trending searchVolume is distinct from normalized Explore interest. |
| `searchVolume` | \['number', 'null'] | Source value or summary count; trending searchVolume is distinct from normalized Explore interest. |
| `trendStartTimestamp` | \['number', 'null'] | Source value or summary count; trending searchVolume is distinct from normalized Explore interest. |
| `position` | \['number', 'null'] | Source value or summary count; trending searchVolume is distinct from normalized Explore interest. |
| `diagnostics` | \['object', 'null'] | Additional retrieval and snapshot diagnostics where available. |

### API and automation

The **API** tab provides snippets for this Actor. For scheduled or larger collections, start a run asynchronously and poll its status instead of holding a synchronous request open. Keep your API token in an environment variable.

```python
import os, time, requests

base = "https://api.apify.com/v2"
headers = {"Authorization": "Bearer " + os.environ["APIFY_TOKEN"]}
actor_input = {'searchTerms': ['ChatGPT'], 'maxItems': 1, 'proxyConfiguration': {'useApifyProxy': False}}
response = requests.post(
    base + "/acts/GVtdsp1ENtWCFbYVo/runs",
    headers=headers, json=actor_input, timeout=30,
)
response.raise_for_status()
run = response.json()["data"]
for _ in range(720):
    if run["status"] not in ("READY", "RUNNING", "TIMING-OUT", "ABORTING"):
        break
    time.sleep(5)
    response = requests.get(base + "/actor-runs/" + run["id"], headers=headers, timeout=30)
    response.raise_for_status()
    run = response.json()["data"]
else:
    raise TimeoutError("Polling ended; inspect the existing run before starting another.")
if run["status"] != "SUCCEEDED":
    raise RuntimeError(run.get("statusMessage", run["status"]))
response = requests.get(
    base + "/datasets/" + run["defaultDatasetId"] + "/items",
    headers=headers, params={"format": "json", "limit": 1000, "offset": 0}, timeout=30,
)
response.raise_for_status()
rows = response.json()
print(rows)  # Paginate with offset for larger datasets; inspect per-row coverage.
```

#### Scheduled monitoring and integrations

1. Save a working input as an Apify Task.
2. Attach a Schedule in your timezone; keep runs sharing an incremental state key sequential.
3. Add a successful-run webhook or connect your downstream workflow to the dataset export/API.
4. Inspect missing/partial data before sending alerts or treating absence as removal.

Use the platform Integrations/API options to connect external workflows such as Make, n8n or a data warehouse. An external sentiment or summarization step is separate from this Actor and may have its own charges. The platform also supports Actor tools through [Apify MCP](https://docs.apify.com/platform/integrations/mcp); availability and client setup depend on your integration.

### FAQ

#### Does 100 mean 100 searches?

No. Google Trends normalizes interest within the requested comparison, place and period; it is not an absolute count.

#### Why are related queries empty in a comparison?

Google may omit per-term related-query/topic widgets in a shared comparison response. The warning explains this source behavior.

#### What is billed as one result?

One delivered Explore report or one trending-search query row. Individual timeline points inside a report are not separately billed.

#### Can I export without writing code?

Yes. Run from the Input form, open the dataset and use the export controls for JSON or CSV. Select your preferred output profile before running when migrating an integration.

#### Does a successful run guarantee every field?

No. Inspect coverage, warnings and source-specific status fields. Optional enrichment may be missing even when usable rows were delivered.

### Troubleshooting

| Symptom | What to check |
|---|---|
| Empty dataset | Validate the target, source availability and filters; try the small quick-start input. |
| Fewer rows than requested | Check source limits, pagination and filtering. Increasing a cap cannot create unavailable source records. |
| Partial fields | Inspect coverage/warnings and the relevant source or enrichment status. |
| Access or throttling errors | Check the run log and documented proxy configuration; retry at a lower request volume. |
| Migration mismatch | Check the explicit input/output profile and technical field mapping below. |
| Unexpected bill | Separate result events from platform resources; inspect enrichment, result caps and the Pricing tab. |

### Technical reference

#### What it returns

Each successful report includes:

- interest over time (`interestOverTime_timelineData`, `interestOverTime_averages`)
- interest by area/subregion
- top and rising related queries
- top and rising related topics when Google exposes them
- geo, category, time range and search-property context
- `coverage`, `warnings`, request method and compact row counts

#### Quick start

```json
{
  "searchTerms": ["ChatGPT", "Claude"],
  "geo": "US",
  "timeRange": "today 12-m"
}
```

Compare up to five terms in the same normalized Google Trends request:

```json
{
  "searchTerms": ["ChatGPT,Claude,Gemini"],
  "isMultiple": true,
  "geo": "US",
  "timeRange": "today 3-m"
}
```

Google Trends comparison requests expose the shared interest-over-time and
regional-comparison widgets. Google does not expose per-term related
query/topic widgets in that comparison response, so comparison rows are still
`coverage: complete` when the shared timeline and geo data are present; the
row includes a warning explaining the source behavior.

You can also paste a Google Trends Explore URL in `startUrls`, or provide a public one-column Google Sheet in `spreadsheetId`.

#### Migration compatibility

Accepted input names include the common official Actor fields:

`searchTerms`, `isMultiple`, `timeRange`, `geo`, `category`, `customTimeRange`, `startUrls`, `spreadsheetId`, `maxItems`, `maxConcurrency`, `maxRequestRetries`, `pageLoadTimeoutSecs`, `viewedFrom`, and `skipDebugScreen`.

`viewedFrom` uses the selected two-letter country code for Apify residential proxies from the first request, for both Explore and trending modes. It controls the access location, separately from `geo` (the data region). Explicit custom/disabled proxies conflict with this option and are rejected. `skipDebugScreen=false` saves real Chromium PNG and HTML snapshots for requested Explore or trending pages in the run key-value store after data delivery. It defaults to true to avoid browser overhead. Snapshot failures are reported separately and preserve the dataset. `debugSnapshots` in OUTPUT lists the stored keys and HTTP status. A saved image may show a source error or consent page; it is diagnostic evidence, not proof that every chart loaded.

#### Reliability model

The Actor first obtains Google Trends session context, then calls `/trends/api/explore` to obtain current widget tokens. It uses those tokens for the timeline, region, related-query and related-topic widget endpoints. This avoids the retired `dailytrends` and `realtimetrends` endpoints that now return HTTP 404.

Transient 403/408/5xx responses are retried with exponential backoff. Normal requests are not artificially delayed by default. HTTP 429 is handled at batch level: the first pass uses a proxy when explicitly enabled (including Schema injection) or requested by `viewedFrom`; otherwise it is direct, then only rate-limited groups are retried through fresh Apify proxy sessions when the fallback proxy is enabled. If no proxy is available, bounded direct-only recovery rounds wait `rateLimitRecoverySeconds` and retry serially. This avoids making successful groups pay proxy or cooldown cost and puts a hard ceiling on recovery work. Advanced users can set `requestDelayMillis` for fixed pacing or disable the fallback proxy in `proxyConfiguration`. One bad keyword produces a structured error row instead of failing unrelated inputs.

`coverage: complete` means all core widgets were fetched. `coverage: partial` means at least one optional/core widget could not be retrieved; the missing surface is listed in `warnings`. Error rows use `coverage: not_available` and are not charged as result events.

#### Source and terms

This Actor accesses publicly reachable Google Trends surfaces. Users remain responsible for how they use and store exported data and for complying with applicable law and source-platform terms.

##### City-level data

Country-scoped Explore reports request public city-resolution data alongside regional data, populating interestByCity and cityCount. Unavailable city requests produce a warning and partial coverage. Empty city data is not proof of no search interest. Trending searches are a separate mode described below.

#### Trending searches

Use `mode=trending`, `trendingSearchesCountry=US`, `trendingSearchesTimeframe=24` (4, 24, 48 or 168 hours), optional category IDs and `trendingSearchesMaxItems`. Returns actual public trending-page queries, source volume, trend start, related queries and category IDs. No keyword is required. An unrecognized source payload fails explicitly. Default keyword mode is unchanged; keyword/predefinedTimeframe aliases are available. Trending rows use the trend-report billing event.

##### Related-query provenance

Numbered RELATED\_QUERIES / RELATED\_TOPICS widgets are supported, and per-term keyword identity is read from each widget request when available. `sourceWidgetDiagnostics` records fetched widget IDs and source ranked-list counts without exposing tokens. Counts describe this source response, not global completeness. This helps distinguish upstream variation from parser loss. Widget variants were checked against the primary pytrends implementation: https://github.com/GeneralMills/pytrends/blob/master/pytrends/request.py.

`fetchRegionalData: false` skips region and city requests, retaining timeline and related queries/topics. Skipped widgets are explicitly marked `skipped_by_input` and do not make an intentionally reduced report partial. The default remains true for existing callers.

The cloud image bundles Playwright and its matching browsers for optional snapshots. For local snapshot runs, install Playwright and Chromium (`pip install playwright` then `python -m playwright install chromium`); ordinary HTTP data extraction and default runs do not launch a browser.

If browser navigation times out, snapshot capture still attempts to preserve the current page and marks it `saved_after_navigation_error` when successful. Such a snapshot can be incomplete or blank; `finalUrl`, the navigation error type and the saved files distinguish it from a normally loaded page.

Snapshot HTML reads, screenshots, storage writes and browser cleanup have separate deadlines. HTML failure still permits a PNG attempt. A saved snapshot may show an HTTP error page; HTTP 4xx/5xx is explicitly included in debugSnapshotWarning, and is not proof that the Google Trends chart rendered.

Regional output follows the source GEO\_MAP resolution: COUNTRY → interestBy, REGION → interestBySubregion, DMA → interestByMetro, CITY → interestByCity. US state queries request available metro data without renaming city rows. `regionalDataStatus` and `sourceGeoResolution` record actual retrieval. Keyword geo values such as US-CA are accepted; trending-country mode still requires a country code. Snapshots honor `pageLoadTimeoutSecs` and explicitly supplied proxy settings.

When proxyConfiguration is explicitly enabled, all extraction requests use it from the first attempt, and missing routing fails clearly. Omitting it preserves the existing direct-first optional recovery behavior.

If native snapshot navigation fails, the Actor can retrieve that same public HTML document over the selected route, then render it in Chromium with the original URL and scripts. This uses only a fresh anonymous session. It is labelled `http_document_browser_render` with original HTTP status and initial-attempt diagnostics; charts are not fabricated from the dataset. Failed/non-HTML/non-Trends documents are not substituted.

Recovered Explore snapshots wait for an actual timeline SVG before capture. If the chart does not become ready within the configured timeout, saved files are marked partial with pageReadyStatus=widget\_not\_ready instead of being reported as a fully rendered page.

After the settling delay and before reading HTML or taking the screenshot, recovered Explore snapshots recheck the timeline: the SVG must be visible, have a painted nonempty line path, and contain numeric 0–100 data in its associated accessible table. `readinessCheckTiming=before_artifact_capture` records this checkpoint; `readyAfterWaitTimeout=true` means this stronger check passed after the initial selector wait timed out. A hidden or empty SVG remains partial even if the later DOM count is positive. This establishes timeline readiness at that checkpoint, not atomic HTML/PNG capture or completeness of every related-data panel.

##### Explicit data\_xplorer input profile

Use `dataXplorerInput` as a JSON object (the form uses a JSON editor, not a string containing JSON). Omit this envelope to keep native defaults: keyword mode, ChatGPT fallback, and regional data enabled.

```json
{"dataXplorerInput":{"trendingSearchesMaxItems":1}}
```

The isolated defaults are copied from the saved data\_xplorer input contract: `mode=trending`, `keyword=bitcoin`, `predefinedTimeframe="today 12-m"`, `geo=""`, `fetchRegionalData=false`, `trendingSearchesCountry=US`, `trendingSearchesTimeframe="24"`, `trendingSearchesCategories=[]`, and `proxyConfiguration={"useApifyProxy":true}`. The optional trending item limit has no schema default; omitted or null uses the existing 50-item runtime fallback. Explicitly enabled proxy routing applies from the first request; this profile does not change the native routing default.

```json
{"dataXplorerInput":{"mode":"keyword","keyword":"Python","geo":"US","fetchRegionalData":true,"skipDebugScreen":false}}
```

Put all settings inside the envelope, including native extensions such as `skipDebugScreen`, `viewedFrom`, `startUrls`, or `timeRange`. Automatically inserted outer native schema defaults are ignored; other outer settings are rejected to avoid ambiguous precedence. UI prefills are not defaults. Unknown fields, invalid types/enums/ranges and duplicate category values are rejected. Defaults are copied per call and explicit values win. `searchTerms`, `startUrls`, or `spreadsheetId` suppress the fallback bitcoin keyword; `timeRange`/`customTimeRange` suppress the competitor timeframe default. Existing URL geo precedence, metro extraction, snapshot behavior and proxy conflicts still apply. This is input compatibility, not a claim of identical competitor output or live success across all modes.

### Support

Open an issue from this Actor’s **Issues** tab with the run ID, expected result and a redacted input. Do not include tokens, cookies or private credentials. Include the output profile and affected field when reporting a migration mismatch.

### Presentation update

The current listing adds workflow examples, grouped input documentation, output-field explanations and plan-based result discounts. Source-specific limitations above still apply. This is an independent tool and is not affiliated with the source platform.

# Actor input Schema

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

One or more Google Trends search terms. With Multiple terms enabled, comma-separated terms are compared in the same Google Trends request.

## `isMultiple` (type: `boolean`):

Treat commas inside each searchTerms entry as comparison separators. Google Trends supports up to five terms per comparison group.

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

Choose a predefined Google Trends time window. Empty means Past 12 months.

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

Choose Worldwide or a country; custom subdivisions such as US-CA remain accepted. A geo in a start URL takes precedence for that URL. Source availability determines regional/city/metro coverage.

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

Choose a named Google Trends category or enter a numeric category ID. Blank/0 means all categories.

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

Paste Google Trends Explore URLs. q, geo, date, cat and gprop parameters are preserved.

## `spreadsheetId` (type: `string`):

Optional public one-column Google Sheet. The first row is treated as a header.

## `requestDelayMillis` (type: `integer`):

Minimum spacing in milliseconds between Google Trends HTTP request starts across all workers.

## `viewedFrom` (type: `string`):

Optional proxy-origin country, separate from the data geography. Requires available Apify residential proxies; custom two-letter country codes remain accepted.

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

Historical keyword reports or live trending searches.

## `keyword` (type: `string`):

Single search term alias.

## `predefinedTimeframe` (type: `string`):

Alias for timeRange.

## `trendingSearchesCountry` (type: `string`):

Trending-search input; same field name as data\_xplorer.

## `trendingSearchesTimeframe` (type: `string`):

Trending-search input; same field name as data\_xplorer.

## `trendingSearchesCategories` (type: `array`):

Trending-search input; same field name as data\_xplorer.

## `trendingSearchesMaxItems` (type: `integer`):

Trending-search input; same field name as data\_xplorer.

## `fetchRegionalData` (type: `boolean`):

Fetch regional and city data. Disable to skip regional requests while retaining timeline and related data.

## `dataXplorerInput` (type: `object`):

Explicit data\_xplorer input object. Defaults to trending mode and fetchRegionalData=false using the frozen competitor contract. Put all settings inside this object, including optional native snapshot/URL settings. Outer non-default settings cannot be mixed. Omit this field to retain native defaults.

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

Maximum number of report rows. Zero means no limit.

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

Retries for transient network errors and 403/408/429/5xx responses.

## `rateLimitRecoverySeconds` (type: `integer`):

Wait before each direct-only 429 recovery round. When an Apify fallback proxy is available, proxy recovery starts immediately. Zero disables waiting.

## `rateLimitRecoveryRounds` (type: `integer`):

Maximum number of bounded batch-level 429 recovery rounds. Each round retries only groups that are still rate-limited.

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

Optional YYYY-MM-DD YYYY-MM-DD range. Takes precedence over timeRange.

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

Used only for retrying groups that Google rate-limits on the direct connection. The fast first pass remains direct.

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

Maximum number of independent Google Trends comparison groups processed in parallel.

## `pageLoadTimeoutSecs` (type: `integer`):

Per-request timeout in seconds for Google Trends HTTP calls.

## `skipDebugScreen` (type: `boolean`):

When false, save a real Chromium PNG and HTML snapshot for every requested Explore or trending page to the run key-value store. Optional browser diagnostics run after data delivery; failure does not discard results. Defaults to true to avoid browser overhead.

## `enableTrendingSearches` (type: `boolean`):

Legacy Data Xplorer alias. When supplied, overrides mode: true selects trending, false selects keyword. Leave unset for normal mode selection.

## `outputSchema` (type: `string`):

Native preserves detailed widget rows. data-xplorer returns timeline\_data reports, or one bundled trending\_searches report per run. A delivered bundle counts as one report event; platform usage is additional. Use native for multi-term comparisons.

## Actor input object example

```json
{
  "searchTerms": [
    "ChatGPT"
  ],
  "isMultiple": false,
  "geo": "",
  "category": "",
  "requestDelayMillis": 0,
  "mode": "keyword",
  "fetchRegionalData": true,
  "maxItems": 0,
  "maxRequestRetries": 4,
  "rateLimitRecoverySeconds": 30,
  "rateLimitRecoveryRounds": 2,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 4,
  "pageLoadTimeoutSecs": 30,
  "skipDebugScreen": true
}
```

# Actor output Schema

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

All trend-report and structured error rows produced by the run.

## `summary` (type: `string`):

Run-level result, error, partial, HTTP request and retry counts.

# 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": [
        "ChatGPT"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("peerless_columbine/google-trends-scraper-api").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": ["ChatGPT"] }

# Run the Actor and wait for it to finish
run = client.actor("peerless_columbine/google-trends-scraper-api").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": [
    "ChatGPT"
  ]
}' |
apify call peerless_columbine/google-trends-scraper-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,peerless_columbine/google-trends-scraper-api"
        }
    }
}

```

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/GVtdsp1ENtWCFbYVo/builds/HboMxL1YcGL9JKFRc/openapi.json
