TL;DR: Every link in a Google News RSS feed points to news.google.com/rss/articles/CBMi..., not to the publisher. Until July 2024 you could base64-decode the ID and read the URL inside. That stopped working. Today the ID holds an opaque token, and resolving it takes a page fetch plus a call to Google's internal batchexecute endpoint. Loop that over a few dozen articles and people report HTTP 429. You can do it yourself with a free library, or pay about $0.001 per article and get the URL in the same row as the headline. Code for both is below.

What the feed gives you

Search Google News over RSS:

https://news.google.com/rss/search?q=amadeus+api&hl=en-US&gl=US&ceid=US:en 

Each <item> has a title, a source, a date and a link like this one:

https://news.google.com/rss/articles/CBMihwFBVV95cUxNaUJGcmZlVjJPc18tQkRFd3BUeTBMZGZSOFhQaUZOMGpWR25JQ3M4WnVtR2EwdlBmZWdoTXVQTjRWc3BxcU93NC1XZTl5VTJRYkhFZzFsQW5QeWZoN1JVczljWVIzMU9DdlVWYXBrRUY3c2ZiU003VjUxQm1ManJfTnpSZTlzZkE?oc=5 

That's a PhocusWire article about Amadeus. Nothing in the link says PhocusWire. If you want to dedupe by URL, fetch the article text, or group coverage by domain, you need the real URL first.

The base64 trick, and why it stopped working

For years the answer on Stack Overflow and in blog posts was: take the part after /articles/, base64-decode it, strip a few bytes, and there's your URL. It worked because the ID was a small protobuf with the URL stored in plain text.

In late July 2024 Google changed the format. A Stack Overflow question from 25 July 2024 (about 3,800 views) says the base64 method "worked perfectly until Google recently changed the structure". The same day, users of the most popular decoder library opened an issue saying it had stopped working.

You can see the change offline. Decode the ID above:

import base64 gid = "CBMihwFBVV95cUxNaUJGcmZlVjJPc18tQkRFd3BUeTBMZGZSOFhQaUZOMGpWR25JQ3M4WnVtR2EwdlBmZWdoTXVQTjRWc3BxcU93NC1XZTl5VTJRYkhFZzFsQW5QeWZoN1JVczljWVIzMU9DdlVWYXBrRUY3c2ZiU003VjUxQm1ManJfTnpSZTlzZkE" raw = base64.urlsafe_b64decode(gid + "=" * (-len(gid) % 4)) print(raw[:4], raw[4:40]) 
b'\x08\x13"\x87' b'\x01AU_yqLMiBFrfeV2Os_-BDEwpTy0LdfR8XPi' 

The protobuf wrapper is still there. Inside it there's now a token starting with AU_yqL, not https://. No amount of decoding turns that into a URL. Only Google can.

What decoding takes now

The method every working decoder uses today, including the one in my Actor, is the one the Google News web app uses itself:

Step Request What you get
1 GET news.google.com/rss/articles/<id> An HTML page. No redirect header. It carries two attributes, data-n-a-ts (a timestamp) and data-n-a-sg (a signature)
2 POST news.google.com/_/DotsSplashUi/data/batchexecute with garturlreq, the id, the timestamp and the signature A JSON-ish response with the publisher URL

So one headline from the feed costs you two more requests to Google. Step 2 can carry several articles in one call. Step 1 can't; it's one page per article.

Volume is where it gets hard. In the decoder library's issue #3 (20 comments, August 2024), a user reports a 429 after looping about 50 times, and others confirm "Google News is being strict now". The common advice there is to slow down. Respect that. It's Google's server, and a 429 is a clear signal.

Option 1: do it yourself, free

googlenewsdecoder implements the two steps above. It's maintained (version 0.2.2, released 18 October 2026) and widely used: 387,792 downloads in the last month on pypistats as of 15 November 2026.

pip install googlenewsdecoder 

It fits well if you resolve a handful of links a day, from one machine, and can wait between requests. You own the retries and the pacing, and you'll need to update when Google changes the page again.

Option 2: a hosted scraper

