Skip to main content

trendspyg

PyPI version PyPI Downloads Python 3.8+ Tests License: MIT

Python library for Google Trends data — real-time trending topics and keyword analysis over time: interest over time, related queries, interest by region, 2–5-keyword comparison on one shared scale, and YouTube / News / Images / Shopping search interest (gprop). Ships a CLI, an MCP server for Claude and other AI agents, and an opt-in local history archive. A modern, actively-maintained alternative to the archived pytrends, with a pytrends-compatible TrendReq. Docs: flack0x.github.io/trendspyg.

Coming from pytrends? Change the import and your code runs: from trendspyg.compat.request import TrendReq (install trendspyg[analysis]). Its trending calls work again. See Migrating from pytrends for what differs.

Using this library from a coding agent? See AGENTS.md for a concise, agent-ready reference.

Installation

pip install trendspyg

# With async support
pip install trendspyg[async]

# With CLI
pip install trendspyg[cli]

# With DataFrame, JSON and Parquet analysis output
pip install trendspyg[analysis]

# With the MCP server (use trendspyg from Claude & other AI agents; Python 3.10+)
pip install trendspyg[mcp]

# All features
pip install trendspyg[all]

What's new in 1.9.0

pytrends code runs on trendspyg. trendspyg.compat provides pytrends 4.9.2's TrendReq with the same method names, arguments and DataFrame shapes, checked against pytrends itself:

from trendspyg.compat.request import TrendReq   # was: from pytrends.request import TrendReq

pytrends = TrendReq(hl="en-US", tz=360, cache="disk", cookies="disk")
pytrends.build_payload(["coffee"], timeframe="today 5-y")
pytrends.interest_over_time()                    # date index, one column per keyword, isPartial
pytrends.interest_by_region(resolution="COUNTRY", inc_low_vol=True)
pytrends.related_queries()
pytrends.trending_searches(pn="united_states")   # answers HTTP 404 in pytrends 4.9.2 today

One fetch per payload serves every later call from memory. Region views include low-volume regions and US metro areas (resolution="DMA"). related_topics() and top_charts() cannot be served and say so. See Migrating from pytrends.

Faster keyword analysis, opt-in. engine="auto" on the Explore functions asks Google directly first and starts Chrome only if Google refuses; measured at 1-7 s per full question against 16-33 s for a browser session. engine="http" never starts Chrome. The default stays "browser"; trendspyg.compat uses "auto". Existing calls behave as before.

Also in 1.8.0

Resolve ambiguous words before studying them: get_keyword_suggestions("apple") returns topic IDs, titles and types, including separate fruit and company candidates, without Chrome. Use trendspyg suggest -k apple from the CLI or suggest_keywords from MCP, then pass the chosen mid to Explore. See the changelog and upgrade notes.

Quick Start

For finished reporting, archive and keyword-study recipes, see Interpreting data and workflows.

RSS Feed (Fast, no browser)

from trendspyg import download_google_trends_rss

# Get one JSON-safe snapshot with its original observation time
env = download_google_trends_rss(geo='US', normalize=True)
print(env['fetched_at'], env['count'])

for trend in env['trends'][:3]:
    print(f"{trend['keyword']} - at least {trend['volume_min']:,}")
    if trend['news']:
        print(f"  {trend['news'][0]['headline']}")

CSV Export (Comprehensive - 10s)

from trendspyg import download_google_trends_csv

# Get filtered trends (requires Chrome and pip install trendspyg[analysis])
df = download_google_trends_csv(
    geo='US',
    hours=168,            # Past 7 days
    category='sports',
    output_format='dataframe'
)

Explore — interest over time (the pytrends use case)

from trendspyg import download_google_trends_interest_over_time

# Google's 0-100 relative-interest time series for a keyword (requires Chrome)
series = download_google_trends_interest_over_time("bitcoin", geo="US", timeframe="today 12-m")
for point in series[-3:]:
    print(point["date"], point["value"])   # {'date': '2026-05-31T00:00:00+00:00', 'value': 57, 'is_partial': True}
from trendspyg import download_google_trends_explore

