Google Trends Scraper API: Bulk, Compare, YouTube avatar

Google Trends Scraper API: Bulk, Compare, YouTube

Pricing

$4.00 / 1,000 per trends data rows

Go to Apify Store
Google Trends Scraper API: Bulk, Compare, YouTube

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.

Pricing

$4.00 / 1,000 per trends data rows

Rating

0.0

(0)

Developer

Nima K

Nima K

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

12 days ago

Last modified

Share

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.

Data surfaceWhat you get
Interest over timeThe trend line: one 0–100 value per time bucket per keyword, plus the period average.
Interest by regionWhere the searches come from — country, subregion, US metro area (Nielsen DMA), or city.
Related queriesWhat people also searched, split into top and rising, with Google's Breakout flag.
Search typesWeb, Images, News, Google Shopping and YouTube search — five separate trend curves.

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.

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.

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.

The same keyword often behaves nothing like its web curve on YouTube. Five search types are supported and each returns a distinct series:

Search typeWhat it measuresStatus
Web searchThe familiar Google Trends numbersVerified
YouTube searchSearches inside YouTubeVerified — distinct curve
News searchSearches inside Google NewsVerified — distinct curve
Image searchSearches inside Google ImagesSupported
Google ShoppingSearches inside Google ShoppingSupported

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:

Modecoffee (period average)matcha (period average)
Bulk (compare: false)7572
Comparison (compare: true, with tea)756

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.

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.

  1. Click Try for free and sign in to Apify.
  2. Type your search terms into Keywords, one per line.
  3. Set Location (empty means worldwide) and Time range (today 12-m is the default).
  4. Leave Compare keywords off to scrape a list; switch it on to put 2–5 terms on one scale.
  5. Tick only the data surfaces you need. Interest over time is on by default; every extra surface is an extra request to Google.
  6. Click Start. A two-keyword trend-line run takes about three seconds.
  7. 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"
}
SettingWhat it does
KeywordsOne search term per line. No limit in bulk mode; 2–5 in comparison mode.
Compare keywordsOff by default. On puts every keyword on one shared scale.
Interest over timeThe trend line. On by default; this is the surface most people want.
Interest by regionWhere the searches come from. Off by default. One extra request per lookup.
Related queriesWhat people also searched, top and rising. Off by default. One extra request per keyword.
Related topicsOff by default and currently returns nothing from Google — see Limitations. Never charged for.
LocationEmpty for worldwide, or US, GB, DE, US-NY, GB-ENG.
Time rangeA preset, a yyyy-mm-dd yyyy-mm-dd range, or an hourly yyyy-mm-ddThh range. Validated before any request.
Search typeWeb, Images, News, Google Shopping or YouTube search.
Region granularityAutomatic, country, subregion, metro area (DMA, US only) or city.
CategoryRestrict to one Trends category id — the clean way to separate "jaguar" the car (47) from "jaguar" the animal (66).
Proxy configurationDatacenter proxy by default, which is included in every Apify plan and is what we measured as fastest. Residential is one dropdown away.
Time zone offsetMinutes from UTC. 0 keeps results reproducible between runs — usually what you want for a dataset.
Max retriesRetries 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 }
]
}

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:

  • Pythonapify-client or plain requests against the Apify API.
  • Node.js / TypeScript — the official apify-client package.
  • 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.

$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.

SurfaceBulk mode (per keyword)Comparison mode (per set of 2–5)
Lookup (always needed)11 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.

Measured on the Apify platform, 9 August 2026:

RunRequestsRowsWall clock
2 keywords, interest over time, worldwide423.0 s
8 keywords, interest over time, US1688.0 s
3 keywords compared, + region (DMA) + related queries, US7521.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.txt disallows exactly two paths, both forms of the explore? page. This Actor never fetches them. The link fields 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 noData instead 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 noData reason 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 0 if you want runs to line up as closely as possible.
  • The trailing bucket is usually incomplete. It is flagged isPartial: true and kept rather than silently dropped, because whether to use it is your call.

FAQ

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 install
npm run build # tsc
npm run lint
npm test # vitest, no network
npx apify validate-schema
npm 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.