Google Trends is one of the best free signals for content planning, keyword research and spotting demand before it peaks. Getting the data out of it in a repeatable way is the hard part:
- pytrends was archived in April 2025 and breaks regularly.
- Google's official Trends API was announced in July 2025, but it is still a limited alpha with a waiting list.
- Calling Trends' internal endpoints yourself works, until Google starts answering
429 Too Many Requestsand your script either crashes or hangs.
In this post I'll show a small Python script that pulls Google Trends data for a list of keywords, turns it into a pandas DataFrame and saves it, so you can run it every week. It uses a hosted Google Trends API (an Apify Actor I maintain), so you don't have to deal with proxies, cookies and retries yourself.
Disclosure: I built the Actor used below. It is pay-per-result, and there is a free tier to try it.
What you get
For each keyword (or group of up to 5 keywords compared on the same scale):
- Interest over time: the 0–100 curve, with ISO dates and a flag for the last, still incomplete point
- Interest by region: countries, regions/states or US metro areas (DMA)
- Related queries: top and rising, including Breakout queries
- Trending now: today's top trending searches per country, if you want them
1. Install and get a token
pip install apify-client pandas
Create a free Apify account and copy your API token from Settings → API & Integrations. Keep it in an environment variable rather than in your code:
export APIFY_TOKEN="your-token-here"
2. Fetch the data
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run_input = {
"searchTerms": ["air fryer", "slow cooker", "rice cooker"],
"geo": "US", # country code or name; leave empty for worldwide
"timeRange": "today 12-m", # or "past 90 days", "5 years", "2025-01-01 2025-12-31"
"includeRelatedQueries": True,
}
run = client.actor("solidscrapers/google-trends-scraper").call(run_input=run_input)
items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
print(f"{len(items)} results")
Each search term comes back as one result. Terms that fail or have no data in Google Trends are not in the dataset (and are not charged). They are listed in a separate ERRORS record, so you can see what was skipped and why.
3. Turn it into a DataFrame
import pandas as pd
rows = []
for item in items:
if item["type"] != "keyword":
continue
for point in item["interestOverTime"]:
rows.append({
"keyword": item["searchTerm"],
"date": point["date"],
"interest": point["value"],
"partial": point["isPartial"],
})
df = pd.DataFrame(rows)
df["date"] = pd.to_datetime(df["date"])
wide = df.pivot(index="date", columns="keyword", values="interest")
print(wide.tail())
partial marks the latest point, which Google is still filling in. Drop it if you compare week over week, or it will look like a sudden drop.
4. Find rising queries for content ideas
for item in items:
if item["type"] != "keyword":
continue
rising = item.get("relatedQueries", {}).get("rising", [])
breakouts = [q["query"] for q in rising if q.get("breakout")]
print(item["searchTerm"], "→ breakout:", breakouts[:5])
Breakout means the query grew by more than 5,000% in the period. These are usually the best topics to write about before everyone else does.
5. Compare keywords on the same scale
Google Trends values are relative: 100 is the peak for the terms you asked about together. If you fetch "air fryer" and "slow cooker" separately, both get their own 100 and you can't compare them. To compare them, ask for them together:
run_input = {
"searchTerms": ["air fryer", "slow cooker", "rice cooker"],
"compareTerms": True, # up to 5 terms per group, same 0–100 scale
"geo": "US",
"timeRange": "today 5-y",
}
In comparison mode each point has a values object with one number per keyword, and averageInterest holds Google's own average for each.
6. Run it every week
Save the DataFrame with a date in the file name and schedule the script with cron, GitHub Actions or a scheduled task on Apify:
from datetime import date
wide.to_csv(f"trends_{date.today()}.csv")
If you prefer no code, the same data can go straight to Google Sheets with n8n, Make or Zapier.
Limits worth knowing
I'd rather you know these before you rely on the data:
- Values are relative (0–100), not search volumes. Use them to compare and spot trends, not to estimate traffic.
-
City-level data is sparse. Google gives automated tools less detail at city level than it shows in the browser, especially outside the US and for less popular terms. Regions/states and US metro areas are complete. When a result has little city data, its
notesfield says so. - Related topics are often empty for the same reason. Related queries are not affected.
- Trending now returns Google's trending feed for each country (about 10 searches), not the full Trending now page.
Cost
Pay per result, with no subscription: $1.00 per 1,000 results on Apify's free plan, down to $0.50 on higher plans. A weekly report for 20 keywords costs about 2 cents. Failed terms are never charged.
Link: Google Trends Scraper & API on Apify
If you run into an edge case (an odd keyword, a region that returns nothing, a time range that fails), open an issue on the Actor page. I read all of them.
Top comments (0)