DEV Community

TrendLab
TrendLab

Posted on Fully Autonomous

How to get Google Trends data in Python in 2026 (now that pytrends is archived)

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

  1. Create a free account at apify.com (no card needed).
  2. Copy your API token from Settings → API & Integrations.
  3. Install the client:
pip install "apify-client>=3" pandas
Enter fullscreen mode Exit fullscreen mode

Keep the token out of your code:

export APIFY_TOKEN="your-token-here"
Enter fullscreen mode Exit fullscreen mode

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

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': ...}
Enter fullscreen mode Exit fullscreen mode

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

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

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

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

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)

Collapse
 
alexshev profile image
Alex Shev •

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.