# Full picture in one call: interest over time + related queries + interest by region
env = download_google_trends_explore("bitcoin", geo="US")
print(env["interest_over_time"][-1])
print(env["related_queries"]["rising"][0])     # {'query': '...', 'formatted_value': 'Breakout', ...}
print(env["interest_by_region"][0])            # {'geo_code': 'US-..', 'geo_name': '..', 'value': 100}

The Explore path drives a real browser against Google's Explore page and is rate-limit sensitive (~10–90s per call, with retries). Measured budget: roughly 8–10 fresh browser sessions in a short burst (~15 min) is enough for Google to serve its hard 429 block page to that IP; trendspyg raises RateLimitError at once when it does (1.5.1+), and recovery took anywhere from ~35 minutes to much longer in our measurements — a rate-limit error means stop for a long while, not retry. Since 1.5.2 every session first visits the Trends home page to pick up Google's session cookie (without it, an IP Google has seen before is refused outright). Space sessions out, reuse results with cache="disk" (no browser run), and use the RSS path for fast, frequent real-time checks — never poll Explore. Fewer refusals (1.6.0): pass cookies="disk" (CLI --cookies disk) and each session reuses Google's cookies from a small local file, so your machine looks like one returning visitor — measured live: while brand-new sessions were refused with the 429 page, sessions carrying the saved jar were served. Opt-in (it keeps a Google cookie on disk); clear_explore_cookies() deletes it.

Compare keywords — one shared 0-100 scale (new in 1.1.0)

from trendspyg import download_google_trends_comparison

# 2-5 keywords, directly comparable (single-keyword series are each scaled
# independently by Google — only a comparison returns comparable numbers)
env = download_google_trends_comparison(["bitcoin", "ethereum", "solana"], geo="US")
print(env["averages"])                          # {'bitcoin': 39, 'ethereum': 7, 'solana': 5}
print(env["interest_over_time"][-1]["values"])  # {'bitcoin': 41, 'ethereum': 6, 'solana': 4}
print(env["interest_by_region"][0])             # {'geo_code': 'US-WY', ..., 'top_keyword': 'bitcoin'}

# pytrends-style table: one column per keyword
df = download_google_trends_comparison(["bitcoin", "ethereum"], output_format="dataframe")

Watch — real-time monitoring (new in 0.7.0)

from trendspyg import watch_google_trends_rss

# Stream changes between RSS snapshots (safe for continuous polling — RSS only)
for change in watch_google_trends_rss(geo="US", interval=60, events=["new", "volume_up"]):
    print(change["event"], change["keyword"], change["volume_min"])
    # {'event': 'new', 'keyword': '...', 'rank': 3, 'prev_rank': None, 'volume_min': 50000, ...}

Monitoring is built on the fast RSS path, so it is safe to poll continuously (the CSV and Explore paths are not). The pure diff_trends(old, new) helper is also exported if you manage snapshots yourself.

Async (Parallel Fetching)

import asyncio
from trendspyg import download_google_trends_rss_batch_async

async def main():
    results = await download_google_trends_rss_batch_async(
        ['US', 'GB', 'CA', 'DE', 'JP'],
        max_concurrent=5
    )
    for country, trends in results.items():
        print(f"{country}: {len(trends)} trends")

asyncio.run(main())

CLI

trendspyg rss --geo US
trendspyg csv --geo US-CA --category sports --hours 168
trendspyg explore --keyword bitcoin --output csv
trendspyg explore -k bitcoin -k ethereum --quiet   # comparison (repeat -k 2-5 times)
trendspyg explore -k bitcoin --gprop youtube       # YouTube search interest (1.5.0)
trendspyg watch --geo US --interval 60 --events new,volume_up
trendspyg list --type countries

MCP server — use trendspyg from Claude & AI agents (new in 0.8.0)

Give any MCP client (Claude Desktop, Claude Code, Cursor, ...) live Google Trends tools — free, local, no API key. Requires Python 3.10+; runs on the MCP SDK v2 stable line or v1 (auto-detected).

pip install trendspyg[mcp]

# Claude Code — one command:
claude mcp add trendspyg -- trendspyg-mcp

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "trendspyg": { "command": "trendspyg-mcp" }
  }
}

