trends-research-cli
A CLI for the Google Trends Research API — the allow-listed research
endpoint, not the public Trends site — aimed at journalism and OSINT work.
Installs a gtrends command.
This wraps the allow-listed research API, not the public Trends site. It returns absolute probabilities rather than the familiar 0–100 index, it has no hourly data, and access must be granted per project.
You need an API key, and you cannot create one yourself. This API is allow-listed per Google Cloud project and granted after review. Request access at support.google.com/trends/contact/trends_api. Without a key,
gtrends guideandgtrends categoriesstill work offline; nothing else will.
The API's real behaviour is largely undocumented, and most of it is a trap.
What this tool knows about it is recorded in the module docstrings and asserted
against the live API by tests/live/ — so if the API changes underneath you,
those tests fail rather than the numbers quietly going wrong.
Install
uv tool install trends-research-cli # or: pipx install trends-research-cli
export TRENDS_API_KEY=... # or put it in a .env file
gtrends doctor # checks the key and the allow-listing
gtrends guide # the full manual, offline
doctor is worth running first: the API reports "your key is bad" and "your
project is not allow-listed" identically, and doctor tells them apart.
The unit
value = P(term | date AND geography) x 10,000,000
Already a share. Never rescaled, never normalised against a "control" — doing so divides a probability by a probability and has produced published errors. Every output states the unit, geo, interval, endpoint and retrieval time.
Time zone and freshness
Days are binned in UTC. Google documents this for daily Trends data, and
this API exposes no timezone parameter to override it. Corroborated directly:
the API serves the current UTC date while it is still yesterday in US Pacific
time. --to therefore defaults to today in UTC, not local time — on a Pacific
machine, local time would silently drop the newest day.
The data horizon sits about two days back, and the API is inconsistent
about it. A short request ending inside that window is rejected outright with a
400, but a long request spanning the same days returns them anyway. Because
the metric is a share rather than a count, those trailing days come back
looking like perfectly ordinary values — nothing in the number reveals it
covers three hours rather than twenty-four. Any range running up to the present
therefore warns, and a late spike is not evidence until it settles.
Dates
One format everywhere: --from and --to take YYYY, YYYY-MM or
YYYY-MM-DD. Partial values expand outward.
--from 2026-07 # all of July
--from 2021 --to 2026 # six whole years
--from 2026-07-21 --to 2026-07-26 # exactly those six days
--from 2026-07-21 # the 21st to today
Coarse intervals return fixed calendar periods, and the requested dates only
select which ones overlap. So there is one rule: if a range contains no whole
period, it errors; otherwise it clamps to the whole periods inside and reports
what was dropped. Asking for --interval month over six days will never
silently hand back the whole month.
Documentation
For AI agents
SKILL.md at the repository root is a portable Agent
Skill — the open format read by Claude Code, Codex,
Cursor, Gemini CLI, Copilot and others. It ships with the package, but
installing the CLI does not put it where agents look, so:
uv tool install trends-research-cli
gtrends skill install # ~/.agents/skills, the cross-tool location
gtrends skill install --all # plus every agent tool found on this machine
gtrends skill install --to .agents/skills # this repository only
gtrends skill uninstall --all # remove it again
install reports any tool-specific directories it finds rather than writing
into several home directories uninvited, and uninstall only ever removes a
directory that actually holds this skill.
It copies rather than symlinking. A link would track package upgrades, but
it points into whichever environment the CLI was installed into — under uvx
that is a prunable cache, so the skill would work today and vanish after
uv cache prune. Re-run gtrends skill install --force after an upgrade;
staleness is cheap here because the skill routes to gtrends guide, which
ships in the binary and cannot go stale. --link is available for a durable
install into a private skills directory; do not commit one to a repository,
where an absolute symlink into your own home is broken for everyone else.
The skill routes to gtrends guide rather than restating it. AGENTS.md
covers developing this repo, which is a different job.
gtrends guide prints the complete operating manual — units, date rules, the
zero caveat, exit codes — with no network or credentials needed. Every command
and subcommand also carries -h/--help with a worked example.
gtrends guide # everything, in one place
gtrends series -h # flags and an example for one command
Commands
gtrends guide # the full manual, offline
gtrends doctor # is my setup working?
gtrends categories # look up a category for --category
gtrends entity find|verify|coverage
gtrends series <id...> # the numbers
gtrends queries <id> # what strings people typed alongside
gtrends topics <id> # what entities co-occur (returns IDs)
gtrends check censoring|variance|vs-public
series
gtrends series /m/0cycc --geo US --from 2025-07-01 --to 2025-07-07
gtrends series /m/0cycc /m/07__7 --geo US --from 2025-07 # terms as columns
gtrends series /m/0cycc --geo US --from 2025-07 --by region # regions as rows
gtrends series /m/0cycc --geo US --from 07-21 --to 07-23 \
--by year --years 2023-2025 # years as columns
gtrends series /m/0cycc --geo US --from 2025-07-21 --to 2025-07-26 --summary mean
--interval takes day, week, month or year. --by region accepts any
range down to a single day; queries and topics are month-only. Long ranges
chunk past the ~380-point ceiling automatically and concatenate with no
bridging factor, because the values are absolute.
--geo takes a country (US), a sub-national region (US-NY) or a bare
Nielsen DMA number (501 for the New York media market). Up to 30 terms per
request; requests are throttled to the documented 2 per second.
Category and property
gtrends categories --find health
gtrends queries /m/0cycc --geo US --from 2025-07 --property news
gtrends series /m/0cycc --geo US --from 2025-01 --to 2025-03 --by region \
--category "/Health/Health Conditions"
--property picks the Google surface: web (default), news, images,
youtube, shopping. --category takes a path or a bare name — names are
globally unique, so Health Conditions and /Health/Health Conditions both
work — and --category-id takes a numeric id. Both are validated against the taxonomy
bundled with the release — the valid ids are a finite known set, and the API
answers an unknown one with an opaque 500, so there is no reason to spend a
request finding out. Upgrading the package updates the taxonomy, which is often
enough: it gained one category in the seven years to 2026.
Both apply to queries, topics and series --by region only. A time
series refuses them: timelinesForHealth accepts them and returns unfiltered
data, so offering the flag would answer a filtered question with the wrong
numbers.
A parent category contains its descendants — /Health sweeps in
Health Conditions and its 31 sub-categories — so the output states what was
swept in. The taxonomy is bundled (a wrong category costs no request) and
predates about 2012: no AI, crypto, streaming, EV or vaping category exists.
entity
Getting IDs right matters more than any analysis decision. find consults both
the Knowledge Graph and the Trends topic index, because neither is complete —
/m/0cycc is what Trends returns for influenza and serves data for, yet
kgsearch has never heard of it.
gtrends entity find "influenza" --geo US
gtrends entity verify /m/07__7 --is "Vaccine"
gtrends entity coverage /m/0cycc --text flu --text grippe \
--geo US --from 2025-07
coverage answers "does this entity capture the words people actually type?" by
fetching the entity and each variant over the same window and comparing the
entity against the summed variants.
Composition
--plain gives bare values, one per line, so commands pipe into each other:
gtrends series $(gtrends topics /m/0cycc --geo US --from 2025-07 --top 5 --plain) \
--geo US --from 2025-07
Output
Human table by default. series takes the full set — --json, --csv,
--parquet PATH, --plain, --strict, --receipt. Other commands take
--json, and queries/topics/entity find also take --plain; check
<command> -h. Machine formats are always tidy long format
— one row per date_start × term × group — and never pivot; the table pivots
only when exactly one axis varies.
Warnings travel with the data in every format — including --plain, where
they go to stderr so stdout stays pipeable — so an agent detects a clamped
window or a censored series from the output rather than from prose. Notes
are separate: caveats that hold whatever the data says, which --strict
deliberately ignores.
gtrends series ... --raw-dir raw/ # archive every response
gtrends series ... --receipt run.json # how each number was obtained
gtrends series ... --strict # exit 4 if anything warned
Every output carries Data source: Google Trends (https://www.google.com/trends)
in its metadata — reusing Trends data requires crediting Google, so cite it
with any figure you publish.
One caveat on --raw-dir: the Google APIs Terms of
Service §5.e restrict creating permanent
copies of API content "unless expressly permitted by the content owner", and an
archive is exactly that. Check your access grant covers it. --receipt records
only the calls made, not response content, so it is unaffected.
Zeros
A zero means no activity or too few distinct queries to release. The API
does not distinguish them. Every series reports pct_zero and the longest zero
run, anything over 50% zero warns, and display formatting will never round a
small non-zero value down to 0.0.
Exit codes
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | usage error: bad flags, unparseable dates, clamp violation |
| 2 | API or network error after retries |
| 3 | assertion failure, e.g. entity verify mismatch |
| 4 | warnings raised under --strict |
What it does not do
No p-values, no significance tests, no verdicts — the tool returns well-labelled numbers with their coverage caveats and you run your own test. No hourly data (the API has none). No forecasting, modelling or plotting.
Development
git clone https://github.com/owahltinez/trends-research-cli && cd trends-research-cli
uv sync
uv run pytest # offline; fast, no network
uv run pytest -m live # also hits the real API; needs TRENDS_API_KEY
The live suite is the project's documentation of the API itself: it asserts every undocumented behaviour this tool relies on — the parameter families, the calendar-period bleeding, the point ceiling, the UTC binning and data horizon — against the real service. AGENTS.md is the contributor guide: the checks, the design invariants, and the rule that no belief about the API is encoded without a live test behind it.
Pull requests run the offline suite only — the live suite spends real quota against a single allow-listed key, so it runs on a schedule instead.
Licence
MIT — see LICENSE. src/trends_research_cli/data/categories.json contains
Google Trends category names and IDs, retrieved from the public Trends category
picker and bundled so --category can be validated offline; its provenance is
recorded in the file.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file trends_research_cli-0.1.0.tar.gz.
File metadata
- Download URL: trends_research_cli-0.1.0.tar.gz
- Upload date:
- Size: 128.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8bdf76b95fc2ebe68e3dbef3a599908f50a5ba5c16bcf5f152d457123d8bb42
|
|
| MD5 |
e9576e1a65c3d63ee42cfd547c0abe90
|
|
| BLAKE2b-256 |
539de5a8a7155ddd83a712cc3f1c23c58a94f8024917c8bb72aac657835294c4
|
Provenance
The following attestation bundles were made for trends_research_cli-0.1.0.tar.gz:
Publisher:
release.yml on owahltinez/trends-research-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trends_research_cli-0.1.0.tar.gz -
Subject digest:
c8bdf76b95fc2ebe68e3dbef3a599908f50a5ba5c16bcf5f152d457123d8bb42 - Sigstore transparency entry: 2415493658
- Sigstore integration time:
-
Permalink:
owahltinez/trends-research-cli@b7cf0eaa4e8646da47d806ae6621d2ad8c141efd -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/owahltinez
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b7cf0eaa4e8646da47d806ae6621d2ad8c141efd -
Trigger Event:
push
-
Statement type:
File details
Details for the file trends_research_cli-0.1.0-py3-none-any.whl.
File metadata
- Download URL: trends_research_cli-0.1.0-py3-none-any.whl
- Upload date:
- Size: 98.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea1f53f1c8d05d3844a7cf5e81a74b4bc46fbcfa13c608b82c313d02fff850e6
|
|
| MD5 |
26e16a04fc52e86f705f70700d7078b2
|
|
| BLAKE2b-256 |
dba972ef3e14a02b799a79cf27cc62854d4a68818446418885ed94659e49dd09
|
Provenance
The following attestation bundles were made for trends_research_cli-0.1.0-py3-none-any.whl:
Publisher:
release.yml on owahltinez/trends-research-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trends_research_cli-0.1.0-py3-none-any.whl -
Subject digest:
ea1f53f1c8d05d3844a7cf5e81a74b4bc46fbcfa13c608b82c313d02fff850e6 - Sigstore transparency entry: 2415493774
- Sigstore integration time:
-
Permalink:
owahltinez/trends-research-cli@b7cf0eaa4e8646da47d806ae6621d2ad8c141efd -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/owahltinez
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b7cf0eaa4e8646da47d806ae6621d2ad8c141efd -
Trigger Event:
push
-
Statement type: