Google Trends Scraper API: Bulk, Compare, YouTube
Pricing
$4.00 / 1,000 per trends data rows
Google Trends Scraper API: Bulk, Compare, YouTube
Scrape Google Trends keyword data as JSON or CSV: interest over time, interest by region down to US metro and city, and related queries. Compare up to 5 keywords on one shared 0-100 scale, or bulk-scrape an unlimited list. Web, Images, News, Shopping, YouTube. No start fee; empty runs are free.
This Google Trends scraper pulls Google Trends keyword data as clean JSON or CSV — interest over time, interest by region down to US metro and city level, and related queries — for a single keyword or for a list of thousands. It talks to the same JSON endpoints the Google Trends website itself calls, so there is no headless browser and no DOM parsing. That is the whole reason the older generation of Google Trends scrapers breaks every time Google reshuffles its page markup, and this one does not.
You get one self-describing row per keyword per data surface, a genuinely co-normalized comparison when you ask for one, and no charge at all for a run that comes back empty.
What data can this Google Trends scraper extract?
| Data surface | What you get |
|---|---|
| Interest over time | The trend line: one 0–100 value per time bucket per keyword, plus the period average. |
| Interest by region | Where the searches come from — country, subregion, US metro area (Nielsen DMA), or city. |
| Related queries | What people also searched, split into top and rising, with Google's Breakout flag. |
| Search types | Web, Images, News, Google Shopping and YouTube search — five separate trend curves. |
Google Trends interest over time
The familiar Trends line chart, as data. Every bucket carries its ISO timestamp, its epoch seconds,
Google's own human-readable label, the value per keyword, a hasData flag per keyword, and an
isPartial flag on the trailing bucket. The bucket size follows the range you ask for: hourly for
the now presets, daily up to about nine months, weekly for a year, monthly for five years and up.
Google omits the period averages for single-keyword lookups. This Actor computes them the same way
Google does — the mean of every bucket including the trailing partial one, rounded — and marks them
averagesComputed: true so you always know whether a number came from Google or from us.
Google Trends interest by region: country, metro (DMA) and city
Set the granularity you want. A US run at metro granularity returns all 210 Nielsen DMAs with
their codes (759 Cheyenne WY-Scottsbluff NE, 744 Honolulu HI), which is the level most demand
and media-planning work actually needs. City granularity returns fewer rows by design — Google only
reports places with enough search volume to be statistically meaningful.
Google Trends related queries: top and rising
Top queries are the most common over your period; rising queries are the fastest growing. When
Google reports "Breakout" it means growth above 5000% and it stops publishing a real percentage,
so those entries are flagged isBreakout: true — sort on that flag first, then on value.
YouTube, News, Shopping and Images search trends
The same keyword often behaves nothing like its web curve on YouTube. Five search types are supported and each returns a distinct series:
| Search type | What it measures | Status |
|---|---|---|
| Web search | The familiar Google Trends numbers | Verified |
| YouTube search | Searches inside YouTube | Verified — distinct curve |
| News search | Searches inside Google News | Verified — distinct curve |
| Image search | Searches inside Google Images | Supported |
| Google Shopping | Searches inside Google Shopping | Supported |
Compare keywords, or bulk-scrape a keyword list
These are the two modes, and picking the right one is the single most important thing to understand about Google Trends data.
- Bulk mode (default). Put a whole keyword list in. Each keyword gets its own lookup and its own 0–100 scale, where 100 is that keyword's own peak. There is no cap on how many keywords you send. This is what you want for keyword research across a list.
- Comparison mode. Switch it on and up to 5 keywords go to Google in one request, so the numbers come back on a single shared 0–100 scale — the way the Trends website shows them. Scrapers that fetch each keyword separately and staple the results together produce numbers that simply are not comparable.
Why the two modes give different numbers
Real figures from two runs of this Actor on 9 August 2026, both coffee and matcha, US, past 12
months:
| Mode | coffee (period average) | matcha (period average) |
|---|---|---|
Bulk (compare: false) | 75 | 72 |
Comparison (compare: true, with tea) | 75 | 6 |
Nothing is broken. Google's index is always relative to 100. In bulk mode, matcha averaging 72
means "matcha in an average week runs at 72% of matcha's own best week" — it says nothing about how
matcha compares to coffee. In comparison mode, 100 is the busiest week of the busiest keyword in the
set, so matcha gets crushed to 6 against coffee. That is the correct answer to "which of these is
bigger", and it is exactly what the Trends website shows.
Rows make the distinction explicit: comparisonGroup: "coffee | tea | matcha" in comparison mode,
and comparisonGroup: null in bulk mode, which tells you those rows are not comparable with
each other.
Google Trends for keyword research, SEO and market research
People use this Google Trends scraper for:
- Keyword research — size demand across a keyword list, then sort by period average.
- Rising and breakout queries — find what is growing before it shows up in volume tools.
- Seasonality — pull five years of monthly data and read the annual shape before you buy stock or schedule content.
- Brand and competitor comparison — put up to five brands on one shared scale.
- Market research — track a category month by month, or use search interest as a demand proxy.
- Regional targeting — find the metros where a term over-indexes.
- Disambiguation — restrict to a Trends category to separate "jaguar" the car (47) from "jaguar" the animal (66).
Search interest is a relative index, not a search volume. It pairs well with a volume/CPC tool rather than replacing one.
How to scrape Google Trends step by step
- Click Try for free and sign in to Apify.
- Type your search terms into Keywords, one per line.
- Set Location (empty means worldwide) and Time range (
today 12-mis the default). - Leave Compare keywords off to scrape a list; switch it on to put 2–5 terms on one scale.
- Tick only the data surfaces you need. Interest over time is on by default; every extra surface is an extra request to Google.
- Click Start. A two-keyword trend-line run takes about three seconds.
- Open the Output tab and export, or pull the dataset from the API.
Start with two or three keywords and interest over time only, so you can see the output shape before committing a long list.
Input
Only keywords is required. A realistic run — five product keywords across the US for the past
year, with a regional breakdown by metro area:
{"keywords": ["air fryer", "electric bike", "padel", "protein powder", "matcha"],"geo": "US","time": "today 12-m","includeTimeseries": true,"includeGeo": true,"geoResolution": "dma"}
| Setting | What it does |
|---|---|
| Keywords | One search term per line. No limit in bulk mode; 2–5 in comparison mode. |
| Compare keywords | Off by default. On puts every keyword on one shared scale. |
| Interest over time | The trend line. On by default; this is the surface most people want. |
| Interest by region | Where the searches come from. Off by default. One extra request per lookup. |
| Related queries | What people also searched, top and rising. Off by default. One extra request per keyword. |
| Related topics | Off by default and currently returns nothing from Google — see Limitations. Never charged for. |
| Location | Empty for worldwide, or US, GB, DE, US-NY, GB-ENG. |
| Time range | A preset, a yyyy-mm-dd yyyy-mm-dd range, or an hourly yyyy-mm-ddThh range. Validated before any request. |
| Search type | Web, Images, News, Google Shopping or YouTube search. |
| Region granularity | Automatic, country, subregion, metro area (DMA, US only) or city. |
| Category | Restrict to one Trends category id — the clean way to separate "jaguar" the car (47) from "jaguar" the animal (66). |
| Proxy configuration | Datacenter proxy by default, which is included in every Apify plan and is what we measured as fastest. Residential is one dropdown away. |
| Time zone offset | Minutes from UTC. 0 keeps results reproducible between runs — usually what you want for a dataset. |
| Max retries | Retries wait about 2s, 6s and 15s, and switch to a fresh IP and cookie jar from the second retry onwards. |
Bad time ranges are rejected before a single request goes out, so a typo costs you nothing.
Output: export to JSON, CSV, Excel or the API
One row per keyword per surface, each row self-describing — it repeats the query it answers, so rows stay readable on their own after export. Download as JSON, CSV, Excel, XML or HTML, or pull the dataset straight from the Apify API. These are real rows from real runs on 9 August 2026, trimmed for readability.
Interest over time — comparison of coffee, tea, matcha in the US. values is index-aligned
to keywords, so values[2] is always matcha:
{"keywords": ["coffee", "tea", "matcha"],"comparisonGroup": "coffee | tea | matcha","geo": "US","time": "today 12-m","searchType": "web","category": 0,"fetchedAt": "2026-08-09T14:24:53.464Z","surface": "timeseries","resolution": "WEEK","averages": [75, 36, 6],"averagesComputed": false,"points": [{"time": "2025-08-03T00:00:00.000Z","epochSeconds": 1754179200,"formattedTime": "Aug 3 – 9, 2025","values": [68, 35, 7],"hasData": [true, true, true],"isPartial": false}]}
Interest by region at US metro (DMA) granularity — 210 metros in one row, each with its Nielsen code:
{"surface": "geo","resolution": "DMA","keywords": ["coffee", "tea", "matcha"],"comparisonGroup": "coffee | tea | matcha","regions": [{"geoCode": "759","geoName": "Cheyenne WY-Scottsbluff NE","values": [69, 28, 3],"formattedValues": ["69%", "28%", "3%"],"hasData": [true, true, true],"maxValueIndex": 0},{"geoCode": "744","geoName": "Honolulu HI","values": [65, 27, 8],"formattedValues": ["65%", "27%", "8%"],"hasData": [true, true, true],"maxValueIndex": 0}]}
Related queries for matcha, top and rising:
{"surface": "relatedQueries","keyword": "matcha","geo": "US","time": "today 12-m","top": [{ "rank": "TOP", "query": "matcha latte", "value": 100, "formattedValue": "100", "isBreakout": false },{ "rank": "TOP", "query": "matcha tea", "value": 94, "formattedValue": "94", "isBreakout": false },{ "rank": "TOP", "query": "matcha near me", "value": 73, "formattedValue": "73", "isBreakout": false }],"rising": [{ "rank": "RISING", "query": "grind rail", "value": 26950, "formattedValue": "Breakout", "isBreakout": true }]}
Use it as a Google Trends API
There is no official public Google Trends API, and the maintained open-source libraries are gone —
pytrends was archived in April 2025 and trendspy has been dormant since December 2024. This
Google Trends scraper is the replacement.
Start a run with your input JSON, poll it, then read the dataset in JSON or CSV. Anything that can call an HTTP endpoint can drive it:
- Python —
apify-clientor plainrequestsagainst the Apify API. - Node.js / TypeScript — the official
apify-clientpackage. - cURL / any HTTP client — start a run, fetch
/datasets/{id}/items?format=csv. - Schedules — have Apify run your keyword list nightly or weekly without writing a cron.
- Webhooks — fire your own endpoint the moment a run finishes.
Integrations: n8n, Make, Zapier and MCP
The Actor plugs into the Apify integrations you already have: n8n, Make, Zapier, Slack, Google Sheets, Google Drive, GitHub, Airtable and Zendesk, plus any warehouse you can point a webhook at. For AI agents, it is reachable over the Apify MCP server, so an agent can ask for Google Trends data as a tool call.
Runs execute under limited permissions — the Actor needs no access to your account and collects no personal data.
How much does it cost to scrape Google Trends?
$0.004 per row — $4.00 per 1,000 rows. One flat rate, the same on every plan, with no start fee and no tiers.
Pay per row of data. You are charged one trends-row event for every dataset row that carries
data, and nothing else. A row is a complete answer for one keyword on one surface: an
interest-over-time row for a one-year window holds 54 weekly buckets and the period averages — not
one bucket. Watch out for per-data-point pricing elsewhere, which makes a headline number look far
lower than it is.
A run that returns nothing costs nothing. Google answers 200 OK with an empty payload more
often than you would think — obscure keywords, tiny regions, dead time windows. This Actor counts
parsed records, never HTTP status. An empty surface is written to your dataset as an explicit
noData row with a plain-English reason, and it is not charged. Failed requests are never
charged either. Set Max total charge on the run if you want a hard ceiling; the Actor stops
cleanly at the limit and keeps everything it has already collected.
Is it free? No, but the first test is nearly free: two keywords with interest over time only is 2 rows, so $0.008. If you are on the Apify free plan, a paid Actor draws on your monthly usage allowance like anything else.
What a run costs in requests
Every request to Google is a chance to be rate-limited, so it is worth knowing where they go. A "lookup" is the one call that fetches the tokens for a keyword or a comparison set; every surface for that keyword reuses it.
| Surface | Bulk mode (per keyword) | Comparison mode (per set of 2–5) |
|---|---|---|
| Lookup (always needed) | 1 | 1 for the whole set |
| Interest over time | +1 → 1 row | +1 → 1 row for the whole set |
| Interest by region | +1 → 1 row | +1 → 1 row for the whole set |
| Related queries | +1 → 1 row | +1 per keyword → 1 row each |
Comparison mode is the cheaper way to get a trend line for several keywords: one request and one row covers the whole set. Bulk mode is the way to cover a long list.
How this Google Trends scraper is built differently
Measured on the Apify platform, 9 August 2026:
| Run | Requests | Rows | Wall clock |
|---|---|---|---|
| 2 keywords, interest over time, worldwide | 4 | 2 | 3.0 s |
| 8 keywords, interest over time, US | 16 | 8 | 8.0 s |
| 3 keywords compared, + region (DMA) + related queries, US | 7 | 5 | 21.4 s |
- No browser, so there is no DOM to break. Trends scrapers built on a headless browser read Google's rendered page. When Google changes that markup — which it does — they return nothing, and they often keep charging while they do it. This Actor calls the JSON endpoints directly.
- A real co-normalized comparison. Up to 5 keywords in one request on one shared scale, not separate scrapes stitched together.
- Per-surface opt-in. Every surface you leave switched off is a request that cannot fail and a row you do not pay for. Fewer requests means faster, cheaper and markedly more reliable runs.
- Charging tied to parsed rows, not HTTP status. This is the difference between "the run finished" and "you got data".
- 100% of public runs have succeeded so far. That is an honest but small sample — this Actor is new. The architecture is the argument; the track record is still being built.
Reliability and fair use
- Public data only. Everything comes from the same public JSON endpoints that render the Google Trends website for any visitor. No logins, no accounts, no CAPTCHA solving, nothing behind a paywall, no personal data.
- robots.txt is respected.
trends.google.com/robots.txtdisallows exactly two paths, both forms of theexplore?page. This Actor never fetches them. Thelinkfields inside related-query results point at that disallowed page, so they are passed through to you as data and never followed. - Polite by design. A batch is many small sequential lookups, not a burst. Retries back off (about 2s, 6s, 15s) and rotate to a fresh IP and cookie jar rather than hammering. Every run has a request budget and a wall clock.
- Honest identification. The Actor identifies itself in its user agent. No browser fingerprint spoofing, no bot-detection circumvention of any kind.
- Limited permissions. The Actor needs no access to your account and collects no personal data.
Limitations worth knowing
- Related topics currently returns nothing. Google answers the related-topics surface with an
empty list for every keyword we have tested, including keywords first resolved to Knowledge Graph
entities — while related queries come back rich in the very same session and the very same
lookup. This is on Google's side, not ours. The surface is off by default, warns loudly when you
switch it on, reports
noDatainstead of failing, and is never charged for. It will start working by itself if Google restores it. Do not buy this Actor for related topics. - This Actor does not scrape "Trending Now" / daily trending searches. It is a keyword-explore tool: you bring the keywords. If you need the real-time trending feed, use a trending-searches Actor instead.
- Comparison mode crushes small terms, by design. A niche keyword next to a huge one lands in single digits, because that is what "relative to the biggest one" means. Use bulk mode if you want each keyword measured against itself.
- Metro (DMA) granularity is a US concept. It returns 210 metros for US locations and nothing
outside the US — the Actor says so in the row's
noDatareason rather than failing. - City granularity returns fewer rows than you might expect. Google only reports places with enough search volume to be statistically meaningful.
- Google's numbers are a relative index, not search volumes. 0–100 relative to the peak in your query. Nobody, including Google, publishes absolute Trends query counts.
- Trends data is sampled, so two runs of the same query can differ slightly. Pin the time zone
offset to
0if you want runs to line up as closely as possible. - The trailing bucket is usually incomplete. It is flagged
isPartial: trueand kept rather than silently dropped, because whether to use it is your call.
FAQ
Is scraping Google Trends legal?
This Actor reads the same public JSON endpoints that render the Google Trends website for any
visitor. It uses no login, solves no CAPTCHA, circumvents no bot detection, collects no personal
data, and respects trends.google.com/robots.txt. You are responsible for how you use the data,
including any licensing or attribution your own use requires.
Why do my numbers change between runs?
Google Trends is built on a sample of searches, so repeated queries can differ slightly. Pinning the
time zone offset to 0 makes runs line up as closely as possible.
Why is my keyword showing 0 or a single-digit value?
Almost always comparison mode. Next to a much larger term, a niche keyword is genuinely that small relative to it. Switch comparison off to measure each keyword against its own peak.
Can I get search volume numbers?
No — and neither can anyone else. Google publishes a relative 0–100 index only. Pair this with a keyword volume tool if you need absolute numbers.
How many keywords can I scrape at once?
Unlimited in bulk mode. Comparison mode is capped at 5, which is Google's own limit.
Can I export to CSV or Excel?
Yes — the dataset exports as JSON, CSV, Excel, XML or HTML, or you can pull it from the Apify API.
Does it support custom date ranges?
Yes: presets, a 2024-01-01 2024-12-31 date range, or an hourly 2024-01-01T00 2024-01-07T23
window. Invalid ranges are rejected before any request is made.
Will I be charged if Google returns nothing?
No. Billing counts parsed rows, not requests or HTTP status codes. Empty surfaces are written as
uncharged noData rows, and failed requests are never charged.
Other Actors by this developer
- Career Site Job Listings Scraper — turn any Greenhouse, Lever, Ashby or Workday careers URL into clean job data, every posting in one identical shape. Pay per job returned.
Support
Found a query that behaves oddly, or want a surface added? Open an issue on the Actor page with the exact input JSON — that is the fastest way to get it looked at.
For developers
npm installnpm run build # tscnpm run lintnpm test # vitest, no networknpx apify validate-schemanpm run start:dev # local run, reads storage/key_value_stores/default/INPUT.json
Source layout: src/input.ts (parse and validate into a RunConfig, pure), src/run.ts (the run
loop, network injected), src/charging.ts (the one function that decides whether a row is
billable), src/trends/* (a standalone Trends client: session and cookie handling, the explore
token dance, XSSI stripping, typed widget parsers, the retry and budget envelope).
../DEVLOG_TRENDS.md carries the full decision trail and every live measurement quoted above.