Nine tools: suggest_keywords (topic IDs and meanings without Chrome), get_trending_now, compare_trending, get_trend_changes (what changed since the last check), list_supported_options, get_trending_history (what WAS trending, from the local archive — instant) — all fast and browser-free — plus get_interest_over_time, compare_interest_over_time (2-5 keywords, one shared scale) and get_trending_full (drive Chrome; slower, described honestly to the agent — though since 1.4.0 identical repeat interest/compare questions answer instantly from a local disk cache).

Data Sources

RSS CSV Explore
Answers "what's trending now?" "what's trending now?" "how is interest in X moving?"
Speed sub-second* ~10s ~10–90s (rate-limit sensitive)
Output 10–20 current trends 480+ current trends interest over time, related queries, regions; 2–5-keyword comparison; web / YouTube / News / Images / Shopping
News articles Yes No No
Time filtering No Yes (4h/24h/48h/7d) Yes (any timeframe)
Category filter No Yes (20 categories) Yes
Requires Chrome No Yes Yes

* Network-dominated: ~0.2s on low-latency links, ~1.4s measured on a high-RTT connection; cache hits are instant. Honest measured numbers per path live in benchmarks/.

Monitoring: trendspyg watch / watch_google_trends_rss(...) polls the RSS path and streams changes (new / dropped / volume / rank) as they happen — built on RSS, so it is safe for continuous polling.

Own the history Google doesn't offer (new in 1.3.0; Explore support in 1.4.0)

Trending data is ephemeral — once the feed updates, "what was trending last Tuesday" is gone, and nobody sells it. Opt in to archiving and every fetch records a snapshot to a single local SQLite file (stdlib only — no server, no keys, no new dependencies):

trendspyg rss --geo US --archive           # record a snapshot while fetching
trendspyg history -k bitcoin --timeline    # when did it first trend? how did it move?
trendspyg history --stats                  # size, date range, geos
from trendspyg import download_google_trends_rss, get_keyword_history, read_archive

download_google_trends_rss(geo="US", archive=True)   # archive while you fetch
download_google_trends_rss(geo="US", cache="disk")   # cache that survives restarts
read_archive(geo="US", start="2026-08-01")           # what WAS trending
get_keyword_history("bitcoin")                       # first seen, rank over time

The Explore path joins in 1.4.0 — and its disk cache is the bigger win there, because every fresh Explore fetch is a 10-40s rate-limited browser run:

from trendspyg import download_google_trends_interest_over_time

# First call drives Chrome; identical calls within 24h answer instantly from disk.
download_google_trends_interest_over_time("bitcoin", cache="disk", archive=True)
trendspyg explore -k bitcoin --cache disk --archive
trendspyg explore -k bitcoin --cookies disk      # be a returning visitor (1.6.0)
trendspyg history --source explore -k bitcoin    # your keyword-research history

Cached Explore results stay fresh for 1 hour on "now *" timeframes and 24 hours otherwise (override with cache_ttl= / --cache-ttl), and a cache hit keeps the original fetch time, so the data's age is never hidden. Archive writes never break a download (they warn instead), and prune_archive / trendspyg history --prune-before reclaim space when you want it back (~15 KB per RSS snapshot, ~4-26 KB per Explore snapshot; ~130-260 MB/year at hourly RSS cadence).

