If you've landed here, you probably just discovered one of two things: pytrends — the unofficial Google Trends library the entire Python ecosystem relied on for a decade — was archived in April 2025 and no longer works reliably, or Google's long-promised official Trends API is still in limited-access alpha and you can't get in.
Meanwhile you have a dashboard, a research pipeline, or an SEO report that needs interest-over-time data. Here's the honest state of your options in 2026.
What actually powers Google Trends
There's no public API, but the Trends website itself is a JavaScript app fed by JSON endpoints — the same data you see in the charts, served as structured JSON. The flow is a two-step "token dance":
- Call
/trends/api/explorewith your keywords, geo, and timeframe. It returns a set of widgets, each with a token — one for the timeline, one for the region map, one each for related queries and topics. - Call the matching widgetdata endpoint (
multiline,comparedgeo,relatedsearches) with that token to get the actual data.
Two quirks to know: every response starts with an anti-XSSI prefix ()]}') you must strip before parsing, and you need a session cookie from an initial page visit — amusingly, Google can answer that first HTML request with HTTP 429 while still setting the cookie and serving the JSON API just fine.
Option 1: Build it yourself
A minimal working example (Python, plain requests, no browser):
import json, requests
s = requests.Session()
s.headers.update({"User-Agent": "Mozilla/5.0 ...", "Accept-Language": "en-US,en;q=0.9"})
s.get("https://trends.google.com/trends/explore") # cookie warm-up (ignore the status)
req = {"comparisonItem": [{"keyword": "standing desk", "geo": "US", "time": "today 12-m"}],
"category": 0, "property": ""}
r = s.get("https://trends.google.com/trends/api/explore",
params={"hl": "en-US", "tz": "360", "req": json.dumps(req)})
widgets = json.loads(r.text.split("\n", 1)[1])["widgets"] # strip )]}' prefix
w = next(x for x in widgets if x["id"] == "TIMESERIES")
r = s.get("https://trends.google.com/trends/api/widgetdata/multiline",
params={"hl": "en-US", "tz": "360",
"req": json.dumps(w["request"]), "token": w["token"]})
timeline = json.loads(r.text.split("\n", 1)[1])["default"]["timelineData"]
This works today. The part that stops being fun is everything around it:
- Rate limits. Google 429s aggressively and unpredictably per IP. Any real workload needs pacing, exponential backoff, cookie-session rotation, and a proxy pool.
- Maintenance. These are internal endpoints; Google reshuffles them occasionally (that's part of what killed pytrends once its maintainers stopped chasing).
-
Edge cases. Example: the region-map widget accepts a
resolutionoverride, but forcing a resolution that doesn't fit the geo (say,REGIONon a worldwide query) makes Google return HTTP 500. There are a dozen little landmines like this.
If you need Trends data once, copy the snippet above and enjoy. If you need it every day, you've just adopted a small maintenance hobby.
Option 2: Use it as a maintained API
I got tired of maintaining exactly that hobby, so I packaged the whole thing as an Apify Actor: Google Trends Scraper. One call gets you, per term:
- Interest over time at Google's finest granularity for your window, with partial-period flags plus computed average and peak
- Interest by region (countries, states, cities, or US metro areas)
- Related queries and topics — top and rising, with "Breakout" markers (the early-signal goldmine for SEO and product research)
- True compare mode — up to 5 terms normalized on one shared 0–100 scale, like the Trends UI comparison
- All five properties: Web, YouTube, News, Images, Shopping
No browser anywhere in the stack — it's the same plain-HTTP flow described above, plus the unglamorous production parts: pacing, backoff, session rotation, per-session proxy identities, and per-term error reporting so one flaky keyword doesn't kill a 50-term run.
curl -X POST "https://api.apify.com/v2/acts/silentshadow55~google-trends-actor/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"searchTerms": ["standing desk", "walking pad"], "geo": "US", "compareAllTerms": true}'
Results export as JSON/CSV/Excel, run on a schedule for daily tracking, and plug into Google Sheets, Make, Zapier, LangChain — or AI agents via Apify's MCP server ("is interest in X growing?" answered with real data). Pricing is per term (about half a cent), with free platform credits covering a trial.
FAQ
What do the 0–100 numbers mean? Relative popularity within your request's timeframe/geo/term set — 100 is the peak of that window, not an absolute volume. To compare terms against each other, they must be requested together (that's what compare mode does).
Which timeframes work? now 1-H through today 5-y, all, and custom ranges like 2025-01-01 2025-06-30. Shorter windows return finer granularity (hourly/daily vs weekly).
Is Google's official API coming? It was announced in 2025 and remains limited-access alpha. When it ships broadly, use it — until then, the website's endpoints are the only public source.
Is scraping Trends legal? It reads the same public, aggregated, anonymized statistics Google shows every visitor at trends.google.com.
I build data tools on Apify — this one exists because I needed it. If a term, geo, or timeframe misbehaves, open an issue on the actor and it'll get fixed fast.
Top comments (0)