If you have ever pulled Google Trends data from Python, you have probably used pytrends. And you have probably met this:
pytrends.exceptions.TooManyRequestsError: The request failed: Google returned a response with code 429
Two things changed in the last couple of years:
- pytrends is archived. The repository was archived by its maintainers and hasn't received a commit since August 2024, so breakages on Google's side don't get fixed anymore.
- Google Trends rate-limits hard. A few requests in a row from the same IP are enough to get HTTP 429 errors, which is painful as soon as you track more than a handful of keywords, or run a script on a schedule from a server.
In this post I'll show how to get the same data (interest over time, interest by region, related queries and topics) into pandas with a few lines of Python, using a hosted scraper that handles the rate limits for you, and how to schedule it with no code at all.
Disclosure: I built the Google Trends Scraper used below. It runs on Apify, which has a free plan with monthly credits, so you can follow this tutorial without paying anything.
What we'll get
For each keyword, one JSON item with:
-
interestOverTime: the full time series (0–100 index, like on trends.google.com) -
interestByRegion: countries, regions/states, cities or US metros -
relatedQueries: top and rising searches (+400%,Breakout) - ready-made metrics:
averageInterest,latestInterest,peakInterestDate -
googleTrendsUrl: a link to the same chart on trends.google.com, handy to double-check
Step 1: get an API token
Create a free account on Apify, then copy your API token from Settings → API & Integrations. Install the Python client and pandas:
pip install apify-client pandas
Step 2: run the scraper from Python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("featherscrape/google-trends-scraper").call(run_input={
"keywords": ["bitcoin", "ethereum", "solana"],
"compareKeywords": True, # same 0-100 scale for all keywords, like on trends.google.com
"geo": "US", # empty string = worldwide; also "US-CA", "FR-IDF"...
"timeRange": "today 3-m", # or "today 12-m", "today 5-y", "now 7-d"... or "2025-01-01 2025-06-30"
"searchType": "web", # or "youtube", "news", "shopping", "images"
})
items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
print(len(items), "keywords")
When Google answers with a 429, the scraper retries with a fresh session and a new IP, so you don't need any sleep() or retry logic on your side. You're charged per keyword returned; keywords that fail after all retries aren't charged.
Step 3: interest over time in a DataFrame
import pandas as pd
frames = []
for item in items:
df = pd.DataFrame(item["interestOverTime"])[["date", "value"]]
df["keyword"] = item["keyword"]
frames.append(df)
trends = (pd.concat(frames)
.assign(date=lambda d: pd.to_datetime(d["date"]))
.pivot(index="date", columns="keyword", values="value"))
print(trends.tail())
trends.plot(title="Google Trends, US, last 90 days")
Because compareKeywords is on, the three columns share the same scale, exactly like the comparison chart on trends.google.com. Turn it off and each keyword gets its own 0–100 scale instead, which is better when you track many unrelated keywords.
Step 4: where is the interest, and what's rising?
for item in items:
top_regions = item["interestByRegion"][:5]
rising = item["relatedQueries"]["rising"][:5]
print(f'\n{item["keyword"]} (peak on {item["peakInterestDate"][:10]})')
print(" top regions:", ", ".join(f'{r["name"]} {r["value"]}' for r in top_regions))
print(" rising:", ", ".join(f'{q["query"]} ({q["formattedValue"]})' for q in rising))
Rising queries are the most useful part for SEO and content ideas: a Breakout query is one whose search volume grew by more than 5,000% over the period.
No-code option: a weekly report in Google Sheets
If you don't want to run Python at all:
- Open the scraper's page, click Try for free, enter your keywords and run it once.
- In the run's Storage tab, export the results as CSV or Excel, or open the Integrations tab to send each run's data to Google Sheets or Google Drive.
- Create a Schedule (for example every Monday at 8 a.m.) so the data refreshes on its own.
A few Google Trends gotchas
- Values are relative, not search volumes. 100 is the peak popularity for the selected keywords, region and period. Comparing two separate requests only makes sense if they used the same comparison group.
- Kansas is often #1 in the US. Searches that Google can only locate to "United States" are assigned to the country's geographic center, which is in Kansas.
- Numbers move a little between runs. Google Trends is computed on a sample of searches, so expect small variations from one request to the next.
- Related topics are sometimes empty, especially when comparing several keywords. Related queries are usually there.
Wrapping up
pytrends was a great library, but with the project archived and Google's rate limits getting stricter, a hosted scraper is the least painful way I know to get Google Trends data reliably, from a notebook or on a schedule.
If you need a field that isn't there, or hit a bug, open an issue on the scraper's page: I usually answer within 48 hours. And I'd love to hear in the comments what you use Google Trends data for.
Top comments (0)