Google Trends Scraper (Reliable, No Browser) avatar

Google Trends Scraper (Reliable, No Browser)

Pricing

from $2.00 / 1,000 results

Go to Apify Store
Google Trends Scraper (Reliable, No Browser)

Google Trends Scraper (Reliable, No Browser)

Fast, retry-hardened Google Trends scraper. Interest over time, related queries, related topics, interest by region. No browser = lower cost and fewer failures.

Pricing

from $2.00 / 1,000 results

Rating

0.0

(0)

Developer

Steady API

Steady API

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 hours ago

Last modified

Share

Google Trends Scraper — Reliable, No Browser

Get Google Trends data that actually comes back. No headless browser, no silent empty runs.

Pull interest over time, related queries, related topics and interest by region for any keyword, country and time range.


Why this Actor exists

Google Trends has no official API, so most scrapers either drive a headless browser (slow and expensive) or call the internal endpoints without handling how Google gates them. Both break often.

Here is the thing that most implementations miss:

The Google Trends internal API returns 429 Too Many Requests on the very first call if you do not carry an NID cookie. It is not a rate limit. It is a gate.

Measured on 2026-09-15:

RequestResult
/trends/api/explore with no cookie429
Same call after one visit to trends.google.com to pick up NID200

This Actor treats "proxy IP + the cookie issued to that IP" as a single session. When a session gets gated, it throws away the whole session and builds a new one. Refreshing only the cookie does not help, because the IP is already flagged.

What you get

  • No browser. Direct JSON endpoints only. Runs finish in seconds and cost a fraction of a browser-based Actor.
  • Retry that understands the failure. Exponential backoff with jitter on 429 and 5xx. Empty 200 bodies are treated as a silent throttle and retried, not returned as success.
  • Partial success by default. One bad keyword does not kill the run. Failed keywords come back as rows with an error and an errorType so you know exactly what is missing and why.
  • A run summary you can assert on. RUN_SUMMARY in the key-value store gives you requested, succeeded, failed, successRate and proxySessionsUsed.
  • You are not charged for failed keywords.

Input

FieldTypeDefaultNotes
keywordsarrayrequiredOne or more search terms
compareKeywordsbooleanfalseOn: one comparison chart, max 5 keywords, values relative to each other. Off: each keyword on its own 0-100 scale
timeframestringtoday 12-mnow 1-Htoday 5-y, all
geostring"" (worldwide)US, GB, DE, JP, or sub-regions like US-CA
includeInterestOverTimebooleantrueThe main trend line
includeRelatedQueriesbooleanfalseTop and rising queries
includeRelatedTopicsbooleanfalseTop and rising topics
includeInterestByRegionbooleanfalseCountry or sub-region breakdown
categoryinteger0Google Trends category ID
propertystring"""" web, images, news, youtube, froogle
hl / tzstring / inten-US / 0Response language and timezone offset in minutes (0 = UTC)
requestDelayMsinteger1200Raise for very large keyword lists
proxyConfigurationobjectDatacenterSwitch to Residential for thousands of keywords

Example

{
"keywords": ["bitcoin", "ethereum", "solana"],
"geo": "US",
"timeframe": "today 3-m",
"includeInterestOverTime": true,
"includeRelatedQueries": true
}

Output

One dataset row per keyword (or per comparison group).

{
"keywords": ["bitcoin"],
"geo": "US",
"timeframe": "today 3-m",
"category": 0,
"property": "web",
"scrapedAt": "2026-09-15T13:02:11.482Z",
"interestOverTime": [
{ "date": "Jun 15, 2026", "timestamp": 1781481600000, "values": [89], "isPartial": false },
{ "date": "Sep 15, 2026", "timestamp": 1789430400000, "values": [44], "isPartial": true }
],
"relatedQueries": {
"top": [{ "query": "bitcoin price", "value": 100, "formattedValue": "100" }],
"rising": [{ "query": "british man recovers lost bitcoin", "formattedValue": "Breakout" }]
}
}

isPartial: true marks the current, still-incomplete bucket. Drop those points before charting if you need clean series.

A failed keyword looks like this instead:

{
"keywords": ["some-term"],
"error": "429 Too Many Requests — temporarily gated by Google",
"errorType": "BLOCKED_OR_UNAVAILABLE",
"scrapedAt": "2026-09-15T13:02:14.113Z"
}

errorType is either INVALID_REQUEST (your input will never work, fix it) or BLOCKED_OR_UNAVAILABLE (retry later or use Residential proxy).

Notes on the data

Google Trends values are relative, not absolute search volume. 100 is the peak of the selected range, everything else is scaled to that. Two separate runs are not directly comparable unless you use compareKeywords.

Tips

  • Scraping thousands of keywords: set proxyConfiguration to Residential and requestDelayMs to 3000.
  • Comparing brands: turn on compareKeywords so the numbers share one scale.
  • Building a dashboard: use timestamp (epoch ms), not date, which is a localized display string.

Only public Google Trends data is requested. No login, no personal data, no private endpoints.