Google News Scraper on Apify reads the RSS feed and resolves publisher URLs in the same run. It batches step 2 (one batchexecute call per 10 articles), retries failures, and runs on Apify's proxies, not your IP.

Disclosure: I built this. It costs $0.001 per article ($1 per 1,000) on Apify's free plan and less on paid plans, publisher URL included. Failed feeds aren't charged. Apify's free plan includes $5 of credit a month.

With apify-client 3.x (pip install apify-client):

import os from apify_client import ApifyClient client = ApifyClient(os.environ["APIFY_TOKEN"]) run = client.actor("kuezi/google-news-scraper").call(logger=None, run_input={ "queries": ["Amadeus API"], "language": "en", "country": "US", "timeRange": "30d", "maxArticlesPerQuery": 10, "decodeUrls": True, }) for a in client.dataset(run.default_dataset_id).iterate_items(): print(a["publishedAt"][:10], "|", a["publisher"]) print(" rss: ", a["googleNewsUrl"][:60] + "...") print(" real:", a["articleUrl"]) print(run.status_message) 

Output from a real run on 15 November 2026:

2026-11-08 | Skift rss: https://news.google.com/rss/articles/CBMikAFBVV95cUxNQVFGbVZ... real: https://skift.com/2026/11/08/ai-agents-still-need-middlemen-but-will-they-need-amadeus/ 2026-11-06 | CISO Series rss: https://news.google.com/rss/articles/CBMisAFBVV95cUxNSjdHZnJ... real: https://cisoseries.com/the-department-of-know-llm-jacking-asia-rocked-by-amadeus-freezers-still-getting-hacked/ 2026-11-04 | The Star rss: https://news.google.com/rss/articles/CBMizgFBVV95cUxNVlo0Wll... real: https://www.thestar.com.my/business/business-news/2026/11/04/singapore-airlines-says-46000-booking-records-affected-by-amadeus-breach 2026-11-02 | The Star rss: https://news.google.com/rss/articles/CBMiywFBVV95cUxQNlpHUmN... real: https://www.thestar.com.my/business/business-news/2026/11/02/malaysia-airlines-says-customer-data-may-be-affected-by-amadeus-breach 2026-10-29 | BigGo Finance rss: https://news.google.com/rss/articles/CBMidkFVX3lxTE9jSnNWQUM... real: https://finance.biggo.com/news/1a7a0087-3f54-4130-ba2a-eeec154210ee Saved 5 articles from 1 search(es). "Amadeus API": 5 articles (2026-10-29 to 2026-11-08); top sources The Star 2, Skift 1, CISO Series 1; newest "AI Agents Still Need Middlemen. But Will They Need Amadeus?" (Skift). 

That run took about 7 seconds end to end and resolved 5 of 5 publisher URLs. Google News only had 5 items for that query in the last 30 days, so it billed $0.005. The last line is the run's status message, which is also what an AI agent sees when it calls the Actor through Apify's MCP server.

Two more things the RSS feed won't do on its own:

  • Past the 100-item cap. One Google News RSS search returns at most 100 items. Set dateFrom and dateTo, and the Actor searches one day at a time and removes duplicates. In a test, "bitcoin" over 6 days returned 400 unique articles in 15 seconds.
  • Only new articles. Turn on onlyNewArticles, save the input as a task and schedule it. Each run returns only articles earlier runs didn't see, which is what you want for brand alerts.

There's a ready-made task to monitor new articles about a brand.

What this doesn't give you

  • Article text. Both options give you the URL. Fetching and parsing the article is a separate step, and the publisher's terms apply.
  • Everything published. Google News lists what it chooses to index. Small outlets can be missing, and results differ by edition.
  • Exact times. Some publication dates in the feed are rounded to the hour or day.
  • A licence. The RSS feed itself says it's provided "for personal, non-commercial use". If you're building a commercial news product, read Google's terms and consider a licensed news API.

If Google changes the format again, this post will get an update. If you find a lighter way to resolve these links, post it in the comments.

AI disclosure: I wrote this with AI assistance. Every quote, number and output above was checked or run on 15 November 2026.