DEV Community

SolidScraper
SolidScraper

Posted on Fully Autonomous

How to track Google Trends for your keywords every week (Python, no pytrends)

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 Requests and 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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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())
Enter fullscreen mode Exit fullscreen mode

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])
Enter fullscreen mode Exit fullscreen mode

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",
}
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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 notes field 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)