Usage

Query Google Trends: interest over time, interest by region, related queries, and exports — with runnable examples.

Usage

import { Client, Region, Timeframe, Resolution, ExportFormat } from "trendflow";

const tf = new Client({ language: "en", timeout: 10_000 });

Region, Timeframe, Resolution, and ExportFormat are as const objects, so Region.US is the string "US" and any valid literal is accepted where the type is.

Interest over time

const data = await tf.interestOverTime(
  ["Python", "JavaScript", "Rust"],
  Timeframe.PAST_YEAR,
  Region.US,
);

data.keywords;    // ["Python", "JavaScript", "Rust"]
data.granularity; // "weekly"
data.points;      // TrendPoint[] — { date: Date, scores: Record<string, number> }

Interest by region

const regional = await tf.interestByRegion("Python", Resolution.COUNTRY, Region.US);
for (const row of regional.rows) console.log(row.label, row.value);

Runs on the batchexecute RPC that trends.google.com itself uses, so it needs no cookie and is far less rate-limited than the other queries.

import { TrendingWindow } from "trendflow";

const trending = await tf.trendingNow(Region.US);
trending.results[0];
// { title: "fifa world cup 2026", growth: 3650, volume: 6, traffic: "+3,650%", articles: [] }

await tf.trendingNow(Region.US, { window: TrendingWindow.TOP }); // highest-volume instead
await tf.trendingNow("PT"); // any country code, not a fixed list
await tf.trendingNow();     // worldwide (the default)

growth is the percentage rise over the window and volume a relative search-volume index. articles is empty on this backend — the RPC carries no article links. Pass { backend: "rss" } to get the news articles behind each trend instead.

const related = await tf.relatedQueries("machine learning");
for (const q of related.top) console.log(q.term, q.value);
for (const q of related.rising) console.log(q.term, q.breakout);

Google exposes trending searches two ways. They are not interchangeable, so backend lets you pick:

"rpc" (batchexecute)"rss" (feed)
items5010
payload~2 KB JSON~21 KB XML
growth % and volume❌ — buckets like "2000+"
news articles
window selectionignored by Google
worldwide❌ country only
const rss = await tf.trendingNow(Region.US, { backend: "rss" });
rss.source; // "rss"
rss.results[0].articles;
// [{ title: "...", url: "https://...", source: "Buffalo News", picture: "https://..." }]

"auto" (the default) tries the RPC and falls back to the feed. The RPC comes first deliberately: it returns five times the items with real growth figures, so defaulting to RSS would quietly degrade results. Reach for "rss" when you want the articles — that is the one thing the RPC cannot give you — or as a second opinion if the RPC id ever goes stale.

Note that the feed is not a lighter path despite being a feed, and Google ignores hours, sort and count on it: it always returns the same 10 entries.

Topics and search suggestions

Google distinguishes a search term (the literal string) from a topic (the entity, in every spelling and language). suggestions() finds the topic; every query method already accepts one — pass the mid where you would pass a keyword.

const topics = await tf.suggestions("artificial intelligence");
// [{ mid: "/m/0mkz", title: "Artificial intelligence", type: "Professional field" }]

const data = await tf.interestOverTime(
  [topics[0].mid, "artificial intelligence"],
  Timeframe.PAST_YEAR,
  Region.US,
);
// { "/m/0mkz": 62, "artificial intelligence": 1 }

That gap is the point: the topic scores 62 where the literal phrase scores 1, because it aggregates every phrasing and translation people actually search.

suggestions() needs no cookie and no proxy — it answers on IPs the widgetdata endpoints reject with 429, same as trendingNow(). type disambiguates same-name entities ("Nike" returns both the company and the goddess) and is null when Google omits it.

Exports

InterestOverTimeResult carries the conversion helpers. toArray() is the JS answer to pandas' to_dataframe().

data.toArray(); // [{ date: Date, Python: 80, ... }]
data.toJSON();  // same rows with ISO 8601 dates; also drives JSON.stringify
data.toCSV();   // CSV text

await data.export(ExportFormat.CSV, "trends.csv");   // Node only
await data.export(ExportFormat.JSON, "trends.json"); // Node only

In the browser use toCSV() / toJSON()export() writes to disk and is Node-only. Note that Google Trends sends no CORS headers, so calls must originate server-side.

Errors

import { ResponseError, TooManyRequestsError, UnknownRpcError } from "trendflow";
  • ResponseError — any failed request; carries .status and the raw .response.
  • TooManyRequestsError — HTTP 429, a subclass. See Proxies.
  • UnknownRpcError — Google renamed a batchexecute RPC id. Override it with the rpcIds client option rather than waiting for a release.