Google Trends Scraper: Interest Over Time, Regions & Queries
Pricing
Pay per event
Google Trends Scraper: Interest Over Time, Regions & Queries
Get Google Trends interest over time, interest by region and top and rising related queries for any term, region and time range, plus daily trending searches. $3 per 1,000 trend rows, $1 per 1,000 trending searches, proxy included; failed queries are free.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Changefeeds Tools
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Share
Google Trends Scraper: Interest Over Time, Regions & Related Queries
- What you get: for each search term and region, the data the trends.google.com Explore page shows: interest over time, interest by region, and top and rising related queries. Optionally today's trending searches per country.
- Built for Google's 429s: residential proxy, cookie handling and up to 8 fresh sessions per blocked query. No Google account, cookie or API key.
- Price: $3 per 1,000 trend rows and $1 per 1,000 trending searches, proxy included. Blocked, failed and no-data queries are free.
Sample output
The prefilled input (chatgpt, US, past 90 days), run on 2026-10-23, gave one
row. Its contents:
| Part of the row | What came back |
|---|---|
timeline | 93 daily points, 2026-07-23 to 2026-10-23. Last three: Oct 21 = 80, Oct 22 = 79, Oct 23 = 69 (isPartial: true) |
regions | 51 (50 states + DC). Top three: California 100, New Jersey 95, Texas 95 |
relatedQueries.top | 25. First three: "chatgpt ai" 100, "chatgpt login" 73, "chatgpt free" 61 |
relatedQueries.rising | 7. First three: "sam altman chatgpt water usage" Breakout, "chatgpt astra" +2,250%, "chatgpt student offer" +500% |
relatedTopics | empty (Google returned none; see Limits) |
The same row as JSON, with each list cut to its first entries:
{"type": "trend","input": "chatgpt","terms": ["chatgpt"],"term": "chatgpt","compared": false,"geo": "US","timeRange": "today 3-m","resolvedTime": "2026-07-23 2026-10-23","resolution": "DAY","category": 0,"property": "","timeline": [ // 93 daily points; last 2 shown{ "time": 1792627200, "date": "2026-10-22T00:00:00.000Z", "formattedTime": "Oct 22, 2026", "value": 79, "values": [79], "isPartial": false },{ "time": 1792713600, "date": "2026-10-23T00:00:00.000Z", "formattedTime": "Oct 23, 2026", "value": 69, "values": [69], "isPartial": true }],"averages": null,"regions": [ // 51; top 2 shown{ "geoCode": "US-CA", "geoName": "California", "value": 100, "values": [100] },{ "geoCode": "US-NJ", "geoName": "New Jersey", "value": 95, "values": [95] }],"regionResolution": "REGION","relatedQueries": {"top": [ // 25; first shown{ "term": "chatgpt", "query": "chatgpt ai", "value": 100, "formattedValue": "100", "link": "https://trends.google.com/trends/explore?q=chatgpt+ai&date=today+3-m&geo=US" }],"rising": [ // 7; first shown{ "term": "chatgpt", "query": "sam altman chatgpt water usage", "value": 7900, "formattedValue": "Breakout", "link": "https://trends.google.com/trends/explore?q=sam+altman+chatgpt+water+usage&date=today+3-m&geo=US" }]},"relatedTopics": { "top": [], "rising": [] },"exploreUrl": "https://trends.google.com/trends/explore?date=today+3-m&geo=US&q=chatgpt&hl=en-US","notes": ["Google returned an empty related-topics list for \"chatgpt\"."],"noData": false,"scraped_at": "2026-10-23T03:49:26.658Z"}
How to run in 30 seconds
- Click Try for free. The input already holds
chatgpt, regionUS, past 90 days. - Click Start. Our test run of that input took 16 seconds and returned one trend row: $0.003 at today's price (that run was billed $0.004, the price until 2026-10-23).
- Open the Output tab, or export the dataset as JSON, CSV or Excel.
For your own terms, replace chatgpt in Search terms or Trends URLs (or
paste a trends.google.com Explore URL), and change Region and Time range.
Tick Compare terms together to put up to 5 terms on one 0-100 scale.
Pricing
- $0.003 per trend row (
trend-returned), $3 per 1,000. One row is a term (or a group of up to 5 compared terms) in one region, with its timeline, regions and related queries. Proxy traffic is included. - $0.001 per trending row (
trending-returned). - Free: status rows (blocked, invalid, error), trend rows where Google had
no data at all (
noData: true), and therun_inforow. - If you set a maximum total charge, the actor checks the remaining budget
before every query, never fetches a row it could not bill, and stops cleanly
with
"max_total_charge_reached"inOUTPUT.stopped_reason.
Example: tracking 20 keywords every week is 20 rows × about 4.3 runs a month, so about 86 rows, or about $0.26 a month.
FAQ
Do I need a Google account or API key? No.
Is this the official Google Trends API? No. It reads the same public JSON endpoints the trends.google.com page uses.
Why are my numbers different from the website? Check that you use the
same region, time range, category and search type (the exploreUrl on each
row opens exactly what was queried), and that you compared the same terms
together. Google also re-samples, so small differences are normal.
Can I get more than 5 terms on one scale? Google compares at most 5 terms at a time. A common workaround is to put one anchor term in every group and rescale the groups against it. The actor does not do that for you.
Can I compare this week's run with last week's? Not directly: Google
rescales every request from 0 to 100. Compare points inside one run's
timeline instead. With today 3-m you get daily points, so read the last 7
complete days against the previous 7 and skip the final isPartial point.
How do I track keywords every week? Save the input as a task, add a
schedule (for example cron 0 8 * * 1, Mondays 08:00; a new schedule starts
disabled, so enable it), and add Google Sheets, Zapier, Make or n8n under the
task's Integrations. A plain webhook sends run metadata, not rows; fetch
the items from the run's resource.defaultDatasetId
(webhook docs).
Limits
- Google's numbers are relative, not search counts. Every value is scaled 0-100 within its own query. The same term alone and inside a comparison gives different numbers, and so do two different time ranges.
- Google's own sampling. Re-running a query can shift values by a point or two, and very small terms flicker between some data and none.
- Related topics usually come back empty. In every live test so far
(September and October 2026) Google returned an empty related-topics list to
this client, even for big terms. The actor passes on what Google returns and
says so in
notes. The comparison view has no related topics at all. - Rising queries are Google's list, noise included. On 2026-10-03 we saw "how to cook pasta" as a rising query for "ai agents" on the Explore page itself. Keeping only rising queries that contain your term removes most of it, but also drops close variants.
- Trending searches are Google's RSS feed: about 10 current searches per
region, with traffic buckets like
"500+"and a few news links. Not the full list on the website, and not historical. - Blocking can still win. A query still blocked after 8 new sessions is
reported as a free
blockedrow, not retried forever. Without a proxy (your own IP) the actor only backs off and retries 3 times. - It stays polite: one query at a time, at least 0.5 s between requests, 5xx retried with backoff, Retry-After honoured up to 60 s. It never tries to solve Google's CAPTCHA.
Input reference
| Field | Type | Default | What it does |
|---|---|---|---|
searchTerms | list of strings | — | Terms to look up. You can also paste trends.google.com/trends/explore?q=... URLs: a URL is fetched with its own terms, geo, date, cat and gprop, and the terms in one URL are compared together. Topic ids like /m/0dl567 work too. |
compareTogether | boolean | false | Off: each term is queried alone (scaled 0-100 against itself). On: terms are compared in groups of up to 5 (Google's limit), one row per group, scaled against each other. |
geo | string | "" | Empty = worldwide. A country (US), subregion (US-CA, GB-ENG) or metro (US-CA-807). Comma-separated codes give one row per term per region. |
timeRange | select | today 12-m | now 1-H, now 4-H, now 1-d, now 7-d, today 1-m, today 3-m, today 12-m, today 5-y, all (2004 to present). A custom YYYY-MM-DD YYYY-MM-DD range is also accepted. |
category | integer | 0 | A Trends category id (the cat= value in a Trends URL). 0 = all categories. |
property | select | "" | "" web search, images, news, froogle (Google Shopping), youtube. |
includeRegions | boolean | true | Add interest by region. One extra request per row. |
includeRelated | boolean | true | Add top and rising related queries (and related topics for single terms). |
trendingNow | boolean | false | Also output today's trending searches for each region in geo (US when geo is empty). Works with no search terms. |
proxy | proxy | residential, US | Leave on. Turn off only when running from your own network. |
Three AI assistants compared in the US over 90 days:
{ "searchTerms": ["chatgpt", "gemini", "claude"], "compareTogether": true, "geo": "US", "timeRange": "today 3-m" }
Output reference
trend rows
timeline[].valueis the 0-100 interest for a single-term row. In a comparison row it isnull: usevalues, one number per entry interms, in the same order. A bucket Google marks as having no data isnull, not0.isPartial: truemarks the latest, still-incomplete bucket.averagesis Google's per-term average for the range. Google returns it only for comparisons; single-term rows havenull.regionsin a single-term row are 0-100 relative to the top region. In a comparison row they are each term's share of that region's searches among the compared terms, in percent. Regions with no data are left out.regionResolutionsays whether these are countries, regions (states) or DMA metros.relatedQueries.topvalues are 0-100 relative.risingvalues are the percent increase; Google labels increases over 5000 % as "Breakout", kept informattedValue. Every item carries thetermit belongs to.notessays why a field is empty, for example too little search volume.exploreUrlopens the same query on trends.google.com.
When Google has no data at all for a query you still get the row, with empty
fields, a note and noData: true. It is not charged.
trending rows
From a live run (trendingNow: true, geo: "US,GB", 2026-09-30), trimmed:
{"type": "trending","geo": "US","title": "evan bouchard","approxTraffic": "500+","approxTrafficMin": 500,"pubDate": "2026-09-30T05:00:00.000Z","picture": "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRY6KarQldgLOIhenYpGzGBRIYWIYlvzsuSV99HI_Y-MKGguer3T3D_orYEPAo","pictureSource": "NHL.com","newsItems": [ // 3; first shown{"title": "Bouchard earns second hat trick","snippet": null,"url": "https://www.nhl.com/video/van-edm-bouchard-has-a-hat-trick-against-the-canucks-6405939435112","picture": "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRY6KarQldgLOIhenYpGzGBRIYWIYlvzsuSV99HI_Y-MKGguer3T3D_orYEPAo","source": "NHL.com"}],"exploreUrl": "https://trends.google.com/trends/explore?date=now+1-d&geo=US&q=evan+bouchard&hl=en-US","scraped_at": "2026-09-30T05:25:34.633Z"}
status rows (free)
{ "type": "status", "input": "chatgpt", "mode": "trend", "geo": "US", "status": "blocked", "error": "HTTP 429: Google reported unusual traffic from this IP; still blocked after 8 proxy rotations", "checked_at": "2026-09-30T05:25:18.678Z" }
invalid: not a usable term, Trends URL or geo code, or Google rejected the query with HTTP 400 (bad category or time range).blocked: Google kept answering 429 after every retry and rotation.not_found: the trending feed for a region had no items.error: any other HTTP or network failure.
The key-value store record OUTPUT holds a run summary: rows by type, charged
counts per event, stopped_reason, truncated_inputs (what was skipped because
the budget ran out), HTTP requests, retries and proxy rotations. Every run writes
at least one dataset row.
How blocking is handled
- Google's first-contact 429 (the one that hands out an
NIDcookie) is recognised as a cookie handshake and retried at once with that cookie. - A real block (a 429 "unusual traffic" page, or a redirect to Google's consent or sorry page) makes the actor wait, move to a new proxy session (a new IP) with a new cookie, and try again, up to 8 times with growing backoff.
- A query still blocked after that becomes a free
blockedrow and the run moves on; one bad query never fails the whole run.
Troubleshooting: pytrends 429 TooManyRequestsError
If you use pytrends and hit
ResponseError: The request failed: Google returned a response with code 429
(TooManyRequestsError), you have met one of the library's longest-running
issues. It happens whether you make one request or a thousand.
Why it happens
There is no public Google Trends API. pytrends reverse-engineers the requests
the trends.google.com website makes, so every call is an anonymous, cookie-less
request against an interface Google did not design for programs. Google
rate-limits that pattern by IP, and seemingly by request velocity and shape.
Free fixes
- Add retries with backoff at construction time:
from pytrends.request import TrendReqpytrends = TrendReq(hl='en-US',tz=360,retries=2,backoff_factor=0.5,)
- Space out requests and batch fewer keywords per call (Trends compares up to 5 terms at a time).
- Route through your own rotating residential proxies:
TrendReqaccepts aproxiesparameter. - Add jitter and cache aggressively; only re-fetch what is stale.
None of this guarantees success, and Google's backend changes without notice.
What this actor does about it
Residential proxy with per-session cookie handling and rotation, retrying through fresh IPs up to 8 times with backoff. Blocked and no-data queries are not charged.