If you have a notebook or a cron job that starts with from pytrends.request import TrendReq, you have probably noticed: it breaks more often than it works. The pytrends repository was archived in April 2025. It is read-only now, the last PyPI release (4.9.2) is from 2023, and the 429 Too Many Requests issues pile up with nobody to merge a fix.
I needed Google Trends data for game market research (comparing titles across countries), so I went through the options. Here is what I found, including the one I ended up building. Disclosure up front: option 3 is my own tool, so weigh that part accordingly.
Option 1: The official Google Trends API (alpha)
Google announced an official Trends API in July 2025 on the Search Central blog. It is the "right" long-term answer, but:
- it is an alpha with access by application, opened gradually to a limited number of developers;
- as an alpha, the interface can still change.
Good for: anyone who can wait and wants an official source. Apply early; it costs nothing to be on the list.
Option 2: Keep scraping it yourself
pytrends was a thin wrapper around the same internal endpoints the Google Trends website calls. You can keep using those yourself, either with a maintained fork or your own requests code.
What you sign up for:
- 429s. Google rate-limits these endpoints aggressively. You need retries with backoff, and sometimes even that is not enough.
- Maintenance. When the response format or token flow changes, your pipeline breaks until you fix it.
- Relative numbers. Values are scaled 0–100 within one request, so every comparison has to be in the same request (max 5 terms).
Good for: occasional, small, non-critical pulls where a failed run is no big deal.
Option 3: A hosted Google Trends API (what I built)
I wrapped the scraping, retries and caching into an Apify Actor called Google Trends Compare, so the 429 handling is somebody else's problem (mine). You call it from Python with the official apify-client package and get JSON back.
Migration side by side
The old pytrends code:
from pytrends.request import TrendReq
pytrends = TrendReq(hl="en-US", tz=0)
pytrends.build_payload(["minecraft", "roblox"], timeframe="today 12-m", geo="US")
df = pytrends.interest_over_time()
The same request with the Actor (pip install apify-client, version 3 or later):
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("antonio_aleph/google-trends-compare").call(run_input={
"keywords": ["minecraft", "roblox"],
"timeRange": "today 12-m",
"geo": "US",
})
for row in client.dataset(run.default_dataset_id).iterate_items():
if row["status"] == "ok":
points = [(p["date"][:10], p["value"]) for p in row["interestOverTime"]]
print(row["keyword"], points[-3:])
else:
# Google kept rate-limiting this group: delivered as a row, not charged
print(row["keyword"], row["status"], row["sectionErrors"])
Output when I ran it (November 2026, US, weekly points):
minecraft [('2026-10-18', 78), ('2026-10-25', 73), ('2026-11-01', 66)]
roblox [('2026-10-18', 59), ('2026-10-25', 56), ('2026-11-01', 57)]
The mapping from pytrends calls:
| pytrends | Actor input |
|---|---|
build_payload(kw_list, timeframe, geo, cat, gprop) |
keywords, timeRange / customTimeRange, geo, category, searchType (web, youtube, news, images, shopping) |
interest_over_time() |
always included (interestOverTime) |
interest_by_region(resolution=...) |
interestByRegion: true, regionResolution
|
related_queries() |
relatedQueries: true (top and rising) |
| one payload per call | up to 10 comparison groups per run (keywordGroups) |
What it does about 429s (honestly)
It does not use proxies or rotate IPs to get around Google's limits. Instead:
- each request is retried after 10, 30 and 60 seconds;
- identical requests are served from a 6-hour cache (
fromCache,fetchedAttell you); - a group that still fails comes back as a row with
status: "failed"and is not charged; - runs stop at a time limit you set (
maxRunSeconds, default 180 s), and unfinished groups are free.
So you can still get a failed group on a bad day. The difference is that your code gets a clear status per keyword instead of an exception halfway through a loop.
Cost
It is pay per result, with no subscription: $0.003 per comparison group of up to 5 keywords on Apify's free plan (less on paid plans). Region and related-query data are included in that price. Failed and timed-out groups cost $0. Apify's free plan includes a monthly usage credit, which covers a lot of $0.003 calls.
Good for: scheduled jobs, dashboards and AI agents that need predictable JSON and don't want to babysit a scraper.
Option 4: Other hosted scrapers and SERP APIs
Several SERP/scraping APIs and other Apify Actors also return Google Trends data. They differ in pricing model (per request, per result, monthly plans), in whether they use proxies, and in output shape. If you already pay for one of them, check whether Trends is included before adding another tool.
Things that trip people up, whichever option you pick
-
valueis not a search count. It is 0–100 relative to the highest point in that request. - Only compare numbers from the same request. Two separate requests are scaled differently. Put the terms in one group (max 5), or keep one shared "anchor" keyword in every group.
- 0 can mean "not enough data", not "nobody searched".
-
The latest point is usually partial. Check
isPartialbefore you plot a dramatic drop in the current week. - The time step changes with the range: hours for a day, days for 1–3 months, weeks for 12 months to 5 years, months for 2004–present.
Which one should you use?
- Can wait, want official: apply for the Google Trends API alpha.
- A few pulls a month, failures are fine: your own scraper or a fork.
- Scheduled pipeline or agent, want JSON and per-keyword status: a hosted API like the Actor above, or whatever SERP API you already have.
If you try the Actor and something is missing (a field, a parameter pytrends had), tell me in the comments. That is exactly the feedback I am looking for.
This post was written with help from an AI assistant. The Actor example was run before publishing (output above), and the facts about pytrends and the official API were checked against their public sources.
Top comments (0)