# Google Trends API Python: ~4.6s Typical (Was ~9s) (https://www.socialcrawl.dev/blog/google-trends-api-faster) > A Google Trends API Python GET is ~4.6s typical (was ~9s on 22 billed calls). Live interest-over-time and related queries, same 5 credits, 2026-09-08 UTC. A Google Trends API Python GET now typically returns in **~4.6s** on a billed miss (was **~9s**). That was measured on production across **22 billed calls** after 2026-09-07. Credits stayed **5**. Interest-over-time (`GET /v1/google_trends/explore`) and related/rising (`GET /v1/google_trends/rising`) share that contract. Google [announced a Trends API alpha on 24 Jul 2025](https://developers.google.com/search/blog/2025/07/trends-api). Access is apply-only for limited testers — not a public REST key. [pytrends](https://pypi.org/project/pytrends/) is the unofficial pandas library people already `pip install` — last release 13 Apr 2023, looking for maintainers. You call it with `x-api-key` and a GET. Which Google Trends API to pick, and what it costs, is on [best Google Trends APIs 2026](/blog/best-google-trends-apis-2026). This post is the speed change and how to call `explore` / `rising`. **Stack:** Python 3 · `requests` · `GET https://www.socialcrawl.dev/v1/google_trends/explore` and `/v1/google_trends/rising` · header `x-api-key`. JSON is trimmed from a 2026-09-08 production harvest on the SocialCrawl API — not a screenshot, not a DataFrame stub. A free 404 and a free 400 are in here too, so a dead keyword does not look like a timeout. A cream isometric line-chart slab with one rising clay-amber curve, the interest-over-time series a Google Trends API Python GET returns. ## How do you pull Google Trends interest over time in Python? `GET /v1/google_trends/explore` is the Google Trends interest over time API. Pass 1–5 keywords, an optional `location`, and a `timeframe`. The response is dated `series` plus per-keyword `averages` on Google's relative 0–100 index, not search volume. The request is one GET. No SDK. This Google Trends API Python example compares three US terms over `past_12_months` (the default window). Harvest row `#2`, 2026-09-08, cache miss, `request_id` `req-xyaesW1MDftWKcMP`. HTTP 200, **5 credits**, **6,751 ms**. ```python BASE = "https://www.socialcrawl.dev" r = requests.get( f"{BASE}/v1/google_trends/explore", params={ "keywords": "oat milk,almond milk,soy milk", "location": "US", "timeframe": "past_12_months", }, headers={"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]}, timeout=90, ) r.raise_for_status() payload = r.json() print(payload["credits_used"], payload["data"]["averages"]) # 5, oat milk 51 / almond milk 68 / soy milk 24 ``` Curl twin of the same GET: ```bash curl -s --max-time 90 -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/google_trends/explore?keywords=oat%20milk,almond%20milk,soy%20milk&location=US&timeframe=past_12_months" ``` Trimmed envelope from that call (three series × **53** weekly points; first and last bucket only): ```json { "success": true, "data": { "averages": [ { "keyword": "oat milk", "value": 51 }, { "keyword": "almond milk", "value": 68 }, { "keyword": "soy milk", "value": 24 } ], "series": [ { "keyword": "oat milk", "points": [ { "date": "2025-09-07", "value": 43, "partial": false }, { "date": "2026-09-06", "value": 60, "partial": true } ] }, { "keyword": "almond milk", "points": [ { "date": "2025-09-07", "value": 56, "partial": false }, { "date": "2026-09-06", "value": 71, "partial": true } ] }, { "keyword": "soy milk", "points": [ { "date": "2025-09-07", "value": 18, "partial": false }, { "date": "2026-09-06", "value": 22, "partial": true } ] } ] }, "credits_used": 5, "request_id": "req-xyaesW1MDftWKcMP" } ``` Read the averages as **one** 0–100 scale across the set. Almond milk 68, oat milk 51, soy milk 24. Those three numbers are comparable **only inside this call**. Almond milk is the only term that hits **100** (week of 2026-04-12). Soy milk never exceeds **36** in the full series. That is the normalisation proof: three terms, one request, directly comparable. Two separate explores are not comparable. [Google's own FAQ](https://support.google.com/trends/answer/4365533) is blunt about this — a point is a share of searches in that geography and window, scaled 0–100, not a headcount. The envelope also carries `success`, `platform`, `endpoint`, `credits_used`, and `request_id`. `credits_used` is **5** on a billed miss. Drop the last bucket before you chart: every explore series in this harvest set `partial: true` on the week of 2026-09-06 (still counting). Same object, one term. `keywords=solid state battery` (`req-T98bfg3d2yGqBi4r`) returned 53 points, average **42**, peak **100** the week of 2026-06-07, min **17** on 2025-09-28. **7,284 ms**, 5 credits, cache miss. Same `series` / `averages` shape. Swap the `keywords` param; do not learn a second schema. Caveats that bite in practice: - Relative index ≠ search volume. Almond milk at 68 does not mean 68 searches. - 1–5 keywords. More than five is a free 400. - `location` accepts ISO (`US`, `KR`), the full country name as Trends spells it (`South Korea`), or a numeric code. Default leans worldwide-US. - Default `timeframe` is `past_12_months`. Eight presets, no arbitrary date range. ## How do you get Google Trends related queries from an API? `GET /v1/google_trends/rising` returns `rising` and `top` for **one** keyword. The resource name is `rising`, not `related-queries`. Google's alpha announcement is about consistently scaled interest data, not related-query lists. This path is the related queries API: breakouts with a percent `growth`, plus the most-searched related queries on a 0–100 `value`. Rising is the list you want when a term is about to move — breakouts that are not yet large enough to dominate the interest-over-time series. Top is where demand is concentrated right now. The param is **`keyword` (singular)**. A comma-separated list is a free 400. Usual order: `explore` to size the series, then `rising` on the winner. Harvest row `#4`. `keyword=solid state battery`, US, `past_12_months`. HTTP 200, **5 credits**, **19,059 ms**, cache miss, `req-JmaL2ZAMP0bYaoVT`. 15 rising rows (numeric `growth` on **7** of 15), 25 top rows. ```python r = requests.get( f"{BASE}/v1/google_trends/rising", params={ "keyword": "solid state battery", "location": "US", "timeframe": "past_12_months", }, headers={"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]}, timeout=90, ) r.raise_for_status() payload = r.json() print( payload["credits_used"], len(payload["data"]["rising"]), len(payload["data"]["top"]), ) # 5, 15, 25 ``` ```bash curl -s --max-time 90 -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/google_trends/rising?keyword=solid%20state%20battery&location=US&timeframe=past_12_months" ``` Trimmed body. Numeric growth kept; two `null`s left as Google sent them: ```json { "success": true, "data": { "rising": [ { "query": "donut battery", "growth": null }, { "query": "donut lab", "growth": null }, { "query": "solid state portable battery", "growth": 650 }, { "query": "solid state drive", "growth": 500 }, { "query": "silver solid state battery", "growth": 200 }, { "query": "solid state battery phone", "growth": 200 }, { "query": "samsung solid state battery", "growth": 180 } ], "top": [ { "query": "solid state drive", "value": 100 }, { "query": "what is solid state battery", "value": 64 }, { "query": "solid power", "value": 59 }, { "query": "solid state battery toyota", "value": 57 }, { "query": "samsung solid state battery", "value": 56 } ] }, "credits_used": 5, "request_id": "req-JmaL2ZAMP0bYaoVT" } ``` `rising[].growth` is percent growth. A true breakout can read into the thousands; this harvest's max is **+650** (`solid state portable battery`), then **+500**, **+200**, **+200**, **+180**. Eight of the 15 rising rows came back `growth: null`. Google omitted the number; the envelope carries `_warnings` for those. Do not fill them in. `top[].value` is 0–100 relative. `solid state drive` at 100 is the related-query ceiling in this window, not a volume count. This rising call was **19.1s** on this run — that number belongs with the n=4 session below, not as the production typical. A blank stopwatch dial with one clay-amber needle, the elapsed wait on a Google Trends API Python call. ## How long does a Google Trends API Python call take? Typical billed call is **~4.6s** now (was **~9s**), measured on **22 billed calls** after 2026-09-07. Two tables. Do not mix them. Production claim, **22 billed calls** after 2026-09-07: | Fact | Before → after (22 billed calls, 2026-09-07) | | --- | --- | | Typical billed call | **~9s → ~4.6s** | | Slow tail | **p95 ~47s → ~12s** as the worst of those 22 | | Timeouts | **273 of 19,459** over 30 days, each after **~48s** → now rare | | Unchanged | Same params, same shape, same **5 credits**, same free **400** / **404** | This Google Trends Python API run, **n=4** cache-miss billed calls on 2026-09-08 (window 00:23:27Z–00:26:45Z), all 5 credits: | Call | latency | | --- | ---: | | explore multi (`oat milk,almond milk,soy milk`, US) | **6.8s** (6,751 ms) | | explore single (`solid state battery`, US) | **7.3s** (7,284 ms) | | rising (`solid state battery`, US) | **19.1s** (19,059 ms) | | explore Hangul (`선풍기`, South Korea) | **19.7s** (19,745 ms) | US English explore answered in ~7s. Hangul and rising sat near **19s** — **slower than the 22-call worst of ~12s**, on a sample of four. Still inside a 60s client timeout; not a 48s timeout failure. Cold, non-English and non-US terms are where the update shows most. Do not overwrite the production table with a four-call mean. Captured call, harvest `#3`. `keywords=선풍기` (electric fan), `location=South Korea`, `past_12_months`. 53 points, average **21**, winter floor **4** (week of 2026-02-15), summer peak **100** (week of 2026-07-26), last point 13 `partial: true`. **19,745 ms**, 5 credits, cache miss, `req-PIzuSdK1giC8D5Zw`. ```python r = requests.get( f"{BASE}/v1/google_trends/explore", params={ "keywords": "선풍기", "location": "South Korea", "timeframe": "past_12_months", }, headers={"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]}, timeout=90, ) r.raise_for_status() payload = r.json() print(payload["credits_used"], payload["data"]["averages"][0]["value"]) # 5, 21 ``` ```json { "success": true, "data": { "series": [ { "keyword": "선풍기", "points": [ { "date": "2025-09-07", "value": 18, "partial": false }, { "date": "2026-02-15", "value": 4, "partial": false }, { "date": "2026-07-26", "value": 100, "partial": false }, { "date": "2026-09-06", "value": 13, "partial": true } ] } ], "averages": [{ "keyword": "선풍기", "value": 21 }] }, "credits_used": 5, "request_id": "req-PIzuSdK1giC8D5Zw" } ``` A seasonal series is the easy read: winter 4, July 100, window average 21. The latency is not tidy. 19.7s is not ~4.6s. The upgrade note says this lane improved most; this one pull, on a sample of four, was still the slowest billed call of the morning. Empty interest is a **404** at **0 credits**, and that 404 can be slow. `keywords=zzqxjbv7wmpl3nonsense99` explore took **52,918 ms**, `req-Q2kdMXZn17dS9X6l`. That is a fallback confirming no data, not a billed timeout. The message names that location and timeframe were accepted, so you know it is the keyword. Some nonsense strings return a sparse 200 and get billed 5 — only the 404 that actually 404'd is below. The matching rising 404 (`req-JSVh0G2ZHHUy7YbJ`) is the same contract: 0 credits, 11.7s. ```json { "success": false, "error": { "type": "RESOURCE_NOT_FOUND", "message": "No search-interest data were returned for this keyword. The location and timeframe were accepted; Google Trends simply holds too little search volume for this keyword in that combination to build a result. Try a wider `timeframe`, a broader keyword, or the keyword in the local language of the location you requested. You were not charged for this request.", "status": 404, "doc_url": "https://www.socialcrawl.dev/docs/errors#resource-not-found" }, "credits_used": 0, "request_id": "req-Q2kdMXZn17dS9X6l" } ``` Bad location is a **400** at **0 credits**, and it is fast. `location=Atlantis` returned in **413 ms**, `req-xOeHKo1Bw5ZaRyJP`. The message names ISO / full name / numeric forms so the caller knows it is the location, not the keyword. Error taxonomy: [`/docs/errors`](/docs/errors). ```json { "success": false, "error": { "type": "INVALID_REQUEST", "message": "Google Trends did not recognise one of the request parameters. `location` must be an ISO country code (\"KR\", \"US\"), the full country name as Google Trends spells it (\"South Korea\", \"United States\"), or a numeric location code (\"2410\"). Google Trends does not publish every country, so a location it has no data for is refused here as well. `category` must be a numeric Google Trends category code. Your credits have been refunded.", "status": 400, "doc_url": "https://www.socialcrawl.dev/docs/errors#invalid-request" }, "credits_used": 0, "request_id": "req-xOeHKo1Bw5ZaRyJP" } ``` Cache hits are free and millisecond-fast. None of the billed four were hits (`cached: false` on every success). Set the client timeout **≥60s** (this harvest used 90). Credits stayed **5** across the speed change. ## How do you use a Google Trends API from Python? You send header `x-api-key` and one GET. No SDK, no OAuth. 1. Get a key. Sign up; new accounts get 100 free credits. Send it as header `x-api-key` only — no OAuth, no query-string key. Auth notes: [`/docs/authentication`](/docs/authentication). That is **one API key** for both GETs above. 2. Copy the first `requests` block. Print `credits_used` and the `averages` array. Set timeout to 90. 3. Named timeframes: `past_hour`, `past_4_hours`, `past_day`, `past_7_days`, `past_30_days`, `past_90_days`, `past_12_months` (default, what the harvest used), `past_5_years`. No arbitrary date range. `past_hour` / `past_4_hours` are minute-level; `past_5_years` is weekly. 4. Next: [Google Trends endpoint docs](/docs/google_trends) for the field map, and [try the same call in the explorer](/platforms/google_trends). Responses sit on **the unified schema** — a `dev.socialcrawl` envelope, not a one-off Trends dump. That docs page is the Google Trends API documentation for these two paths. This post is the live harvest, not a second copy of it. ## Frequently asked questions ### How long does a Google Trends API take? Typical billed call is **~4.6s** now (was **~9s**), measured on **22 billed calls** after 2026-09-07. A four-call production check on 2026-09-08 landed 6.8s–19.7s depending on the term — that table is "this run", not the typical. ### Why did the Google Trends API timeout? **273 of 19,459** calls over 30 days died after **~48s**. Slow tail on the 22 billed calls after the change was **~12s** worst-case. Timeouts are rare, not gone. Empty-interest 404s can still sit near 50s at **0 credits** — that is not a billed timeout. Use a client timeout ≥60s. ### Is there an official Google Trends API? Yes. Google announced a Trends API **alpha** on **24 Jul 2025**, limited testers, apply-form access, not a drop-in public REST key. SocialCrawl is a public `x-api-key` GET returning website-style 0–100 series. For which-API / pricing, see [best Google Trends APIs 2026](/blog/best-google-trends-apis-2026). ### How do you call a Google Trends related queries API? `GET /v1/google_trends/rising?keyword=…` returns `rising` and `top` for one keyword. Resource is `rising`. 5 credits on a billed miss. `keyword` is singular. ### Did credits or the response shape change? No. Same params, same shape, same **5 credits**, same free 400s and free 404s. ### Do you need pytrends to call a Google Trends API from Python? No. One Google Trends API Python GET with `x-api-key`. pytrends is an unofficial library (pandas, last release Apr 2023); it is not a dependency, and this is not a wrapper around it. ### Where is the Google Trends API documentation? [Google Trends endpoint docs](/docs/google_trends) for params and field maps. [Try the same call in the explorer](/platforms/google_trends) against production. The field map lives there — this post does not copy it. Rerun any harvest row with your own key. A cache miss on `explore` or `rising` is 5 credits. A 400 or empty-interest 404 is 0. That is the whole Google Trends API Python path: two GETs, same 5 credits, same shape as this harvest.