For years the answer to "how do I get Google Trends data in Python?" was pytrends. That's no longer a good answer:
- The pytrends GitHub repo is archived. The last commit was in August 2024, and it has 150+ open issues.
- The most common one is
TooManyRequestsError/ HTTP 429: Google rate-limits you after a handful of requests, especially from cloud servers. - Google still has no official public Google Trends API.
This post shows how to get the same data (interest over time, interest by region, related queries, comparisons and Trending Now) from Python in a few lines, without fighting 429s.
Disclosure: I built the tool used below, Google Trends Scraper - Fast, No Browser on Apify. It's paid per search, and Apify's free plan includes monthly credit, enough for roughly 2,500 searches.
Setup
- Create a free account at apify.com (no card needed).
- Copy your API token from Settings → API & Integrations.
- Install the client:
pip install "apify-client>=3" pandas
Keep the token out of your code:
export APIFY_TOKEN="your-token-here"
1. Interest over time
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
actor = client.actor("vp916/google-trends-fast")
run = actor.call(run_input={
"searchTerms": ["chatgpt"],
"geo": "US", # country code, or "" for worldwide
"timeRange": "today 12-m", # past 12 months
})
item = next(client.dataset(run.default_dataset_id).iterate_items())
for point in item["interestOverTime"][:3]:
print(point["date"], point["values"]["chatgpt"])
print("average:", item["averages"]["chatgpt"])
Each run returns one item per search line, with interestOverTime, averages, interestByRegion and relatedQueries already parsed.
2. Compare up to 5 terms
Put the terms on one line, separated by commas. That's the same as typing them into the Google Trends compare box, so all terms share one 0-100 scale:
run = actor.call(run_input={
"searchTerms": ["iphone, samsung, pixel"],
"geo": "IN",
"timeRange": "today 3-m",
})
item = next(client.dataset(run.default_dataset_id).iterate_items())
print(item["averages"]) # {'iphone': ..., 'samsung': ..., 'pixel': ...}
Each separate line in searchTerms is a separate search. You can send hundreds in one run.
3. Interest by region: states, cities or US metros
run = actor.call(run_input={
"searchTerms": ["taylor swift"],
"geo": "US",
"regionResolution": "DMA", # COUNTRY, REGION, CITY or DMA (US metro areas)
"includeInterestOverTime": False,
})
item = next(client.dataset(run.default_dataset_id).iterate_items())
top = sorted(item["interestByRegion"], key=lambda r: -(r["values"]["taylor swift"] or 0))[:5]
for r in top:
print(r["geoName"], r["values"]["taylor swift"])
4. Related queries, including "Breakout"
rq = item["relatedQueries"]["taylor swift"]
print([q["query"] for q in rq["top"][:5]])
print([(q["query"], q["formattedValue"]) for q in rq["rising"][:5]])
rising is where the SEO gold is. "Breakout" means growth above 5,000%.
5. Trending Now for any country
run = actor.call(run_input={
"trendingNowGeos": ["US", "IN"],
"trendingNowHours": "24", # 4, 24, 48 or 168
"trendingNowMaxItems": 50,
})
for t in client.dataset(run.default_dataset_id).iterate_items():
print(t["geo"], t["title"], t["searchVolume"], t["categories"])
Each trend comes with search volume, % increase, start time, whether it's still active, category and related searches.
6. Straight into pandas
Set outputFormat to "flat" and you get one row per data point, which loads directly into a DataFrame:
import pandas as pd
run = actor.call(run_input={
"searchTerms": ["python, javascript, rust"],
"timeRange": "today 5-y",
"outputFormat": "flat",
})
df = pd.DataFrame(client.dataset(run.default_dataset_id).iterate_items())
ts = df[df["type"] == "interestOverTime"].pivot(index="date", columns="keyword", values="value")
print(ts.tail())
ts.plot(title="Search interest, worldwide, 5 years")
Why not just retry pytrends?
You can, and for 3 searches on your laptop it may work. It gets painful when you need hundreds of keywords, run it from a server, or want it on a schedule. That's the gap this fills. It runs on Apify's infrastructure, rotates IPs when Google slows down, and talks to Google's JSON endpoints directly instead of opening a browser, so 40 searches take under a minute.
What else would you want from a Google Trends API? I'm adding features based on requests.
Top comments (1)
The flat output is useful for analysis, but the pipeline should retain the query configuration beside every row: geo, timeframe, resolution, collection timestamp, and comparison set. Trends values are normalized, so a chart without that provenance can look like a demand trend when it is only a relative slice.