Proxies and rate limits

Google rate-limits Trends by exit IP. Rotate through a proxy pool, and understand why rotation happens per query rather than per request.

Using a proxy pool

Pass a list of proxy URLs and the client rotates through them automatically, moving to the next one whenever a query is refused:

import trendflow
from trendflow import Region

tf = trendflow.Client(
    proxies=[
        "http://user:pass@gate.decodo.com:7000",
        "http://user:pass@gate.decodo.com:7000",
    ],
    max_proxy_attempts=3,  # defaults to the pool size, capped at 5
    on_proxy_rotate=lambda attempt, error: print(f"rotated after {attempt}: {error!r}"),
)

trending = tf.trending_now(Region.US)
print(tf.current_proxy)  # the proxy that answered

Entries are just URLs, so a pool can mix providers. Repeating one rotating gateway also works: each entry gets its own connection, so it lands on a fresh exit IP.

Rotation happens per query, not per request — this matters. Google binds the NID cookie and the widget token to the IP that requested them, so a single query must complete on one exit IP; sending the follow-up widgetdata call from a different IP earns an instant 429. The pool pins one proxy for the whole query and advances only on failure, re-seeding the cookie jar each time. For the same reason, point the pool at sticky sessions rather than per-request rotating endpoints if your provider offers the choice.

Rotation is skipped for errors a different IP cannot fix, such as a 404 or a renamed RPC.

Where to get proxies

Residential proxies are what actually clears Google's 429. Verified against this library:

Decodo

ProviderNotesEndpoint format
Decodo (formerly Smartproxy)Cheapest entry tier; pay-as-you-go available. Used to verify this library's live tests.http://user:pass@gate.decodo.com:7000

Ask for sticky sessions when you sign up — per-request rotating endpoints break the cookie/token binding described above. Note that a shared residential pool can be exhausted for Google Trends specifically, in which case even a valid proxy returns 429; that is what max_proxy_attempts is for.