Features

  • Real-time trending topics (RSS + CSV paths) and keyword analysis over time (Explore path)
  • Real-time monitoring — watch streams trend changes as NDJSON (RSS-only, poll-safe)
  • Interest over time, related queries, and interest by region for any keyword — the core pytrends use case
  • Multi-keyword comparison (2-5 terms) on one shared 0-100 scale — the pytrends kw_list use case
  • Google property selection — analyze YouTube, News, Images, or Shopping search interest, not just web (gprop=, 1.5.0)
  • 125 countries + 51 US states, 20 categories, 4 trending time periods (4h, 24h, 48h, 7 days)
  • Output formats: dict, DataFrame, JSON, CSV (+ Parquet on the CSV path)
  • Async support for parallel fetching
  • Built-in caching (5-min TTL) + opt-in disk cache that survives restarts (1.3.0) — Explore too, with hours-scale freshness, so repeat analyses skip the 10-40s browser run (1.4.0); a cached full Explore answer also serves the plain interest-over-time question (1.6.0)
  • Returning-visitor sessions — opt-in cookies="disk" reuses Google's session cookies across Explore calls, so a busy IP keeps getting served (1.6.0)
  • Historical archiving — opt-in local SQLite archive of every fetch (all three data paths) + trendspyg history (1.3.0/1.4.0)
  • Agent-ready: typed shapes, normalize=True, and a JSON-native Explore schema
  • MCP server — trendspyg-mcp exposes 9 tools to Claude and any MCP client (no API key; MCP SDK v1 & v2 both supported)
  • CLI for terminal access
  • Stable API — semantic versioning with a written contract: STABILITY.md
  • Documentation site — flack0x.github.io/trendspyg (1.5.0)

Normalized output (for agents & pipelines)

Pass normalize=True to get one unified, JSON-native schema that is identical for both the RSS and CSV paths — no need to learn two different shapes.

from trendspyg import download_google_trends_rss

env = download_google_trends_rss(geo='US', normalize=True)
# {'schema_version': '1.0', 'source': 'rss', 'geo': 'US',
#  'fetched_at': '2026-05-22T...Z', 'count': 10, 'trends': [...]}

for t in env['trends']:
    print(t['rank'], t['keyword'], t['volume_min'])  # volume_min is a real int

Every trend has a fixed, JSON-safe shape: keyword, rank, volume_text, volume_min (int), started_at / ended_at (ISO 8601 or None), is_active, related_queries (list), news (list), image, explore_url. normalize=True works on every entry point — RSS, CSV, async, and the batch functions (each geo then maps to its own envelope) — and on the CLI (trendspyg rss --geo US --normalize). It is opt-in — default output is unchanged.

Caching

from trendspyg import clear_rss_cache, get_rss_cache_stats

# Results are cached for 5 minutes by default
trends = download_google_trends_rss(geo='US')  # Network call
trends = download_google_trends_rss(geo='US')  # From cache

# Bypass cache
trends = download_google_trends_rss(geo='US', cache=False)

# Check cache stats
print(get_rss_cache_stats())

# Clear cache
clear_rss_cache()

Documentation

Stability

trendspyg is 1.0 — the public API follows semantic versioning under a written contract: what's covered (every exported name, the exception types, CLI commands and flags, MCP tools, the versioned data schemas), what a breaking change is, and how deprecations work. The honest boundary: Google's side of the wire is not ours to guarantee — upstream changes are fixed in patch releases. Details in STABILITY.md.

Requirements

  • Python 3.8+
  • Chrome browser (for the CSV and Explore paths; the RSS path needs no browser)

License

MIT License - see LICENSE for details.

Metadata

Release files for trendspyg 1.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for trendspyg 1.9.0
File Size Uploaded
trendspyg-1.9.0.tar.gz 189.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for trendspyg 1.9.0
File Interpreter ABI Platform
trendspyg-1.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 298.1 kB

Release files / trendspyg-1.9.0.tar.gz

Download URL trendspyg-1.9.0.tar.gz
Size 189.0 kB
Tags Source
SHA-256 checksum
How to use checksums
eff1c9a368b656e09c22494da89c6f793e8716191d2912a73c0088adb766f5d0
BLAKE2b-256 checksum
How to use checksums
fe3525f67bade8e79cfc64b1c0425b3a2577e3d569c208dc6233d57e9666b5b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / trendspyg-1.9.0-py3-none-any.whl

Download URL trendspyg-1.9.0-py3-none-any.whl
Size 109.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
959871d044f6e34b7bd235fe064129bd19307145c03b77ff90db769a8af101dc
BLAKE2b-256 checksum
How to use checksums
205ab359882e44c8daa7829bd7723a1499c671cc5d85928640d245da1c223d0c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.9.0 This release

2 release files

1.8.0

2 release files

1.7.0

2 release files

1.6.0

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page