gnews-decoder
Turn news.google.com/rss/articles/CBMi... links into the publisher URLs behind
them — in one call for the whole list, not one call per article.
from gnews_decoder import from_rss, decode, decode_many
for item in from_rss("artificial intelligence"):
print(item["url"]) # https://www.economist.com/...
decode("https://news.google.com/rss/articles/CBMi...")
decode_many(urls) # {google_url: publisher_url or None}
pip install gnews-decoder
Measured against a live feed on 19 September 2026: 50 of 50 resolved in 6.8 seconds, using 50 signature requests and one decode call.
Why this exists
Google News links do not contain the destination. Until late 2024 the id after
/articles/ was base64 of a small protobuf with the URL inside, and every
library in this space decoded it offline with zero requests.
That format is gone. Of 30 ids taken from a live feed on 19 September 2026,
0 decoded offline and all 30 needed Google's batchexecute RPC. This is what
"base 64 deprecation" — the most-discussed open issue on the abandoned
pygooglenews — actually means, and
why so much code in this area quietly returns nothing.
Two other walls come with it, and this package handles both:
The consent interstitial. Without a recorded consent choice every article URL
302s to consent.google.com, and the page that comes back carries no signature.
That is the "returns a URL about Google Consent Mode" report that turns up in
every library's issue tracker. Measured: 0 of 6 signatures without the cookie,
6 of 6 with it. Pass consent_cookie= to supply your own.
Rate limiting. The obvious implementation issues one RPC per article and
Google starts answering 429 — which is why the alternatives' release notes are a
history of retry delays and proxy support. batchexecute takes every article in
a single POST; 50 resolve in about 0.8s of RPC time. That is the difference
between 100 requests and 51.
One more thing worth knowing, because it breaks scrapers: the HTML search page
at news.google.com/search answers 429 almost immediately, while
news.google.com/rss/search answers 200. from_rss uses the feed.
What it does not do
It does not give you the article text. The Google News feed carries headlines, links and timestamps — no body, not even a summary. Once you have the publisher URL you still have to fetch and extract it, and a meaningful share of publishers will not serve you: some want a subscription, some refuse the request outright. That is a separate and much harder problem, and this package does not pretend to solve it.
It also will not get you past the ~100-article ceiling per feed query, because that limit is Google's and no amount of decoding changes it.
API
decode(url, **kw) |
one URL → publisher URL, or None |
decode_many(urls, **kw) |
{original: resolved or None} — every input is a key, so a failure cannot silently misalign a zip against your own list |
from_rss(query, limit=50, **kw) |
search the feed and decode every link: {title, published, google_url, url} |
Keyword arguments: ceid (default "US:en"), concurrency (16), timeout
(20.0), consent_cookie, session.
If you need the text too
This package is the free half of a problem we spend our time on. If you want the article body, at scale, with the paywalled and blocked cases labelled rather than silently dropped, that is hawkcrawl — and the measurements behind all of the above, including the feed parameters Google does not document, are written up at hawkcrawl.com/google-news-rss.
You do not need it to use this. This works on its own and always will.
Licence
MIT.
Release files for gnews-decoder 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gnews_decoder-0.1.0.tar.gz | 7.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gnews_decoder-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.5 kB
Release files / gnews_decoder-0.1.0.tar.gz
| Download URL | gnews_decoder-0.1.0.tar.gz |
|---|---|
| Size | 7.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
095a60f5f698417ea153f37a8cd17bc923dec17853d29a9c4f7a69187e48c3e3
|
|
BLAKE2b-256 checksum How to use checksums |
948daae4037a53f78f9fe9cf0585ada3055ed5dd2f1a6b4e6ac73df5ad6adfdf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.5
|
Release files / gnews_decoder-0.1.0-py3-none-any.whl
| Download URL | gnews_decoder-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b99d9db5072fe5c1b7d40ba074f6896b21985cfa4ec598a6e926cbad02edc2de
|
|
BLAKE2b-256 checksum How to use checksums |
e4c45d542b0760078fb4aa66d3da6afe19e66c6048ab19a6a25f708584c414f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.5
|