Disclosure: I maintain one of the paid Google Trends scrapers on the Apify Store, so I'm not neutral about Option 5. I don't link to it here, and the free options come first, because for many people they are enough.
If you're here, you've probably seen this:
pytrends.exceptions.TooManyRequestsError: The request failed: Google returned a response with code 429
This post is the state of things in October 2026: what's actually going on with pytrends, a small test we ran, and five options that work, from free to paid. Pick the one that fits how many keywords you pull and where your code runs.
The facts first
- pytrends is archived. The GitHub repo (GeneralMills/pytrends) was archived by its owner on April 17, 2025 and is read-only. The last release on PyPI is 4.9.2, from April 2023. It still installs and, as you'll see, it still often works.
- 429 is the most common complaint. A GitHub search for "429" in that repo returns 63 issues and pull requests.
-
retries=andbackoff_factor=crash on modern installs. pytrends 4.9.2 passesmethod_whitelistto urllib3'sRetry. urllib3 removed that argument in version 2.0.0 (April 2023). A freshpip install pytrendstoday pulls urllib3 2.x, so this line:
TrendReq(retries=2, backoff_factor=0.5)
fails at the first request with:
TypeError: __init__() got an unexpected keyword argument 'method_whitelist'
So the built-in retry option from many old tutorials doesn't run at all unless you pin urllib3<2.
- Google has an official Trends API, but it's an alpha. Google announced it in July 2025 and is still accepting applications for alpha testers. It offers 5 years of data, consistently scaled values and region data. If you get access, it's the cleanest option. Most people don't have it yet.
A small test: how often does pytrends get a 429?
On October 8, 2026, from a home internet connection, we ran pytrends 4.9.2 against 20 coffee and tea keywords (interest_over_time, US, past 12 months), one keyword per request, with no pause between requests. The connection had already made other Google Trends requests that day:
- 0 of 20 returned data: every request got a 429, all within 16 seconds.
We also ran the same 20 keywords with a 2–4 second pause between keywords and a retry loop (code below), twice:
- 20 of 20 returned data both times. One run, about half an hour before the no-pause test, took 101 seconds and hit one 429, which the loop waited out once (10 seconds). The other started about a minute after the blocked run: the first keyword got three 429s in a row (waits of 11, 23 and 44 seconds), then everything went through, in 158 seconds total.
This is one small test from one connection, not a benchmark. Results from cloud servers, Colab notebooks or CI runners can be worse, because those IP ranges are shared by many users. But it shows the shape of the problem: hammering Google gets you blocked, while pacing and a polite retry loop get the data, at least at small volume.
Option 1: pace your requests and retry properly (free)
Since the built-in retries crash, write the loop yourself. The fetch function below is exactly the one from the test; the loop is shortened to 5 keywords (the test used 20):
import random
import time
from pytrends.request import TrendReq
from pytrends.exceptions import TooManyRequestsError
def fetch(pytrends, kw_list, tries=5, base=10, **payload):
"""interest_over_time with exponential backoff on 429."""
for attempt in range(tries):
try:
pytrends.build_payload(kw_list, **payload)
return pytrends.interest_over_time()
except TooManyRequestsError:
wait = base * 2 ** attempt + random.uniform(0, 5)
print(f"429 on {kw_list}, sleeping {wait:.0f}s")
time.sleep(wait)
raise RuntimeError(f"Still rate-limited after {tries} tries: {kw_list}")
pytrends = TrendReq(hl="en-US", tz=0)
keywords = ["coffee", "tea", "matcha", "espresso", "latte"]
for kw in keywords:
df = fetch(pytrends, [kw], timeframe="today 12-m", geo="US")
print(kw, len(df), "rows")
time.sleep(random.uniform(2, 4)) # be polite between keywords
Three habits that cut requests further:
-
Put up to 5 keywords in one payload when you want them compared anyway.
build_payloadplusinterest_over_timeis two HTTP calls whether you pass 1 term or 5. - Cache what you already downloaded. Weekly data for "today 5-y" doesn't change between runs; save it to a file and only fetch what's new.
- Spread big jobs over hours, not minutes.
Good for: a few dozen keywords a day from your own machine.
Not great for: hundreds of keywords, scheduled jobs on cloud servers, anything that has to finish on time.
Option 2: pytrends with your own proxies (free library, paid proxies)
pytrends accepts a list of HTTPS proxies and moves to the next one after each successful request:
pytrends = TrendReq(hl="en-US", tz=0,
proxies=["https://user:pass@proxy1:port", "https://user:pass@proxy2:port"],
timeout=(10, 25))
Combine it with the retry loop above. It works if your proxies are good (residential IPs are blocked less often than datacenter ones). The cost is that you now maintain proxies, sessions and cookies, and you still depend on an archived library that nobody updates when Google changes something.
Good for: teams that already pay for a proxy pool.
Option 3: download the CSV by hand (free)
For a one-off report, open trends.google.com, enter your terms, and use the download icon on each chart. It's slow, but there's no code to break.
Good for: a single analysis, a slide, a quick check.
Option 4: the official Google Trends API (alpha)
If your project is research or a product that needs Trends data long-term, apply for the alpha. Its data is "consistently scaled", which means you can merge many requests and compare dozens of terms, something the website and pytrends can't do directly.
Good for: anyone who gets accepted. Apply early, because access is limited.
Option 5: a managed scraper or API (paid per use)
If you need many keywords, a schedule, or code that runs on a server without babysitting, pay someone else to deal with IPs and sessions. SerpApi has a Google Trends API, and the Apify Store lists several Google Trends scrapers, including one by Apify itself. Most of them charge per search or per keyword. Before you pick one, compare the price per 1,000 keywords and check two things: whether failed requests are billed, and whether more than 5 keywords can come back on one comparable scale (see the anchor tip at the end).
Good for: hundreds of keywords, scheduled jobs, servers and notebooks where pytrends gets blocked.
Not worth it for: a handful of keywords on your laptop. Use Option 1.
Which one should you use?
| Your situation | Use |
|---|---|
| Up to a few dozen keywords, on your own computer | Option 1: pytrends + pause + retry loop |
| You already pay for a proxy pool | Option 2: pytrends + proxies + retry loop |
| One report, once | Option 3: CSV from trends.google.com |
| Long-term research or product, and you got access | Option 4: official Trends API (alpha) |
| Hundreds of keywords, a schedule, or code on a server | Option 5: a managed scraper or API |
Two things that confuse everyone
- Trends values are not search counts. They are a 0–100 index relative to the peak in your comparison, for the place and time you chose. Every tool above returns the same kind of number, because that's what Google publishes.
- Values from different comparisons aren't comparable. "40" for a keyword compared with "coffee" and "40" for one compared with "tea" are different things. Keep one shared term in every group (an anchor) if you need a single ranking.
The code in this post was run on October 8, 2026 with Python 3.9, pytrends 4.9.2, urllib3 2.6.3 and pandas 2.3.3 (on Python 3.10+ the error message starts with "Retry.init()"). This post was written by AI agents; the tests and numbers come from real runs and were checked by a person before publishing.
Top comments (0)